git.delta.rocks / unique-network / refs/commits / d8467f134b10

difftreelog

Merge branch 'develop' into tests/generalization

Max Andreev2023-01-17parents: #f37b77a #2991c90.patch.diff
in: master

41 files changed

modified.docker/Dockerfile-chain-devdiffbeforeafterboth
1FROM ubuntu:20.041FROM uniquenetwork/services:latest
22
3ARG RUST_TOOLCHAIN3ARG RUST_TOOLCHAIN
4ARG NETWORK4ARG NETWORK
1111
12RUN echo "$NETWORK\n" && echo "$RUST_TOOLCHAIN\n"12RUN echo "$NETWORK\n" && echo "$RUST_TOOLCHAIN\n"
1313
14RUN apt-get update && apt-get install -y git curl libssl-dev llvm pkg-config libclang-dev clang git make cmake protobuf-compiler
15
16RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
17
18RUN rustup toolchain uninstall $(rustup toolchain list) && \14RUN rustup toolchain uninstall $(rustup toolchain list) && \
19 rustup toolchain install $RUST_TOOLCHAIN && \15 rustup toolchain install $RUST_TOOLCHAIN && \
20 rustup default $RUST_TOOLCHAIN && \16 rustup default $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-chain-dev-unitdiffbeforeafterboth
1FROM ubuntu:20.041FROM uniquenetwork/services:latest
22
3ENV DEBIAN_FRONTEND=noninteractive3ENV DEBIAN_FRONTEND=noninteractive
4ENV TZ=Etc/UTC
5
6RUN apt-get update && apt-get install -y git curl libssl-dev llvm pkg-config libclang-dev clang git make cmake protobuf-compiler
7
8ENV CARGO_HOME="/cargo-home"4ENV CARGO_HOME="/cargo-home"
9ENV PATH="/cargo-home/bin:$PATH"5ENV PATH="/cargo-home/bin:$PATH"
10
11RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
126
13ARG RUST_TOOLCHAIN7ARG RUST_TOOLCHAIN
14ARG NETWORK8ARG NETWORK
modified.docker/Dockerfile-parachaindiffbeforeafterboth
2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot
33
4# ===== Rust builder =====4# ===== Rust builder =====
5FROM ubuntu:20.04 as rust-builder5FROM uniquenetwork/services:latest as rust-builder
6LABEL maintainer="Unique.Network"
7
8ARG RUST_TOOLCHAIN=6ARG RUST_TOOLCHAIN=
9ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN7ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
108
11ENV CARGO_HOME="/cargo-home"9ENV CARGO_HOME="/cargo-home"
12ENV PATH="/cargo-home/bin:$PATH"10ENV PATH="/cargo-home/bin:$PATH"
13ENV TZ=UTC11ENV TZ=UTC
14RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
15
16RUN apt-get update && \
17 apt-get install -y curl cmake pkg-config libssl-dev git clang protobuf-compiler && \
18 apt-get clean && \
19 rm -r /var/lib/apt/lists/*
20
21RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
22
23RUN rustup toolchain uninstall $(rustup toolchain list) && \12RUN rustup toolchain uninstall $(rustup toolchain list) && \
24 rustup toolchain install $RUST_TOOLCHAIN && \13 rustup toolchain install $RUST_TOOLCHAIN && \
25 rustup default $RUST_TOOLCHAIN && \14 rustup default $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-parachain-node-onlydiffbeforeafterboth
2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot
33
4# ===== Rust builder =====4# ===== Rust builder =====
5FROM ubuntu:20.04 as rust-builder5FROM uniquenetwork/services:latest as rust-builder
6LABEL maintainer="Unique.Network"
76
8ARG RUST_TOOLCHAIN=7ARG RUST_TOOLCHAIN=
9
10ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN8ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
11ENV CARGO_HOME="/cargo-home"9ENV CARGO_HOME="/cargo-home"
12ENV PATH="/cargo-home/bin:$PATH"10ENV PATH="/cargo-home/bin:$PATH"
13ENV TZ=UTC11ENV TZ=UTC
14RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
15
16RUN apt-get update && \
17 apt-get install -y curl cmake pkg-config libssl-dev git clang protobuf-compiler && \
18 apt-get clean && \
19 rm -r /var/lib/apt/lists/*
20
21RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
22
23RUN rustup toolchain uninstall $(rustup toolchain list) && \12RUN rustup toolchain uninstall $(rustup toolchain list) && \
24 rustup toolchain install $RUST_TOOLCHAIN && \13 rustup toolchain install $RUST_TOOLCHAIN && \
25 rustup default $RUST_TOOLCHAIN && \14 rustup default $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-parachain-upgradediffbeforeafterboth
2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot
33
4# ===== Rust builder =====4# ===== Rust builder =====
5FROM ubuntu:20.04 as rust-builder5FROM uniquenetwork/services:latest as rust-builder
6LABEL maintainer="Unique.Network"
76
8ARG RUST_TOOLCHAIN=7ARG RUST_TOOLCHAIN=
98
10ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN9ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
11ENV CARGO_HOME="/cargo-home"10ENV CARGO_HOME="/cargo-home"
12ENV PATH="/cargo-home/bin:$PATH"11ENV PATH="/cargo-home/bin:$PATH"
13ENV TZ=UTC12ENV TZ=UTC
14RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
15
16RUN apt-get update && \
17 apt-get install -y curl cmake pkg-config libssl-dev git clang protobuf-compiler && \
18 apt-get clean && \
19 rm -r /var/lib/apt/lists/*
20
21RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
22
23RUN rustup toolchain uninstall $(rustup toolchain list) && \13RUN rustup toolchain uninstall $(rustup toolchain list) && \
24 rustup toolchain install $RUST_TOOLCHAIN && \14 rustup toolchain install $RUST_TOOLCHAIN && \
25 rustup default $RUST_TOOLCHAIN && \15 rustup default $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-parachain-upgrade-datadiffbeforeafterboth
2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot2FROM uniquenetwork/builder-polkadot:${POLKADOT_BUILD_BRANCH} as polkadot
33
4# ===== Rust builder =====4# ===== Rust builder =====
5FROM ubuntu:20.04 as rust-builder5FROM uniquenetwork/services:latest as rust-builder
6LABEL maintainer="Unique.Network"
7
8ARG RUST_TOOLCHAIN=6ARG RUST_TOOLCHAIN=
97
10ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN8ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
11ENV CARGO_HOME="/cargo-home"9ENV CARGO_HOME="/cargo-home"
12ENV PATH="/cargo-home/bin:$PATH"10ENV PATH="/cargo-home/bin:$PATH"
13ENV TZ=UTC11ENV TZ=UTC
14RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
15
16RUN apt-get update && \
17 apt-get install -y curl cmake pkg-config libssl-dev git clang protobuf-compiler && \
18 apt-get clean && \
19 rm -r /var/lib/apt/lists/*
20
21RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
2212
23RUN rustup toolchain uninstall $(rustup toolchain list) && \13RUN rustup toolchain uninstall $(rustup toolchain list) && \
24 rustup toolchain install $RUST_TOOLCHAIN && \14 rustup toolchain install $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-testnet.j2diffbeforeafterboth
1# ===== Rust builder =====1# ===== Rust builder =====
2FROM ubuntu:20.04 as rust-builder2FROM uniquenetwork/services:latest as rust-builder
3LABEL maintainer="Unique.Network"3ARG RUST_TOOLCHAIN=
44
5ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
5ENV CARGO_HOME="/cargo-home"6ENV CARGO_HOME="/cargo-home"
6ENV PATH="/cargo-home/bin:$PATH"7ENV PATH="/cargo-home/bin:$PATH"
7ENV TZ=UTC8ENV TZ=UTC
8RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
99
10RUN apt-get update && \
11 apt-get install -y curl cmake pkg-config libssl-dev git clang llvm libudev-dev protobuf-compiler && \
12 apt-get clean && \
13 rm -r /var/lib/apt/lists/*
14
15RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
16
17RUN rustup toolchain uninstall $(rustup toolchain list) && \10RUN rustup toolchain uninstall $(rustup toolchain list) && \
18 rustup toolchain install {{ RUST_TOOLCHAIN }} && \11 rustup toolchain install {{ RUST_TOOLCHAIN }} && \
19 rustup default {{ RUST_TOOLCHAIN }} && \12 rustup default {{ RUST_TOOLCHAIN }} && \
modified.docker/Dockerfile-try-runtimediffbeforeafterboth
1# ===== Rust builder =====1# ===== Rust builder =====
2FROM ubuntu:20.04 as rust-builder2FROM uniquenetwork/services:latest as rust-builder
3LABEL maintainer="Unique.Network"
43
5ARG RUST_TOOLCHAIN4ARG RUST_TOOLCHAIN
65
7ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN6ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
8ENV CARGO_HOME="/cargo-home"7ENV CARGO_HOME="/cargo-home"
9ENV PATH="/cargo-home/bin:$PATH"8ENV PATH="/cargo-home/bin:$PATH"
10ENV TZ=UTC9ENV TZ=UTC
11RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
1210
13
14RUN apt-get update && \
15 apt-get install -y curl cmake pkg-config libssl-dev git clang protobuf-compiler && \
16 apt-get clean && \
17 rm -r /var/lib/apt/lists/*
18
19RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
20
21RUN rustup toolchain uninstall $(rustup toolchain list) && \11RUN rustup toolchain uninstall $(rustup toolchain list) && \
22 rustup toolchain install $RUST_TOOLCHAIN && \12 rustup toolchain install $RUST_TOOLCHAIN && \
23 rustup default $RUST_TOOLCHAIN && \13 rustup default $RUST_TOOLCHAIN && \
modified.docker/Dockerfile-xcm.j2diffbeforeafterboth
1# ===== Rust builder =====1# ===== Rust builder =====
2FROM ubuntu:20.04 as rust-builder2FROM uniquenetwork/services:latest as rust-builder
3LABEL maintainer="Unique.Network"
4
5ENV CARGO_HOME="/cargo-home"3ENV CARGO_HOME="/cargo-home"
6ENV PATH="/cargo-home/bin:$PATH"4ENV PATH="/cargo-home/bin:$PATH"
7ENV TZ=UTC5ENV TZ=UTC
8RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
9
10RUN apt-get update && \
11 apt-get install -y curl cmake pkg-config libssl-dev git clang llvm libudev-dev protobuf-compiler && \
12 apt-get clean && \
13 rm -r /var/lib/apt/lists/*
14
15RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
166
17RUN rustup toolchain uninstall $(rustup toolchain list) && \7RUN rustup toolchain uninstall $(rustup toolchain list) && \
18 rustup toolchain install {{ RUST_TOOLCHAIN }} && \8 rustup toolchain install {{ RUST_TOOLCHAIN }} && \
modifiedCargo.lockdiffbeforeafterboth
23402340
2341[[package]]2341[[package]]
2342name = "evm-coder-procedural"2342name = "evm-coder-procedural"
2343version = "0.2.2"2343version = "0.2.3"
2344dependencies = [2344dependencies = [
2345 "Inflector",2345 "Inflector",
2346 "hex",2346 "hex",
2467[[package]]2467[[package]]
2468name = "fc-consensus"2468name = "fc-consensus"
2469version = "2.0.0-dev"2469version = "2.0.0-dev"
2470source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2470source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2471dependencies = [2471dependencies = [
2472 "async-trait",2472 "async-trait",
2473 "fc-db",2473 "fc-db",
2486[[package]]2486[[package]]
2487name = "fc-db"2487name = "fc-db"
2488version = "2.0.0-dev"2488version = "2.0.0-dev"
2489source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2489source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2490dependencies = [2490dependencies = [
2491 "fp-storage",2491 "fp-storage",
2492 "kvdb-rocksdb",2492 "kvdb-rocksdb",
2505[[package]]2505[[package]]
2506name = "fc-mapping-sync"2506name = "fc-mapping-sync"
2507version = "2.0.0-dev"2507version = "2.0.0-dev"
2508source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2508source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2509dependencies = [2509dependencies = [
2510 "fc-db",2510 "fc-db",
2511 "fp-consensus",2511 "fp-consensus",
2522[[package]]2522[[package]]
2523name = "fc-rpc"2523name = "fc-rpc"
2524version = "2.0.0-dev"2524version = "2.0.0-dev"
2525source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2525source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2526dependencies = [2526dependencies = [
2527 "ethereum 0.14.0",2527 "ethereum 0.14.0",
2528 "ethereum-types 0.14.1",2528 "ethereum-types 0.14.1",
2565[[package]]2565[[package]]
2566name = "fc-rpc-core"2566name = "fc-rpc-core"
2567version = "1.1.0-dev"2567version = "1.1.0-dev"
2568source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2568source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2569dependencies = [2569dependencies = [
2570 "ethereum 0.14.0",2570 "ethereum 0.14.0",
2571 "ethereum-types 0.14.1",2571 "ethereum-types 0.14.1",
2730[[package]]2730[[package]]
2731name = "fp-consensus"2731name = "fp-consensus"
2732version = "2.0.0-dev"2732version = "2.0.0-dev"
2733source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2733source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2734dependencies = [2734dependencies = [
2735 "ethereum 0.14.0",2735 "ethereum 0.14.0",
2736 "parity-scale-codec 3.2.1",2736 "parity-scale-codec 3.2.1",
2742[[package]]2742[[package]]
2743name = "fp-ethereum"2743name = "fp-ethereum"
2744version = "1.0.0-dev"2744version = "1.0.0-dev"
2745source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2745source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2746dependencies = [2746dependencies = [
2747 "ethereum 0.14.0",2747 "ethereum 0.14.0",
2748 "ethereum-types 0.14.1",2748 "ethereum-types 0.14.1",
2757[[package]]2757[[package]]
2758name = "fp-evm"2758name = "fp-evm"
2759version = "3.0.0-dev"2759version = "3.0.0-dev"
2760source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2760source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2761dependencies = [2761dependencies = [
2762 "evm",2762 "evm",
2763 "frame-support",2763 "frame-support",
2771[[package]]2771[[package]]
2772name = "fp-evm-mapping"2772name = "fp-evm-mapping"
2773version = "0.1.0"2773version = "0.1.0"
2774source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2774source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2775dependencies = [2775dependencies = [
2776 "frame-support",2776 "frame-support",
2777 "sp-core",2777 "sp-core",
2780[[package]]2780[[package]]
2781name = "fp-rpc"2781name = "fp-rpc"
2782version = "3.0.0-dev"2782version = "3.0.0-dev"
2783source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2783source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2784dependencies = [2784dependencies = [
2785 "ethereum 0.14.0",2785 "ethereum 0.14.0",
2786 "ethereum-types 0.14.1",2786 "ethereum-types 0.14.1",
2797[[package]]2797[[package]]
2798name = "fp-self-contained"2798name = "fp-self-contained"
2799version = "1.0.0-dev"2799version = "1.0.0-dev"
2800source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2800source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2801dependencies = [2801dependencies = [
2802 "ethereum 0.14.0",2802 "ethereum 0.14.0",
2803 "frame-support",2803 "frame-support",
2810[[package]]2810[[package]]
2811name = "fp-storage"2811name = "fp-storage"
2812version = "2.0.0"2812version = "2.0.0"
2813source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"2813source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
2814dependencies = [2814dependencies = [
2815 "parity-scale-codec 3.2.1",2815 "parity-scale-codec 3.2.1",
2816 "serde",2816 "serde",
5687[[package]]5687[[package]]
5688name = "pallet-base-fee"5688name = "pallet-base-fee"
5689version = "1.0.0"5689version = "1.0.0"
5690source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"5690source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
5691dependencies = [5691dependencies = [
5692 "fp-evm",5692 "fp-evm",
5693 "frame-support",5693 "frame-support",
5952[[package]]5952[[package]]
5953name = "pallet-ethereum"5953name = "pallet-ethereum"
5954version = "4.0.0-dev"5954version = "4.0.0-dev"
5955source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"5955source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
5956dependencies = [5956dependencies = [
5957 "ethereum 0.14.0",5957 "ethereum 0.14.0",
5958 "ethereum-types 0.14.1",5958 "ethereum-types 0.14.1",
5980[[package]]5980[[package]]
5981name = "pallet-evm"5981name = "pallet-evm"
5982version = "6.0.0-dev"5982version = "6.0.0-dev"
5983source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"5983source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
5984dependencies = [5984dependencies = [
5985 "environmental",5985 "environmental",
5986 "evm",5986 "evm",
6066[[package]]6066[[package]]
6067name = "pallet-evm-precompile-simple"6067name = "pallet-evm-precompile-simple"
6068version = "2.0.0-dev"6068version = "2.0.0-dev"
6069source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#cf1894629c7df1c4dafe58aa773627a3d940da14"6069source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.36#ef8d2809ed05da0664e9b43cb87436451295b634"
6070dependencies = [6070dependencies = [
6071 "fp-evm",6071 "fp-evm",
6072 "ripemd",6072 "ripemd",
modifiedcrates/evm-coder/procedural/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "evm-coder-procedural"2name = "evm-coder-procedural"
3version = "0.2.2"3version = "0.2.3"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
811 let list = generics_list(gen);811 let list = generics_list(gen);
812 quote! { <#list> }812 quote! { <#list> }
813}813}
814fn generics_stub(gen: &Generics) -> proc_macro2::TokenStream {
815 if gen.params.is_empty() {
816 return quote! {};
817 }
818 let params = (0..gen.params.len()).map(|_| quote! {()});
819 quote! {<#(#params,)*>}
820}
814fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {821fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {
815 let list = generics_list(gen);822 let list = generics_list(gen);
816 if gen.params.len() == 1 {823 if gen.params.len() == 1 {
866 let generics = self.generics;873 let generics = self.generics;
867 let gen_ref = generics_reference(&generics);874 let gen_ref = generics_reference(&generics);
868 let gen_data = generics_data(&generics);875 let gen_data = generics_data(&generics);
876 let gen_stub = generics_stub(&generics);
869 let gen_where = &generics.where_clause;877 let gen_where = &generics.where_clause;
870878
871 let call_sub = self879 let call_sub = self
936 let solidity_events_idents = self.info.events.0.iter().map(|is| is.name.clone());944 let solidity_events_idents = self.info.events.0.iter().map(|is| is.name.clone());
937 let docs = &self.docs;945 let docs = &self.docs;
946
947 let expect_selector = self.info.expect_selector.map(|s| {
948 quote! {
949 const _: () = assert!(#s == u32::from_be_bytes(<#call_name #gen_stub>::interface_id()), "selector mismatch, review contained function selectors");
950 }
951 });
938952
939 quote! {953 quote! {
940 #(954 #(
953 )*967 )*
954 }968 }
969
970 #expect_selector
971
955 impl #gen_ref #call_name #gen_ref {972 impl #gen_ref #call_name #gen_ref {
956 #(973 #(
957 #consts974 #consts
958 )*975 )*
959 /// Return this call ERC165 selector976 /// Return this call ERC165 selector
960 pub fn interface_id() -> ::evm_coder::types::bytes4 {977 pub const fn interface_id() -> ::evm_coder::types::bytes4 {
961 let mut interface_id = 0;978 let mut interface_id = 0;
962 #(#interface_id)*979 #(#interface_id)*
963 #(#inline_interface_id)*980 #(#inline_interface_id)*
modifiedcrates/evm-coder/procedural/src/to_log.rsdiffbeforeafterboth
1616
17use inflector::cases;17use inflector::cases;
18use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};18use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};
19use std::fmt::Write;
20use quote::quote;19use quote::quote;
2120
22use crate::{parse_ident_from_path, parse_ident_from_type, snake_ident_to_screaming};21use crate::{parse_ident_from_path, parse_ident_from_type, snake_ident_to_screaming};
61 name: Ident,60 name: Ident,
62 name_screaming: Ident,61 name_screaming: Ident,
63 fields: Vec<EventField>,62 fields: Vec<EventField>,
64 selector: [u8; 32],63 selector: proc_macro2::TokenStream,
65 selector_str: String,
66}64}
6765
68impl Event {66impl Event {
69 fn try_from(variant: &Variant) -> syn::Result<Self> {67 fn try_from(variant: &Variant) -> syn::Result<Self> {
70 let name = &variant.ident;68 let name = &variant.ident;
69 let name_lit = proc_macro2::Literal::string(name.to_string().as_str());
71 let name_screaming = snake_ident_to_screaming(name);70 let name_screaming = snake_ident_to_screaming(name);
7271
73 let named = match &variant.fields {72 let named = match &variant.fields {
90 ));89 ));
91 }90 }
91
92 let mut selector_str = format!("{}(", name);92 let args = fields.iter().map(|f| {
93 let ty = &f.ty;
94 quote! {nameof(<#ty as ::evm_coder::abi::AbiType>::SIGNATURE) fixed(",")}
93 for (i, arg) in fields.iter().enumerate() {95 });
94 if i != 0 {96 // Remove trailing comma
95 write!(selector_str, ",").unwrap();
96 }
97 write!(selector_str, "{}", arg.ty).unwrap();97 let shift = (!fields.is_empty()).then(|| quote! {shift_left(1)});
98 }98
99 selector_str.push(')');99 let signature = quote! { ::evm_coder::make_signature!(new fixed(#name_lit) fixed("(") #(#args)* #shift fixed(")")) };
100 let selector = crate::event_selector_str(&selector_str);100 let selector = quote! {
101 {
102 let signature = #signature;
103 let mut sum = ::evm_coder::sha3_const::Keccak256::new();
104 let mut pos = 0;
105 while pos < signature.len {
106 sum = sum.update(&[signature.data[pos]; 1]);
107 pos += 1;
108 }
109 let a = sum.finalize();
110 let mut selector_bytes = [0; 32];
111 let mut i = 0;
112 while i != 32 {
113 selector_bytes[i] = a[i];
114 i += 1;
115 }
116 selector_bytes
117 }
118 };
101119
102 Ok(Self {120 Ok(Self {
103 name: name.to_owned(),121 name: name.to_owned(),
104 name_screaming,122 name_screaming,
105 fields,123 fields,
106 selector,124 selector,
107 selector_str,
108 })125 })
109 }126 }
110127
133150
134 fn expand_consts(&self) -> proc_macro2::TokenStream {151 fn expand_consts(&self) -> proc_macro2::TokenStream {
135 let name_screaming = &self.name_screaming;152 let name_screaming = &self.name_screaming;
136 let selector_str = &self.selector_str;
137 let selector = &self.selector;153 let selector = &self.selector;
138154
139 quote! {155 quote! {
140 #[doc = #selector_str]
141 const #name_screaming: [u8; 32] = [#(156 const #name_screaming: [u8; 32] = #selector;
142 #selector,
143 )*];
144 }157 }
145 }158 }
146159
modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
143 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()143 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
144}144}
145145
146#[cfg(feature = "quartz-runtime")]146#[cfg(not(feature = "unique-runtime"))]
147macro_rules! testnet_genesis {147macro_rules! testnet_genesis {
148 (148 (
149 $runtime:path,149 $runtime:path,
207 }};207 }};
208}208}
209209
210#[cfg(not(feature = "quartz-runtime"))]210#[cfg(feature = "unique-runtime")]
211macro_rules! testnet_genesis {211macro_rules! testnet_genesis {
212 (212 (
213 $runtime:path,213 $runtime:path,
modifiedpallets/common/src/benchmarking.rsdiffbeforeafterboth
176 key: property_key(p as usize),176 key: property_key(p as usize),
177 value: property_value(),177 value: property_value(),
178 }).collect::<Vec<_>>();178 }).collect::<Vec<_>>();
179 }: {<Pallet<T>>::set_collection_properties(&collection, &owner, props)?}179 }: {<Pallet<T>>::set_collection_properties(&collection, &owner, props.into_iter())?}
180180
181 delete_collection_properties {181 delete_collection_properties {
182 let b in 0..MAX_PROPERTIES_PER_ITEM;182 let b in 0..MAX_PROPERTIES_PER_ITEM;
188 key: property_key(p as usize),188 key: property_key(p as usize),
189 value: property_value(),189 value: property_value(),
190 }).collect::<Vec<_>>();190 }).collect::<Vec<_>>();
191 <Pallet<T>>::set_collection_properties(&collection, &owner, props)?;191 <Pallet<T>>::set_collection_properties(&collection, &owner, props.into_iter())?;
192 let to_delete = (0..b).map(|p| property_key(p as usize)).collect::<Vec<_>>();192 let to_delete = (0..b).map(|p| property_key(p as usize)).collect::<Vec<_>>();
193 }: {<Pallet<T>>::delete_collection_properties(&collection, &owner, to_delete)?}193 }: {<Pallet<T>>::delete_collection_properties(&collection, &owner, to_delete.into_iter())?}
194}194}
195195
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
125 .map(eth::Property::try_into)125 .map(eth::Property::try_into)
126 .collect::<Result<Vec<_>>>()?;126 .collect::<Result<Vec<_>>>()?;
127127
128 <Pallet<T>>::set_collection_properties(self, &caller, properties)128 <Pallet<T>>::set_collection_properties(self, &caller, properties.into_iter())
129 .map_err(dispatch_to_evm::<T>)129 .map_err(dispatch_to_evm::<T>)
130 }130 }
131131
158 })158 })
159 .collect::<Result<Vec<_>>>()?;159 .collect::<Result<Vec<_>>>()?;
160160
161 <Pallet<T>>::delete_collection_properties(self, &caller, keys).map_err(dispatch_to_evm::<T>)161 <Pallet<T>>::delete_collection_properties(self, &caller, keys.into_iter())
162 .map_err(dispatch_to_evm::<T>)
162 }163 }
163164
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
390 Ok(())390 Ok(())
391 }391 }
392392
393 /// Return **true** if `user` was not allowed to have tokens, and he can ignore such restrictions.393 /// Returns **true** if
394 /// * the `user`is a collection owner or admin
395 /// * the collection limits allow the owner/admins to transfer/burn any collection token
394 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {396 pub fn ignores_token_restrictions(&self, user: &T::CrossAccountId) -> bool {
395 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)397 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)
396 }398 }
397399
1198 Ok(())1200 Ok(())
1199 }1201 }
12001202
1201 /// Set collection property.1203 /// This function sets or removes a collection properties according to
1204 /// `properties_updates` contents:
1205 /// * sets a property under the <key> with the value provided `(<key>, Some(<value>))`
1206 /// * removes a property under the <key> if the value is `None` `(<key>, None)`.
1202 ///1207 ///
1203 /// * `collection` - Collection handler.1208 /// This function fires an event for each property change.
1204 /// * `sender` - The owner or administrator of the collection.1209 /// In case of an error, all the changes (including the events) will be reverted
1205 /// * `property` - The property to set.1210 /// since the function is transactional.
1211 #[transactional]
1206 pub fn set_collection_property(1212 fn modify_collection_properties(
1207 collection: &CollectionHandle<T>,1213 collection: &CollectionHandle<T>,
1208 sender: &T::CrossAccountId,1214 sender: &T::CrossAccountId,
1209 property: Property,1215 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
1210 ) -> DispatchResult {1216 ) -> DispatchResult {
1211 collection.check_is_owner_or_admin(sender)?;1217 collection.check_is_owner_or_admin(sender)?;
12121218
1213 CollectionProperties::<T>::try_mutate(collection.id, |properties| {1219 let mut stored_properties = <CollectionProperties<T>>::get(collection.id);
1214 let property = property.clone();1220
1215 properties.try_set(property.key, property.value)1221 for (key, value) in properties_updates {
1216 })1222 match value {
1217 .map_err(<Error<T>>::from)?;1223 Some(value) => {
12181224 stored_properties
1225 .try_set(key.clone(), value)
1219 Self::deposit_event(Event::CollectionPropertySet(collection.id, property.key));1226 .map_err(<Error<T>>::from)?;
1227
1228 Self::deposit_event(Event::CollectionPropertySet(collection.id, key));
1220 <PalletEvm<T>>::deposit_log(1229 <PalletEvm<T>>::deposit_log(
1221 erc::CollectionHelpersEvents::CollectionChanged {1230 erc::CollectionHelpersEvents::CollectionChanged {
1222 collection_id: eth::collection_id_to_address(collection.id),1231 collection_id: eth::collection_id_to_address(collection.id),
1223 }1232 }
1224 .to_log(T::ContractAddress::get()),1233 .to_log(T::ContractAddress::get()),
1225 );1234 );
1235 }
1236 None => {
1237 stored_properties.remove(&key).map_err(<Error<T>>::from)?;
1238
1239 Self::deposit_event(Event::CollectionPropertyDeleted(collection.id, key));
1240 <PalletEvm<T>>::deposit_log(
1241 erc::CollectionHelpersEvents::CollectionChanged {
1242 collection_id: eth::collection_id_to_address(collection.id),
1243 }
1244 .to_log(T::ContractAddress::get()),
1245 );
1246 }
1247 }
1248 }
1249
1250 <CollectionProperties<T>>::set(collection.id, stored_properties);
12261251
1227 Ok(())1252 Ok(())
1228 }1253 }
1254
1255 /// Set collection property.
1256 ///
1257 /// * `collection` - Collection handler.
1258 /// * `sender` - The owner or administrator of the collection.
1259 /// * `property` - The property to set.
1260 pub fn set_collection_property(
1261 collection: &CollectionHandle<T>,
1262 sender: &T::CrossAccountId,
1263 property: Property,
1264 ) -> DispatchResult {
1265 Self::set_collection_properties(collection, sender, [property].into_iter())
1266 }
12291267
1230 /// Set a scoped collection property, where the scope is a special prefix1268 /// Set a scoped collection property, where the scope is a special prefix
1231 /// prohibiting a user access to change the property directly.1269 /// prohibiting a user access to change the property directly.
1270 /// * `collection` - Collection handler.1308 /// * `collection` - Collection handler.
1271 /// * `sender` - The owner or administrator of the collection.1309 /// * `sender` - The owner or administrator of the collection.
1272 /// * `properties` - The properties to set.1310 /// * `properties` - The properties to set.
1273 #[transactional]
1274 pub fn set_collection_properties(1311 pub fn set_collection_properties(
1275 collection: &CollectionHandle<T>,1312 collection: &CollectionHandle<T>,
1276 sender: &T::CrossAccountId,1313 sender: &T::CrossAccountId,
1277 properties: Vec<Property>,1314 properties: impl Iterator<Item = Property>,
1278 ) -> DispatchResult {1315 ) -> DispatchResult {
1279 for property in properties {
1280 Self::set_collection_property(collection, sender, property)?;1316 Self::modify_collection_properties(
1281 }1317 collection,
12821318 sender,
1283 Ok(())1319 properties.map(|property| (property.key, Some(property.value))),
1320 )
1284 }1321 }
12851322
1293 sender: &T::CrossAccountId,1330 sender: &T::CrossAccountId,
1294 property_key: PropertyKey,1331 property_key: PropertyKey,
1295 ) -> DispatchResult {1332 ) -> DispatchResult {
1296 collection.check_is_owner_or_admin(sender)?;
1297
1298 CollectionProperties::<T>::try_mutate(collection.id, |properties| {
1299 properties.remove(&property_key)
1300 })
1301 .map_err(<Error<T>>::from)?;
1302
1303 Self::deposit_event(Event::CollectionPropertyDeleted(
1304 collection.id,
1305 property_key,
1306 ));
1307 <PalletEvm<T>>::deposit_log(1333 Self::delete_collection_properties(collection, sender, [property_key].into_iter())
1308 erc::CollectionHelpersEvents::CollectionChanged {
1309 collection_id: eth::collection_id_to_address(collection.id),
1310 }
1311 .to_log(T::ContractAddress::get()),
1312 );
1313
1314 Ok(())
1315 }1334 }
13161335
1317 /// Delete collection properties.1336 /// Delete collection properties.
1318 ///1337 ///
1319 /// * `collection` - Collection handler.1338 /// * `collection` - Collection handler.
1320 /// * `sender` - The owner or administrator of the collection.1339 /// * `sender` - The owner or administrator of the collection.
1321 /// * `properties` - The properties to delete.1340 /// * `properties` - The properties to delete.
1322 #[transactional]
1323 pub fn delete_collection_properties(1341 pub fn delete_collection_properties(
1324 collection: &CollectionHandle<T>,1342 collection: &CollectionHandle<T>,
1325 sender: &T::CrossAccountId,1343 sender: &T::CrossAccountId,
1326 property_keys: Vec<PropertyKey>,1344 property_keys: impl Iterator<Item = PropertyKey>,
1327 ) -> DispatchResult {1345 ) -> DispatchResult {
1328 for key in property_keys {
1329 Self::delete_collection_property(collection, sender, key)?;1346 Self::modify_collection_properties(collection, sender, property_keys.map(|key| (key, None)))
1330 }
1331
1332 Ok(())
1333 }1347 }
13341348
1335 /// Set collection propetry permission without any checks.1349 /// Set collection propetry permission without any checks.
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
266 sender: &T::CrossAccountId,266 sender: &T::CrossAccountId,
267 properties: Vec<Property>,267 properties: Vec<Property>,
268 ) -> DispatchResult {268 ) -> DispatchResult {
269 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)269 <PalletCommon<T>>::set_collection_properties(collection, sender, properties.into_iter())
270 }270 }
271271
272 /// Delete properties of the collection, associated with the provided keys.272 /// Delete properties of the collection, associated with the provided keys.
278 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)278 <PalletCommon<T>>::delete_collection_properties(
279 collection,
280 sender,
281 property_keys.into_iter(),
282 )
279 }283 }
280284
674 collection.check_allowlist(spender)?;678 collection.check_allowlist(spender)?;
675 }679 }
680
681 if collection.ignores_token_restrictions(spender) {
682 return Ok(Self::compute_allowance_decrease(
683 collection, from, spender, amount,
684 ));
685 }
686
676 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {687 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
677 // TODO: should collection owner be allowed to perform this transfer?
678 ensure!(688 ensure!(
679 <PalletStructure<T>>::check_indirectly_owned(689 <PalletStructure<T>>::check_indirectly_owned(
680 spender.clone(),690 spender.clone(),
688 return Ok(None);698 return Ok(None);
689 }699 }
700
690 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);701 let allowance = Self::compute_allowance_decrease(collection, from, spender, amount);
691 if allowance.is_none() {
692 ensure!(702 ensure!(allowance.is_some(), <CommonError<T>>::ApprovedValueTooLow);
693 collection.ignores_allowance(spender),
694 <CommonError<T>>::ApprovedValueTooLow
695 );
696 }
697703
698 Ok(allowance)704 Ok(allowance)
699 }705 }
706
707 /// Returns `Some(amount)` if the `spender` have allowance to spend this amount.
708 /// Otherwise, it returns `None`.
709 fn compute_allowance_decrease(
710 collection: &FungibleHandle<T>,
711 from: &T::CrossAccountId,
712 spender: &T::CrossAccountId,
713 amount: u128,
714 ) -> Option<u128> {
715 <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount)
716 }
700717
701 /// Transfer fungible tokens from one account to another.718 /// Transfer fungible tokens from one account to another.
702 /// Same as the [`transfer`][`Pallet::transfer`] but spender doesn't needs to be an owner of the token pieces.719 /// Same as the [`transfer`][`Pallet::transfer`] but spender doesn't needs to be an owner of the token pieces.
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
525 Ok(<Pallet<T>>::allowance_for_all(self, &owner, &operator))525 Ok(<Pallet<T>>::allowance_for_all(self, &owner, &operator))
526 }526 }
527
528 /// @notice Returns collection helper contract address
529 fn collection_helper_address(&self) -> Result<address> {
530 Ok(T::ContractAddress::get())
531 }
532}527}
533528
534/// @title ERC721 Token that can be irreversibly burned (destroyed).529/// @title ERC721 Token that can be irreversibly burned (destroyed).
1059 Ok(token_id.into())1054 Ok(token_id.into())
1060 }1055 }
1056
1057 /// @notice Returns collection helper contract address
1058 fn collection_helper_address(&self) -> Result<address> {
1059 Ok(T::ContractAddress::get())
1060 }
1061}1061}
10621062
1063#[solidity_interface(1063#[solidity_interface(
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
577 })577 })
578 }578 }
579579
580 /// Batch operation to add, edit or remove properties for the token580 /// A batch operation to add, edit or remove properties for a token.
581 ///581 /// It sets or removes a token's properties according to
582 /// All affected properties should have mutable permission and sender should have582 /// `properties_updates` contents:
583 /// permission to edit those properties.583 /// * sets a property under the <key> with the value provided `(<key>, Some(<value>))`
584 /// * removes a property under the <key> if the value is `None` `(<key>, None)`.
584 ///585 ///
585 /// - `nesting_budget`: Limit for searching parents in depth to check ownership.586 /// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
586 /// - `is_token_create`: Indicates that method is called during token initialization.587 /// - `is_token_create`: Indicates that method is called during token initialization.
587 /// Allows to bypass ownership check.588 /// Allows to bypass ownership check.
589 ///
590 /// All affected properties should have `mutable` permission
591 /// to be **deleted** or to be **set more than once**,
592 /// and the sender should have permission to edit those properties.
593 ///
594 /// This function fires an event for each property change.
595 /// In case of an error, all the changes (including the events) will be reverted
596 /// since the function is transactional.
588 #[transactional]597 #[transactional]
589 fn modify_token_properties(598 fn modify_token_properties(
590 collection: &NonfungibleHandle<T>,599 collection: &NonfungibleHandle<T>,
591 sender: &T::CrossAccountId,600 sender: &T::CrossAccountId,
592 token_id: TokenId,601 token_id: TokenId,
593 properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,602 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
594 is_token_create: bool,603 is_token_create: bool,
595 nesting_budget: &dyn Budget,604 nesting_budget: &dyn Budget,
596 ) -> DispatchResult {605 ) -> DispatchResult {
614 })623 })
615 };624 };
625
626 let mut stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
627 let permissions = <PalletCommon<T>>::property_permissions(collection.id);
616628
617 for (key, value) in properties {629 for (key, value) in properties_updates {
618 let permission = <PalletCommon<T>>::property_permissions(collection.id)630 let permission = permissions
619 .get(&key)631 .get(&key)
620 .cloned()632 .cloned()
621 .unwrap_or_else(PropertyPermission::none);633 .unwrap_or_else(PropertyPermission::none);
622634
623 let is_property_exists = TokenProperties::<T>::get((collection.id, token_id))635 let is_property_exists = stored_properties.get(&key).is_some();
624 .get(&key)
625 .is_some();
626636
649659
650 match value {660 match value {
651 Some(value) => {661 Some(value) => {
652 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {662 stored_properties
653 properties.try_set(key.clone(), value)663 .try_set(key.clone(), value)
654 })
655 .map_err(<CommonError<T>>::from)?;664 .map_err(<CommonError<T>>::from)?;
656665
657 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(666 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(
661 ));670 ));
662 }671 }
663 None => {672 None => {
664 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {673 stored_properties
665 properties.remove(&key)674 .remove(&key)
666 })
667 .map_err(<CommonError<T>>::from)?;675 .map_err(<CommonError<T>>::from)?;
668676
669 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(677 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
683 );691 );
684 }692 }
693
694 <TokenProperties<T>>::set((collection.id, token_id), stored_properties);
685695
686 Ok(())696 Ok(())
687 }697 }
784 sender: &T::CrossAccountId,794 sender: &T::CrossAccountId,
785 properties: Vec<Property>,795 properties: Vec<Property>,
786 ) -> DispatchResult {796 ) -> DispatchResult {
787 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)797 <PalletCommon<T>>::set_collection_properties(collection, sender, properties.into_iter())
788 }798 }
789799
790 /// Remove properties from the collection800 /// Remove properties from the collection
796 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)806 <PalletCommon<T>>::delete_collection_properties(
807 collection,
808 sender,
809 property_keys.into_iter(),
810 )
797 }811 }
798812
1232 collection.check_allowlist(spender)?;1246 collection.check_allowlist(spender)?;
1233 }1247 }
12341248
1235 if collection.limits.owner_can_transfer() && collection.is_owner_or_admin(spender) {1249 if collection.ignores_token_restrictions(spender) {
1236 return Ok(());1250 return Ok(());
1237 }1251 }
12381252
1255 if <CollectionAllowance<T>>::get((collection.id, from, spender)) {1269 if <CollectionAllowance<T>>::get((collection.id, from, spender)) {
1256 return Ok(());1270 return Ok(());
1257 }1271 }
1258 ensure!(1272
1259 collection.ignores_allowance(spender),
1260 <CommonError<T>>::ApprovedValueTooLow1273 Err(<CommonError<T>>::ApprovedValueTooLow.into())
1261 );
1262 Ok(())
1263 }1274 }
12641275
1265 /// Transfer NFT token from one account to another.1276 /// Transfer NFT token from one account to another.
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
785}785}
786786
787/// @title Unique extensions for ERC721.787/// @title Unique extensions for ERC721.
788/// @dev the ERC-165 identifier for this interface is 0x0e48fdb4788/// @dev the ERC-165 identifier for this interface is 0x16de3152
789contract ERC721UniqueExtensions is Dummy, ERC165 {789contract ERC721UniqueExtensions is Dummy, ERC165 {
790 /// @notice A descriptive name for a collection of NFTs in this contract790 /// @notice A descriptive name for a collection of NFTs in this contract
791 /// @dev EVM selector for this function is: 0x06fdde03,791 /// @dev EVM selector for this function is: 0x06fdde03,
987 return 0;987 return 0;
988 }988 }
989
990 /// @notice Returns collection helper contract address
991 /// @dev EVM selector for this function is: 0x1896cce6,
992 /// or in textual repr: collectionHelperAddress()
993 function collectionHelperAddress() public view returns (address) {
994 require(false, stub_error);
995 dummy;
996 return 0x0000000000000000000000000000000000000000;
997 }
989}998}
990999
991/// @dev anonymous struct1000/// @dev anonymous struct
10431052
1044/// @title ERC-721 Non-Fungible Token Standard1053/// @title ERC-721 Non-Fungible Token Standard
1045/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md1054/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
1046/// @dev the ERC-165 identifier for this interface is 0x983a942b1055/// @dev the ERC-165 identifier for this interface is 0x80ac58cd
1047contract ERC721 is Dummy, ERC165, ERC721Events {1056contract ERC721 is Dummy, ERC165, ERC721Events {
1048 /// @notice Count all NFTs assigned to an owner1057 /// @notice Count all NFTs assigned to an owner
1049 /// @dev NFTs assigned to the zero address are considered invalid, and this1058 /// @dev NFTs assigned to the zero address are considered invalid, and this
1177 return false;1186 return false;
1178 }1187 }
1179
1180 /// @notice Returns collection helper contract address
1181 /// @dev EVM selector for this function is: 0x1896cce6,
1182 /// or in textual repr: collectionHelperAddress()
1183 function collectionHelperAddress() public view returns (address) {
1184 require(false, stub_error);
1185 dummy;
1186 return 0x0000000000000000000000000000000000000000;
1187 }
1188}1188}
11891189
1190contract UniqueNFT is1190contract UniqueNFT is
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
184 .saturating_add(T::DbWeight::get().reads(1 as u64))184 .saturating_add(T::DbWeight::get().reads(1 as u64))
185 .saturating_add(T::DbWeight::get().writes(1 as u64))185 .saturating_add(T::DbWeight::get().writes(1 as u64))
186 }186 }
187 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
188 // Storage: Nonfungible TokenProperties (r:1 w:1)187 // Storage: Nonfungible TokenProperties (r:1 w:1)
188 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
189 fn set_token_properties(b: u32, ) -> Weight {189 fn set_token_properties(b: u32, ) -> Weight {
190 Weight::from_ref_time(4_361_000 as u64)190 Weight::from_ref_time(31_850_484 as u64)
191 // Standard Error: 5_349_868191 // Standard Error: 9_618
192 .saturating_add(Weight::from_ref_time(637_246_356 as u64).saturating_mul(b as u64))192 .saturating_add(Weight::from_ref_time(4_721_947 as u64).saturating_mul(b as u64))
193 .saturating_add(T::DbWeight::get().reads(2 as u64))193 .saturating_add(T::DbWeight::get().reads(2 as u64))
194 .saturating_add(T::DbWeight::get().writes(1 as u64))194 .saturating_add(T::DbWeight::get().writes(1 as u64))
195 }195 }
196 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
197 // Storage: Nonfungible TokenProperties (r:1 w:1)196 // Storage: Nonfungible TokenProperties (r:1 w:1)
197 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
198 fn delete_token_properties(b: u32, ) -> Weight {198 fn delete_token_properties(b: u32, ) -> Weight {
199 Weight::from_ref_time(4_489_000 as u64)199 Weight::from_ref_time(13_795_000 as u64)
200 // Standard Error: 5_738_954200 // Standard Error: 28_239
201 .saturating_add(Weight::from_ref_time(689_912_822 as u64).saturating_mul(b as u64))201 .saturating_add(Weight::from_ref_time(12_840_446 as u64).saturating_mul(b as u64))
202 .saturating_add(T::DbWeight::get().reads(2 as u64))202 .saturating_add(T::DbWeight::get().reads(2 as u64))
203 .saturating_add(T::DbWeight::get().writes(1 as u64))203 .saturating_add(T::DbWeight::get().writes(1 as u64))
204 }204 }
354 .saturating_add(RocksDbWeight::get().reads(1 as u64))354 .saturating_add(RocksDbWeight::get().reads(1 as u64))
355 .saturating_add(RocksDbWeight::get().writes(1 as u64))355 .saturating_add(RocksDbWeight::get().writes(1 as u64))
356 }356 }
357 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
358 // Storage: Nonfungible TokenProperties (r:1 w:1)357 // Storage: Nonfungible TokenProperties (r:1 w:1)
358 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
359 fn set_token_properties(b: u32, ) -> Weight {359 fn set_token_properties(b: u32, ) -> Weight {
360 Weight::from_ref_time(4_361_000 as u64)360 Weight::from_ref_time(31_850_484 as u64)
361 // Standard Error: 5_349_868361 // Standard Error: 9_618
362 .saturating_add(Weight::from_ref_time(637_246_356 as u64).saturating_mul(b as u64))362 .saturating_add(Weight::from_ref_time(4_721_947 as u64).saturating_mul(b as u64))
363 .saturating_add(RocksDbWeight::get().reads(2 as u64))363 .saturating_add(RocksDbWeight::get().reads(2 as u64))
364 .saturating_add(RocksDbWeight::get().writes(1 as u64))364 .saturating_add(RocksDbWeight::get().writes(1 as u64))
365 }365 }
366 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
367 // Storage: Nonfungible TokenProperties (r:1 w:1)366 // Storage: Nonfungible TokenProperties (r:1 w:1)
367 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
368 fn delete_token_properties(b: u32, ) -> Weight {368 fn delete_token_properties(b: u32, ) -> Weight {
369 Weight::from_ref_time(4_489_000 as u64)369 Weight::from_ref_time(13_795_000 as u64)
370 // Standard Error: 5_738_954370 // Standard Error: 28_239
371 .saturating_add(Weight::from_ref_time(689_912_822 as u64).saturating_mul(b as u64))371 .saturating_add(Weight::from_ref_time(12_840_446 as u64).saturating_mul(b as u64))
372 .saturating_add(RocksDbWeight::get().reads(2 as u64))372 .saturating_add(RocksDbWeight::get().reads(2 as u64))
373 .saturating_add(RocksDbWeight::get().writes(1 as u64))373 .saturating_add(RocksDbWeight::get().writes(1 as u64))
374 }374 }
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
295 MintingFinished {},295 MintingFinished {},
296}296}
297297
298/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
299/// @dev See https://eips.ethereum.org/EIPS/eip-721
298#[solidity_interface(name = ERC721Metadata)]300#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
299impl<T: Config> RefungibleHandle<T>301impl<T: Config> RefungibleHandle<T>
300where302where
301 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,303 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
364366
365/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension367/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
366/// @dev See https://eips.ethereum.org/EIPS/eip-721368/// @dev See https://eips.ethereum.org/EIPS/eip-721
367#[solidity_interface(name = ERC721Enumerable)]369#[solidity_interface(name = ERC721Enumerable, expect_selector = 0x780e9d63)]
368impl<T: Config> RefungibleHandle<T> {370impl<T: Config> RefungibleHandle<T> {
369 /// @notice Enumerate valid RFTs371 /// @notice Enumerate valid RFTs
370 /// @param index A counter less than `totalSupply()`372 /// @param index A counter less than `totalSupply()`
391393
392/// @title ERC-721 Non-Fungible Token Standard394/// @title ERC-721 Non-Fungible Token Standard
393/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md395/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
394#[solidity_interface(name = ERC721, events(ERC721Events))]396#[solidity_interface(name = ERC721, events(ERC721Events), expect_selector = 0x80ac58cd)]
395impl<T: Config> RefungibleHandle<T> {397impl<T: Config> RefungibleHandle<T> {
396 /// @notice Count all RFTs assigned to an owner398 /// @notice Count all RFTs assigned to an owner
397 /// @dev RFTs assigned to the zero address are considered invalid, and this399 /// @dev RFTs assigned to the zero address are considered invalid, and this
422 }424 }
423425
424 /// @dev Not implemented426 /// @dev Not implemented
427 #[solidity(rename_selector = "safeTransferFrom")]
425 fn safe_transfer_from_with_data(428 fn safe_transfer_from_with_data(
426 &mut self,429 &mut self,
427 _from: address,430 _from: address,
434 }437 }
435438
436 /// @dev Not implemented439 /// @dev Not implemented
440 #[solidity(rename_selector = "safeTransferFrom")]
437 fn safe_transfer_from(441 fn safe_transfer_from(
438 &mut self,442 &mut self,
439 _from: address,443 _from: address,
518 Ok(<Pallet<T>>::allowance_for_all(self, &owner, &operator))522 Ok(<Pallet<T>>::allowance_for_all(self, &owner, &operator))
519 }523 }
520
521 /// @notice Returns collection helper contract address
522 fn collection_helper_address(&self) -> Result<address> {
523 Ok(T::ContractAddress::get())
524 }
525}524}
526525
527/// Returns amount of pieces of `token` that `owner` have526/// Returns amount of pieces of `token` that `owner` have
1117 ))1116 ))
1118 }1117 }
1118
1119 /// @notice Returns collection helper contract address
1120 fn collection_helper_address(&self) -> Result<address> {
1121 Ok(T::ContractAddress::get())
1122 }
1119}1123}
11201124
1121#[solidity_interface(1125#[solidity_interface(
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
515 Ok(())515 Ok(())
516 }516 }
517517
518 /// A batch operation to add, edit or remove properties for a token.
519 /// It sets or removes a token's properties according to
520 /// `properties_updates` contents:
521 /// * sets a property under the <key> with the value provided `(<key>, Some(<value>))`
522 /// * removes a property under the <key> if the value is `None` `(<key>, None)`.
523 ///
524 /// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
525 /// - `is_token_create`: Indicates that method is called during token initialization.
526 /// Allows to bypass ownership check.
527 ///
528 /// All affected properties should have `mutable` permission
529 /// to be **deleted** or to be **set more than once**,
530 /// and the sender should have permission to edit those properties.
531 ///
532 /// This function fires an event for each property change.
533 /// In case of an error, all the changes (including the events) will be reverted
534 /// since the function is transactional.
518 #[transactional]535 #[transactional]
519 fn modify_token_properties(536 fn modify_token_properties(
520 collection: &RefungibleHandle<T>,537 collection: &RefungibleHandle<T>,
521 sender: &T::CrossAccountId,538 sender: &T::CrossAccountId,
522 token_id: TokenId,539 token_id: TokenId,
523 properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,540 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
524 is_token_create: bool,541 is_token_create: bool,
525 nesting_budget: &dyn Budget,542 nesting_budget: &dyn Budget,
526 ) -> DispatchResult {543 ) -> DispatchResult {
544 Ok(is_bundle_owner)561 Ok(is_bundle_owner)
545 };562 };
563
564 let mut stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
565 let permissions = <PalletCommon<T>>::property_permissions(collection.id);
546566
547 for (key, value) in properties {567 for (key, value) in properties_updates {
548 let permission = <PalletCommon<T>>::property_permissions(collection.id)568 let permission = permissions
549 .get(&key)569 .get(&key)
550 .cloned()570 .cloned()
551 .unwrap_or_else(PropertyPermission::none);571 .unwrap_or_else(PropertyPermission::none);
552572
553 let is_property_exists = TokenProperties::<T>::get((collection.id, token_id))573 let is_property_exists = stored_properties.get(&key).is_some();
554 .get(&key)
555 .is_some();
556574
578596
579 match value {597 match value {
580 Some(value) => {598 Some(value) => {
581 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {599 stored_properties
582 properties.try_set(key.clone(), value)600 .try_set(key.clone(), value)
583 })
584 .map_err(<CommonError<T>>::from)?;601 .map_err(<CommonError<T>>::from)?;
585602
586 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(603 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(
590 ));607 ));
591 }608 }
592 None => {609 None => {
593 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {610 stored_properties
594 properties.remove(&key)611 .remove(&key)
595 })
596 .map_err(<CommonError<T>>::from)?;612 .map_err(<CommonError<T>>::from)?;
597613
598 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(614 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
612 );628 );
613 }629 }
630
631 <TokenProperties<T>>::set((collection.id, token_id), stored_properties);
614632
615 Ok(())633 Ok(())
616 }634 }
1160 collection.check_allowlist(spender)?;1178 collection.check_allowlist(spender)?;
1161 }1179 }
1180
1181 if collection.ignores_token_restrictions(spender) {
1182 return Ok(Self::compute_allowance_decrease(
1183 collection, token, from, &spender, amount,
1184 ));
1185 }
1186
1162 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {1187 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
1163 // TODO: should collection owner be allowed to perform this transfer?1188 // TODO: should collection owner be allowed to perform this transfer?
1174 return Ok(None);1199 return Ok(None);
1175 }1200 }
1201
1176 let allowance =1202 let allowance = Self::compute_allowance_decrease(collection, token, from, &spender, amount);
1177 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);1203 if allowance.is_some() {
1204 return Ok(allowance);
1205 }
11781206
1179 // Allowance (if any) would be reduced if spender is also wallet operator1207 // Allowance (if any) would be reduced if spender is also wallet operator
1180 if <CollectionAllowance<T>>::get((collection.id, from, spender)) {1208 if <CollectionAllowance<T>>::get((collection.id, from, spender)) {
1181 return Ok(allowance);1209 return Ok(allowance);
1182 }1210 }
11831211
1184 if allowance.is_none() {
1185 ensure!(
1186 collection.ignores_allowance(spender),
1187 <CommonError<T>>::ApprovedValueTooLow1212 Err(<CommonError<T>>::ApprovedValueTooLow.into())
1188 );
1189 }
1190 Ok(allowance)
1191 }1213 }
1214
1215 /// Returns `Some(amount)` if the `spender` have allowance to spend this amount.
1216 /// Otherwise, it returns `None`.
1217 fn compute_allowance_decrease(
1218 collection: &RefungibleHandle<T>,
1219 token: TokenId,
1220 from: &T::CrossAccountId,
1221 spender: &T::CrossAccountId,
1222 amount: u128,
1223 ) -> Option<u128> {
1224 <Allowance<T>>::get((collection.id, token, from, spender)).checked_sub(amount)
1225 }
11921226
1193 /// Transfer RFT token pieces from one account to another.1227 /// Transfer RFT token pieces from one account to another.
1194 ///1228 ///
1353 sender: &T::CrossAccountId,1387 sender: &T::CrossAccountId,
1354 properties: Vec<Property>,1388 properties: Vec<Property>,
1355 ) -> DispatchResult {1389 ) -> DispatchResult {
1356 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)1390 <PalletCommon<T>>::set_collection_properties(collection, sender, properties.into_iter())
1357 }1391 }
13581392
1359 pub fn delete_collection_properties(1393 pub fn delete_collection_properties(
1364 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)1398 <PalletCommon<T>>::delete_collection_properties(
1399 collection,
1400 sender,
1401 property_keys.into_iter(),
1402 )
1365 }1403 }
13661404
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
641 TransferEnabled641 TransferEnabled
642}642}
643643
644/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
645/// @dev See https://eips.ethereum.org/EIPS/eip-721
644/// @dev the ERC-165 identifier for this interface is 0x5b5e139f646/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
645contract ERC721Metadata is Dummy, ERC165 {647contract ERC721Metadata is Dummy, ERC165 {
646 // /// @notice A descriptive name for a collection of NFTs in this contract648 // /// @notice A descriptive name for a collection of NFTs in this contract
783}785}
784786
785/// @title Unique extensions for ERC721.787/// @title Unique extensions for ERC721.
786/// @dev the ERC-165 identifier for this interface is 0xabf30dc2788/// @dev the ERC-165 identifier for this interface is 0xb365c124
787contract ERC721UniqueExtensions is Dummy, ERC165 {789contract ERC721UniqueExtensions is Dummy, ERC165 {
788 /// @notice A descriptive name for a collection of NFTs in this contract790 /// @notice A descriptive name for a collection of NFTs in this contract
789 /// @dev EVM selector for this function is: 0x06fdde03,791 /// @dev EVM selector for this function is: 0x06fdde03,
986 return 0x0000000000000000000000000000000000000000;988 return 0x0000000000000000000000000000000000000000;
987 }989 }
990
991 /// @notice Returns collection helper contract address
992 /// @dev EVM selector for this function is: 0x1896cce6,
993 /// or in textual repr: collectionHelperAddress()
994 function collectionHelperAddress() public view returns (address) {
995 require(false, stub_error);
996 dummy;
997 return 0x0000000000000000000000000000000000000000;
998 }
988}999}
9891000
990/// @dev anonymous struct1001/// @dev anonymous struct
10421053
1043/// @title ERC-721 Non-Fungible Token Standard1054/// @title ERC-721 Non-Fungible Token Standard
1044/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md1055/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
1045/// @dev the ERC-165 identifier for this interface is 0x4016cd871056/// @dev the ERC-165 identifier for this interface is 0x80ac58cd
1046contract ERC721 is Dummy, ERC165, ERC721Events {1057contract ERC721 is Dummy, ERC165, ERC721Events {
1047 /// @notice Count all RFTs assigned to an owner1058 /// @notice Count all RFTs assigned to an owner
1048 /// @dev RFTs assigned to the zero address are considered invalid, and this1059 /// @dev RFTs assigned to the zero address are considered invalid, and this
1075 }1086 }
10761087
1077 /// @dev Not implemented1088 /// @dev Not implemented
1078 /// @dev EVM selector for this function is: 0x60a11672,1089 /// @dev EVM selector for this function is: 0xb88d4fde,
1079 /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)1090 /// or in textual repr: safeTransferFrom(address,address,uint256,bytes)
1080 function safeTransferFromWithData(1091 function safeTransferFrom(
1081 address from,1092 address from,
1082 address to,1093 address to,
1083 uint256 tokenId,1094 uint256 tokenId,
1174 return false;1185 return false;
1175 }1186 }
1176
1177 /// @notice Returns collection helper contract address
1178 /// @dev EVM selector for this function is: 0x1896cce6,
1179 /// or in textual repr: collectionHelperAddress()
1180 function collectionHelperAddress() public view returns (address) {
1181 require(false, stub_error);
1182 dummy;
1183 return 0x0000000000000000000000000000000000000000;
1184 }
1185}1187}
11861188
1187contract UniqueRefungible is1189contract UniqueRefungible is
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
246 .saturating_add(T::DbWeight::get().reads(1 as u64))246 .saturating_add(T::DbWeight::get().reads(1 as u64))
247 .saturating_add(T::DbWeight::get().writes(1 as u64))247 .saturating_add(T::DbWeight::get().writes(1 as u64))
248 }248 }
249 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
250 // Storage: Refungible TokenProperties (r:1 w:1)249 // Storage: Refungible TokenProperties (r:1 w:1)
250 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
251 fn set_token_properties(b: u32, ) -> Weight {251 fn set_token_properties(b: u32, ) -> Weight {
252 Weight::from_ref_time(4_578_000 as u64)252 Weight::from_ref_time(25_518_267 as u64)
253 // Standard Error: 5_396_287253 // Standard Error: 20_451
254 .saturating_add(Weight::from_ref_time(633_314_546 as u64).saturating_mul(b as u64))254 .saturating_add(Weight::from_ref_time(5_041_089 as u64).saturating_mul(b as u64))
255 .saturating_add(T::DbWeight::get().reads(2 as u64))255 .saturating_add(T::DbWeight::get().reads(2 as u64))
256 .saturating_add(T::DbWeight::get().writes(1 as u64))256 .saturating_add(T::DbWeight::get().writes(1 as u64))
257 }257 }
258 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
259 // Storage: Refungible TokenProperties (r:1 w:1)258 // Storage: Refungible TokenProperties (r:1 w:1)
259 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
260 fn delete_token_properties(b: u32, ) -> Weight {260 fn delete_token_properties(b: u32, ) -> Weight {
261 Weight::from_ref_time(4_583_000 as u64)261 Weight::from_ref_time(13_715_000 as u64)
262 // Standard Error: 5_762_380262 // Standard Error: 28_323
263 .saturating_add(Weight::from_ref_time(696_007_076 as u64).saturating_mul(b as u64))263 .saturating_add(Weight::from_ref_time(13_113_351 as u64).saturating_mul(b as u64))
264 .saturating_add(T::DbWeight::get().reads(2 as u64))264 .saturating_add(T::DbWeight::get().reads(2 as u64))
265 .saturating_add(T::DbWeight::get().writes(1 as u64))265 .saturating_add(T::DbWeight::get().writes(1 as u64))
266 }266 }
478 .saturating_add(RocksDbWeight::get().reads(1 as u64))478 .saturating_add(RocksDbWeight::get().reads(1 as u64))
479 .saturating_add(RocksDbWeight::get().writes(1 as u64))479 .saturating_add(RocksDbWeight::get().writes(1 as u64))
480 }480 }
481 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
482 // Storage: Refungible TokenProperties (r:1 w:1)481 // Storage: Refungible TokenProperties (r:1 w:1)
482 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
483 fn set_token_properties(b: u32, ) -> Weight {483 fn set_token_properties(b: u32, ) -> Weight {
484 Weight::from_ref_time(4_578_000 as u64)484 Weight::from_ref_time(25_518_267 as u64)
485 // Standard Error: 5_396_287485 // Standard Error: 20_451
486 .saturating_add(Weight::from_ref_time(633_314_546 as u64).saturating_mul(b as u64))486 .saturating_add(Weight::from_ref_time(5_041_089 as u64).saturating_mul(b as u64))
487 .saturating_add(RocksDbWeight::get().reads(2 as u64))487 .saturating_add(RocksDbWeight::get().reads(2 as u64))
488 .saturating_add(RocksDbWeight::get().writes(1 as u64))488 .saturating_add(RocksDbWeight::get().writes(1 as u64))
489 }489 }
490 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
491 // Storage: Refungible TokenProperties (r:1 w:1)490 // Storage: Refungible TokenProperties (r:1 w:1)
491 // Storage: Common CollectionPropertyPermissions (r:1 w:0)
492 fn delete_token_properties(b: u32, ) -> Weight {492 fn delete_token_properties(b: u32, ) -> Weight {
493 Weight::from_ref_time(4_583_000 as u64)493 Weight::from_ref_time(13_715_000 as u64)
494 // Standard Error: 5_762_380494 // Standard Error: 28_323
495 .saturating_add(Weight::from_ref_time(696_007_076 as u64).saturating_mul(b as u64))495 .saturating_add(Weight::from_ref_time(13_113_351 as u64).saturating_mul(b as u64))
496 .saturating_add(RocksDbWeight::get().reads(2 as u64))496 .saturating_add(RocksDbWeight::get().reads(2 as u64))
497 .saturating_add(RocksDbWeight::get().writes(1 as u64))497 .saturating_add(RocksDbWeight::get().writes(1 as u64))
498 }498 }
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
33};33};
34use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};34use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
35use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};35use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};
36use sp_std::vec;
37use up_data_structs::{36use up_data_structs::{
38 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,37 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,
39 CreateCollectionData,38 CreateCollectionData,
316 <PalletCommon<T>>::set_collection_properties(315 <PalletCommon<T>>::set_collection_properties(
317 &collection,316 &collection,
318 &caller,317 &caller,
319 vec![up_data_structs::Property {318 [up_data_structs::Property {
320 key: key::base_uri(),319 key: key::base_uri(),
321 value: base_uri320 value: base_uri
322 .into_bytes()321 .into_bytes()
323 .try_into()322 .try_into()
324 .map_err(|_| "base uri is too large")?,323 .map_err(|_| "base uri is too large")?,
325 }],324 }]
325 .into_iter(),
326 )326 )
327 .map_err(dispatch_to_evm::<T>)?;327 .map_err(dispatch_to_evm::<T>)?;
328 }328 }
modifiedruntime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth
140 | OwnerOf { .. }140 | OwnerOf { .. }
141 | GetApproved { .. }141 | GetApproved { .. }
142 | IsApprovedForAll { .. }142 | IsApprovedForAll { .. } => None,
143 | CollectionHelperAddress => None,
144143
145 // Not sponsored144 // Not sponsored
146 SafeTransferFromWithData { .. }145 SafeTransferFromWithData { .. }
231 | Properties { .. }230 | Properties { .. }
232 | NextTokenId231 | NextTokenId
233 | TokenContractAddress { .. } => None,232 | TokenContractAddress { .. }
233 | CollectionHelperAddress => None,
234234
235 // Not sponsored235 // Not sponsored
236 BurnFrom { .. }236 BurnFrom { .. }
modifiedruntime/common/identity.rsdiffbeforeafterboth
24 transaction_validity::{TransactionValidity, ValidTransaction, TransactionValidityError},24 transaction_validity::{TransactionValidity, ValidTransaction, TransactionValidityError},
25};25};
26
27#[cfg(feature = "collator-selection")]
28use sp_runtime::transaction_validity::InvalidTransaction;
2629
27#[derive(Debug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)]30#[derive(Debug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)]
28pub struct DisableIdentityCalls;31pub struct DisableIdentityCalls;
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
451 }451 }
452452
453 fn account_code_at(address: H160) -> Vec<u8> {453 fn account_code_at(address: H160) -> Vec<u8> {
454 use pallet_evm::OnMethodCall;
455 <Runtime as pallet_evm::Config>::OnMethodCall::get_code(&address)
454 EVM::account_codes(address)456 .unwrap_or_else(|| EVM::account_codes(address))
455 }457 }
456458
457 fn author() -> H160 {459 fn author() -> H160 {
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
193 'refungible',193 'refungible',
194 'rmrk',194 'rmrk',
195 'app-promotion',195 'app-promotion',
196 'collator-selection',
196 'foreign-assets',197 'foreign-assets',
197 'pallet-test-utils',198 'pallet-test-utils',
198]199]
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
49 "name": "ApprovalForAll",49 "name": "ApprovalForAll",
50 "type": "event"50 "type": "event"
51 },51 },
52 {
53 "anonymous": false,
54 "inputs": [],
55 "name": "MintingFinished",
56 "type": "event"
57 },
52 {58 {
53 "anonymous": false,59 "anonymous": false,
54 "inputs": [60 "inputs": [
416 "stateMutability": "view",422 "stateMutability": "view",
417 "type": "function"423 "type": "function"
418 },424 },
425 {
426 "inputs": [],
427 "name": "finishMinting",
428 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
429 "stateMutability": "nonpayable",
430 "type": "function"
431 },
419 {432 {
420 "inputs": [433 "inputs": [
421 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }434 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
502 "stateMutability": "nonpayable",515 "stateMutability": "nonpayable",
503 "type": "function"516 "type": "function"
504 },517 },
518 {
519 "inputs": [],
520 "name": "mintingFinished",
521 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
522 "stateMutability": "view",
523 "type": "function"
524 },
505 {525 {
506 "inputs": [],526 "inputs": [],
507 "name": "name",527 "name": "name",
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
49 "name": "ApprovalForAll",49 "name": "ApprovalForAll",
50 "type": "event"50 "type": "event"
51 },51 },
52 {
53 "anonymous": false,
54 "inputs": [],
55 "name": "MintingFinished",
56 "type": "event"
57 },
52 {58 {
53 "anonymous": false,59 "anonymous": false,
54 "inputs": [60 "inputs": [
398 "stateMutability": "view",404 "stateMutability": "view",
399 "type": "function"405 "type": "function"
400 },406 },
407 {
408 "inputs": [],
409 "name": "finishMinting",
410 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
411 "stateMutability": "nonpayable",
412 "type": "function"
413 },
401 {414 {
402 "inputs": [415 "inputs": [
403 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }416 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
484 "stateMutability": "nonpayable",497 "stateMutability": "nonpayable",
485 "type": "function"498 "type": "function"
486 },499 },
500 {
501 "inputs": [],
502 "name": "mintingFinished",
503 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
504 "stateMutability": "view",
505 "type": "function"
506 },
487 {507 {
488 "inputs": [],508 "inputs": [],
489 "name": "name",509 "name": "name",
596 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },616 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
597 { "internalType": "bytes", "name": "data", "type": "bytes" }617 { "internalType": "bytes", "name": "data", "type": "bytes" }
598 ],618 ],
599 "name": "safeTransferFromWithData",619 "name": "safeTransferFrom",
600 "outputs": [],620 "outputs": [],
601 "stateMutability": "nonpayable",621 "stateMutability": "nonpayable",
602 "type": "function"622 "type": "function"
modifiedtests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth
96 "stateMutability": "view",96 "stateMutability": "view",
97 "type": "function"97 "type": "function"
98 },98 },
99 {
100 "inputs": [
101 { "internalType": "address", "name": "from", "type": "address" },
102 { "internalType": "uint256", "name": "amount", "type": "uint256" }
103 ],
104 "name": "burnFrom",
105 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
106 "stateMutability": "nonpayable",
107 "type": "function"
108 },
99 {109 {
100 "inputs": [110 "inputs": [
101 {111 {
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
536}536}
537537
538/// @title Unique extensions for ERC721.538/// @title Unique extensions for ERC721.
539/// @dev the ERC-165 identifier for this interface is 0x0e48fdb4539/// @dev the ERC-165 identifier for this interface is 0x16de3152
540interface ERC721UniqueExtensions is Dummy, ERC165 {540interface ERC721UniqueExtensions is Dummy, ERC165 {
541 /// @notice A descriptive name for a collection of NFTs in this contract541 /// @notice A descriptive name for a collection of NFTs in this contract
542 /// @dev EVM selector for this function is: 0x06fdde03,542 /// @dev EVM selector for this function is: 0x06fdde03,
662 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])662 /// or in textual repr: mintCross((address,uint256),(string,bytes)[])
663 function mintCross(CrossAddress memory to, Property[] memory properties) external returns (uint256);663 function mintCross(CrossAddress memory to, Property[] memory properties) external returns (uint256);
664
665 /// @notice Returns collection helper contract address
666 /// @dev EVM selector for this function is: 0x1896cce6,
667 /// or in textual repr: collectionHelperAddress()
668 function collectionHelperAddress() external view returns (address);
664}669}
665670
666/// @dev anonymous struct671/// @dev anonymous struct
703708
704/// @title ERC-721 Non-Fungible Token Standard709/// @title ERC-721 Non-Fungible Token Standard
705/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md710/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
706/// @dev the ERC-165 identifier for this interface is 0x983a942b711/// @dev the ERC-165 identifier for this interface is 0x80ac58cd
707interface ERC721 is Dummy, ERC165, ERC721Events {712interface ERC721 is Dummy, ERC165, ERC721Events {
708 /// @notice Count all NFTs assigned to an owner713 /// @notice Count all NFTs assigned to an owner
709 /// @dev NFTs assigned to the zero address are considered invalid, and this714 /// @dev NFTs assigned to the zero address are considered invalid, and this
787 /// or in textual repr: isApprovedForAll(address,address)792 /// or in textual repr: isApprovedForAll(address,address)
788 function isApprovedForAll(address owner, address operator) external view returns (bool);793 function isApprovedForAll(address owner, address operator) external view returns (bool);
789
790 /// @notice Returns collection helper contract address
791 /// @dev EVM selector for this function is: 0x1896cce6,
792 /// or in textual repr: collectionHelperAddress()
793 function collectionHelperAddress() external view returns (address);
794}794}
795795
796interface UniqueNFT is796interface UniqueNFT is
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
441 TransferEnabled441 TransferEnabled
442}442}
443443
444/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
445/// @dev See https://eips.ethereum.org/EIPS/eip-721
444/// @dev the ERC-165 identifier for this interface is 0x5b5e139f446/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
445interface ERC721Metadata is Dummy, ERC165 {447interface ERC721Metadata is Dummy, ERC165 {
446 // /// @notice A descriptive name for a collection of NFTs in this contract448 // /// @notice A descriptive name for a collection of NFTs in this contract
534}536}
535537
536/// @title Unique extensions for ERC721.538/// @title Unique extensions for ERC721.
537/// @dev the ERC-165 identifier for this interface is 0xabf30dc2539/// @dev the ERC-165 identifier for this interface is 0xb365c124
538interface ERC721UniqueExtensions is Dummy, ERC165 {540interface ERC721UniqueExtensions is Dummy, ERC165 {
539 /// @notice A descriptive name for a collection of NFTs in this contract541 /// @notice A descriptive name for a collection of NFTs in this contract
540 /// @dev EVM selector for this function is: 0x06fdde03,542 /// @dev EVM selector for this function is: 0x06fdde03,
661 /// or in textual repr: tokenContractAddress(uint256)663 /// or in textual repr: tokenContractAddress(uint256)
662 function tokenContractAddress(uint256 token) external view returns (address);664 function tokenContractAddress(uint256 token) external view returns (address);
665
666 /// @notice Returns collection helper contract address
667 /// @dev EVM selector for this function is: 0x1896cce6,
668 /// or in textual repr: collectionHelperAddress()
669 function collectionHelperAddress() external view returns (address);
663}670}
664671
665/// @dev anonymous struct672/// @dev anonymous struct
702709
703/// @title ERC-721 Non-Fungible Token Standard710/// @title ERC-721 Non-Fungible Token Standard
704/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md711/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
705/// @dev the ERC-165 identifier for this interface is 0x4016cd87712/// @dev the ERC-165 identifier for this interface is 0x80ac58cd
706interface ERC721 is Dummy, ERC165, ERC721Events {713interface ERC721 is Dummy, ERC165, ERC721Events {
707 /// @notice Count all RFTs assigned to an owner714 /// @notice Count all RFTs assigned to an owner
708 /// @dev RFTs assigned to the zero address are considered invalid, and this715 /// @dev RFTs assigned to the zero address are considered invalid, and this
725 function ownerOf(uint256 tokenId) external view returns (address);732 function ownerOf(uint256 tokenId) external view returns (address);
726733
727 /// @dev Not implemented734 /// @dev Not implemented
728 /// @dev EVM selector for this function is: 0x60a11672,735 /// @dev EVM selector for this function is: 0xb88d4fde,
729 /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)736 /// or in textual repr: safeTransferFrom(address,address,uint256,bytes)
730 function safeTransferFromWithData(737 function safeTransferFrom(
731 address from,738 address from,
732 address to,739 address to,
733 uint256 tokenId,740 uint256 tokenId,
784 /// or in textual repr: isApprovedForAll(address,address)791 /// or in textual repr: isApprovedForAll(address,address)
785 function isApprovedForAll(address owner, address operator) external view returns (bool);792 function isApprovedForAll(address owner, address operator) external view returns (bool);
786
787 /// @notice Returns collection helper contract address
788 /// @dev EVM selector for this function is: 0x1896cce6,
789 /// or in textual repr: collectionHelperAddress()
790 function collectionHelperAddress() external view returns (address);
791}793}
792794
793interface UniqueRefungible is795interface UniqueRefungible is
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {expect, itSub, Pallets, usingPlaygrounds} from '../util';18import {expect, itSub, Pallets, usingPlaygrounds} from '../util';
19import {UniqueFTCollection, UniqueNFToken, UniqueRFToken} from '../util/playgrounds/unique';
1920
20describe('Integration Test: Unnesting', () => {21describe('Integration Test: Unnesting', () => {
21 let alice: IKeyringPair;22 let alice: IKeyringPair;
23 let bob: IKeyringPair;
24 let charlie: IKeyringPair;
2225
23 before(async () => {26 before(async () => {
24 await usingPlaygrounds(async (helper, privateKey) => {27 await usingPlaygrounds(async (helper, privateKey) => {
25 const donor = await privateKey({filename: __filename});28 const donor = await privateKey({filename: __filename});
26 [alice] = await helper.arrange.createAccounts([50n], donor);29 [alice, bob, charlie] = await helper.arrange.createAccounts([200n, 50n, 50n], donor);
27 });30 });
28 });31 });
2932
64 expect(await targetToken.getChildren()).to.be.length(0);67 expect(await targetToken.getChildren()).to.be.length(0);
65 });68 });
69
70 itSub.ifWithPallets('ReFungible: allows the owner to successfully unnest a token', [Pallets.ReFungible], async ({helper}) => {
71 const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
72 const targetToken = await collection.mintToken(alice);
73
74 const collectionRFT = await helper.rft.mintCollection(alice);
75
76 // Nest and unnest
77 const token = await collectionRFT.mintToken(alice, 10n, targetToken.nestingAccount());
78 await expect(token.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
79 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(9n);
80 expect(await token.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
81
82 // Nest and burn
83 await token.transfer(alice, targetToken.nestingAccount(), 5n);
84 await expect(token.burnFrom(alice, targetToken.nestingAccount(), 6n), 'while burning').to.be.fulfilled;
85 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(4n);
86 expect(await token.getBalance(targetToken.nestingAccount())).to.be.equal(0n);
87 expect(await targetToken.getChildren()).to.be.length(0);
88 });
89
90 async function checkNestedAmountState({
91 expectedBalance,
92 childrenShouldPresent,
93 nested,
94 targetNft,
95 }: {
96 expectedBalance: bigint,
97 childrenShouldPresent: boolean,
98 nested: UniqueFTCollection | UniqueRFToken,
99 targetNft: UniqueNFToken,
100 }) {
101 const balance = await nested.getBalance(targetNft.nestingAccount());
102 expect(balance).to.be.equal(expectedBalance);
103
104 const children = await targetNft.getChildren();
105
106 if (childrenShouldPresent) {
107 expect(children[0]).to.be.deep.equal({
108 collectionId: nested.collectionId,
109 tokenId: (nested instanceof UniqueFTCollection) ? 0 : nested.tokenId,
110 });
111 } else {
112 expect(children.length).to.be.equal(0);
113 }
114 }
115
116 function ownerOrAdminUnnestCases(modes: ('ft' | 'nft' | 'rft')[]): {
117 mode: 'ft' | 'nft' | 'rft',
118 sender: string,
119 op: 'transfer' | 'burn',
120 requiredPallets: Pallets[],
121 }[] {
122 const senders = ['owner', 'admin'];
123 const ops = ['transfer', 'burn'];
124
125 const cases = [];
126 for (const mode of modes) {
127 const requiredPallets = (mode === 'rft')
128 ? [Pallets.ReFungible]
129 : [];
130
131 for (const sender of senders) {
132 for (const op of ops) {
133 cases.push({
134 mode: mode as 'ft' | 'nft' | 'rft',
135 sender,
136 op: op as 'transfer' | 'burn',
137 requiredPallets,
138 });
139 }
140 }
141 }
142
143 return cases;
144 }
145
146 ownerOrAdminUnnestCases(['ft', 'rft']).map(testCase =>
147 itSub.ifWithPallets(`[${testCase.mode}]: allows a collection ${testCase.sender} to ${testCase.op} nested token`, testCase.requiredPallets, async({helper}) => {
148 const owner = alice;
149 const admin = bob;
150
151 const unnester = (testCase.sender === 'owner')
152 ? owner
153 : admin;
154
155 const collectionNFT = await helper.nft.mintCollection(owner);
156 await collectionNFT.setPermissions(owner, {nesting: {tokenOwner: true}});
157
158 const collectionNested = await helper[testCase.mode as 'ft' | 'rft'].mintCollection(owner, {
159 limits: {
160 ownerCanTransfer: true,
161 },
162 });
163 await collectionNested.addAdmin(owner, {Substrate: admin.address});
164
165 const targetNft = await collectionNFT.mintToken(owner, {Substrate: charlie.address});
166
167 let nested: UniqueFTCollection | UniqueRFToken;
168 const totalAmount = 5n;
169 const firstUnnestAmount = 2n;
170 const restUnnestAmount = totalAmount - firstUnnestAmount;
171
172 if (collectionNested instanceof UniqueFTCollection) {
173 await collectionNested.mint(owner, totalAmount, {Substrate: charlie.address});
174 nested = collectionNested;
175 } else {
176 nested = await collectionNested.mintToken(owner, totalAmount, {Substrate: charlie.address});
177 }
178
179 // transfer/burn `amount` of nested assets by `unnester`.
180 const doOperationAndCheck = async ({
181 amount,
182 shouldBeNestedAfterOp,
183 }: {
184 amount: bigint,
185 shouldBeNestedAfterOp: boolean,
186 }) => {
187 const nestedBalanceBeforeOp = await nested.getBalance(targetNft.nestingAccount());
188
189 if (testCase.op === 'transfer') {
190 const bobBalanceBeforeOp = await nested.getBalance({Substrate: bob.address});
191
192 await nested.transferFrom(unnester, targetNft.nestingAccount(), {Substrate: bob.address}, amount);
193 expect(await nested.getBalance({Substrate: bob.address})).to.be.equal(bobBalanceBeforeOp + amount);
194 } else {
195 if (nested instanceof UniqueFTCollection) {
196 await nested.burnTokensFrom(unnester, targetNft.nestingAccount(), amount);
197 } else {
198 await nested.burnFrom(unnester, targetNft.nestingAccount(), amount);
199 }
200 }
201
202 await checkNestedAmountState({
203 expectedBalance: nestedBalanceBeforeOp - amount,
204 childrenShouldPresent: shouldBeNestedAfterOp,
205 nested,
206 targetNft,
207 });
208 };
209
210 // Initial setup: nest (fungibles/rft parts).
211 // Check NFT's balance of nested assets and NFT's children.
212 await nested.transfer(charlie, targetNft.nestingAccount(), totalAmount);
213 await checkNestedAmountState({
214 expectedBalance: totalAmount,
215 childrenShouldPresent: true,
216 nested,
217 targetNft,
218 });
219
220 // Transfer/burn only a part of nested assets.
221 // Check that NFT's balance of the nested assets correctly decreased and NFT's children are not changed.
222 await doOperationAndCheck({
223 amount: firstUnnestAmount,
224 shouldBeNestedAfterOp: true,
225 });
226
227 // Transfer/burn all remaining nested assets.
228 // Check that NFT's balance of the nested assets is 0 and NFT has no more children.
229 await doOperationAndCheck({
230 amount: restUnnestAmount,
231 shouldBeNestedAfterOp: false,
232 });
233 }));
234
235 ownerOrAdminUnnestCases(['nft']).map(testCase =>
236 itSub(`[nft]: allows a collection ${testCase.sender} to ${testCase.op} nested token`, async ({helper}) => {
237 const owner = alice;
238 const admin = bob;
239
240 const unnester = (testCase.sender === 'owner')
241 ? owner
242 : admin;
243
244 const collectionNFT = await helper.nft.mintCollection(owner);
245 await collectionNFT.setPermissions(owner, {nesting: {tokenOwner: true}});
246
247 const collectionNested = await helper.nft.mintCollection(owner, {
248 limits: {
249 ownerCanTransfer: true,
250 },
251 });
252 await collectionNested.addAdmin(owner, {Substrate: admin.address});
253
254 const targetNft = await collectionNFT.mintToken(owner, {Substrate: charlie.address});
255 const nested = await collectionNested.mintToken(owner, {Substrate: charlie.address});
256
257 await nested.transfer(charlie, targetNft.nestingAccount());
258 expect(await targetNft.getChildren()).to.be.deep.equal([{
259 collectionId: nested.collectionId,
260 tokenId: nested.tokenId,
261 }]);
262
263 if (testCase.op === 'transfer') {
264 await nested.transferFrom(unnester, targetNft.nestingAccount(), {Substrate: bob.address});
265 } else {
266 await nested.burnFrom(unnester, targetNft.nestingAccount());
267 }
268
269 expect((await targetNft.getChildren()).length).to.be.equal(0);
270 }));
66});271});
67272
68describe('Negative Test: Unnesting', () => {273describe('Negative Test: Unnesting', () => {
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
76 appPromotion,76 appPromotion,
77 testUtils,77 testUtils,
78 ...rmrkPallets,78 ...rmrkPallets,
79 ...collatorSelection,
79 );80 );
80 } else if (chain.eq('QUARTZ by UNIQUE') || chain.eq('SAPPHIRE by UNIQUE')) {81 } else if (chain.eq('QUARTZ by UNIQUE') || chain.eq('SAPPHIRE by UNIQUE')) {
81 requiredPallets.push(82 requiredPallets.push(
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
651 try {651 try {
652 result = await this.signTransaction(sender, this.constructApiCall(extrinsic, params), options, extrinsic) as ITransactionResult;652 result = await this.signTransaction(sender, this.constructApiCall(extrinsic, params), options, extrinsic) as ITransactionResult;
653 events = this.eventHelper.extractEvents(result.result.events);653 events = this.eventHelper.extractEvents(result.result.events);
654 const errorEvent = events.find((event) => event.method == 'ExecutedFailed' || event.method == 'CreatedFailed');
655 if (errorEvent)
656 throw Error(errorEvent.method + ': ' + extrinsic);
654 }657 }
655 catch(e) {658 catch(e) {
656 if(!(e as object).hasOwnProperty('status')) throw e;659 if(!(e as object).hasOwnProperty('status')) throw e;