From a7384514d3debe08c40d7f6ac0e3583e3991979f Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Thu, 08 Dec 2022 08:53:23 +0000 Subject: [PATCH] Merge branch 'develop' into tests/vesting --- --- a/.docker/Dockerfile-try-runtime +++ b/.docker/Dockerfile-try-runtime @@ -46,4 +46,4 @@ echo "Fork from: $REPLICA_FROM\n" && \ cargo build --features=try-runtime,${NETWORK}-runtime --release -CMD cargo run --features=try-runtime,${NETWORK}-runtime --release -- try-runtime --no-spec-check-panic on-runtime-upgrade live --uri $REPLICA_FROM +CMD cargo run --features=try-runtime,${NETWORK}-runtime --release -- try-runtime -ltry-runtime::cli=debug --no-spec-check-panic on-runtime-upgrade live --uri $REPLICA_FROM --- /dev/null +++ b/.docker/additional/Dockerfile-polkadot @@ -0,0 +1,45 @@ +# ===== Rust builder ===== +FROM ubuntu:20.04 as rust-builder +LABEL maintainer="Unique.Network" + +ARG RUST_TOOLCHAIN=nightly-2022-10-09 + +ENV CARGO_HOME="/cargo-home" +ENV PATH="/cargo-home/bin:$PATH" +ENV TZ=UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt-get update && \ + apt-get install -y curl cmake pkg-config libssl-dev git clang llvm libudev-dev protobuf-compiler && \ + apt-get clean && \ + rm -r /var/lib/apt/lists/* + +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none + +RUN rustup toolchain uninstall $(rustup toolchain list) && \ + rustup toolchain install $RUST_TOOLCHAIN && \ + rustup default $RUST_TOOLCHAIN && \ + rustup target list --installed && \ + rustup show +RUN rustup target add wasm32-unknown-unknown --toolchain $RUST_TOOLCHAIN + +RUN mkdir /unique_parachain +WORKDIR /unique_parachain + +# ===== BUILD POLKADOT ===== +FROM rust-builder as builder-polkadot-bin + +ARG POLKADOT_BUILD_BRANCH=release-v0.9.33 + +WORKDIR /unique_parachain + +RUN git clone -b $POLKADOT_BUILD_BRANCH --depth 1 https://github.com/paritytech/polkadot.git && \ + cd polkadot && \ + cargo build --release + +# ===== BIN ====== + +FROM ubuntu:20.04 as builder-polkadot + +COPY --from=builder-polkadot-bin /unique_parachain/polkadot/target/release/polkadot /unique_parachain/polkadot/target/release/polkadot +COPY --from=builder-polkadot-bin /unique_parachain/polkadot/target/release/wbuild/westend-runtime/westend_runtime.compact.compressed.wasm /unique_parachain/polkadot/target/release/wbuild/westend-runtime/westend_runtime.compact.compressed.wasm --- a/.docker/docker-compose.tmp-node.j2 +++ b/.docker/docker-compose.tmp-node.j2 @@ -23,10 +23,12 @@ read_only: true expose: - 9944 + - 9945 - 9933 - 9844 ports: - 127.0.0.1:9944:9944 + - 127.0.0.1:9945:9945 - 127.0.0.1:9933:9933 - 127.0.0.1:9844:9844 logging: --- a/.docker/forkless-config/launch-config-forkless-data.j2 +++ b/.docker/forkless-config/launch-config-forkless-data.j2 @@ -107,7 +107,11 @@ "--rpc-cors=all", "--unsafe-rpc-external", "--unsafe-ws-external", - "-lxcm=trace,parity_ws::handler=debug,jsonrpsee_core=trace,jsonrpsee-core=trace,jsonrpsee_ws_server=debug" + "-lxcm=trace,parity_ws::handler=debug,jsonrpsee_core=trace,jsonrpsee-core=trace,jsonrpsee_ws_server=debug", + "--", + "--port=31335", + "--ws-port=9745", + "--rpc-port=9734" ] }, { --- a/.docker/forkless-config/launch-config-forkless-nodata.j2 +++ b/.docker/forkless-config/launch-config-forkless-nodata.j2 @@ -102,7 +102,11 @@ "--unsafe-rpc-external", "--unsafe-ws-external", "-lxcm=trace,parity_ws::handler=debug,jsonrpsee_core=trace,jsonrpsee-core=trace,jsonrpsee_ws_server=debug", - "--ws-max-connections=1000" + "--ws-max-connections=1000", + "--", + "--port=31335", + "--ws-port=9745", + "--rpc-port=9734" ] }, { @@ -115,7 +119,11 @@ "--unsafe-rpc-external", "--unsafe-ws-external", "-lxcm=trace,parity_ws::handler=debug,jsonrpsee_core=trace,jsonrpsee-core=trace,jsonrpsee_ws_server=debug", - "--ws-max-connections=1000" + "--ws-max-connections=1000", + "--", + "--port=31337", + "--ws-port=9747", + "--rpc-port=9737" ] } ] --- a/.docker/forkless-config/launch-config-node-update-only-v3.j2 +++ b/.docker/forkless-config/launch-config-node-update-only-v3.j2 @@ -102,7 +102,11 @@ "--unsafe-rpc-external", "--unsafe-ws-external", "-lxcm=trace,parity_ws::handler=debug,jsonrpsee_core=trace,jsonrpsee-core=trace,jsonrpsee_ws_server=debug", - "--ws-max-connections=1000" + "--ws-max-connections=1000", + "--", + "--port=31335", + "--ws-port=9745", + "--rpc-port=9734" ] }, { --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -11,7 +11,11 @@ rustfmt: runs-on: [ self-hosted-ci ] steps: + - name: Clean Workspace + uses: AutoModality/action-clean@v1.1.0 - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} - name: Install latest nightly uses: actions-rs/toolchain@v1 with: @@ -28,7 +32,11 @@ yarn_eslint: runs-on: [ self-hosted-ci ] steps: + - name: Clean Workspace + uses: AutoModality/action-clean@v1.1.0 - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} - uses: actions/setup-node@v3 with: node-version: 16 --- a/.github/workflows/node-only-update.yml +++ b/.github/workflows/node-only-update.yml @@ -80,7 +80,7 @@ REPO_URL=${{ github.server_url }}/${{ github.repository }}.git RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }} - POLKADOT_LAUNCH_BRANCH=${{ env.POLKADOT_LAUNCH_BRANCH }} + POLKADOT_LAUNCH_BRANCH=${{ env.POLKADOT_LAUNCH_BRANCH }} POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }} MAINNET_TAG=${{ matrix.mainnet_tag }} MAINNET_BRANCH=${{ matrix.mainnet_branch }} @@ -160,56 +160,35 @@ ref: ${{ matrix.mainnet_branch }} #Checking out head commit path: ${{ matrix.mainnet_branch }} - - name: Run tests before Node Parachain upgrade + - name: Run Parallel tests before Node Parachain upgrade working-directory: ${{ matrix.mainnet_branch }}/tests + if: success() || failure() run: | yarn install yarn add mochawesome node scripts/readyness.js echo "Ready to start tests" yarn polkadot-types - NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-before-${NOW} + NOW=$(date +%s) && yarn testParallel --reporter mochawesome --reporter-options reportFilename=test-parallel-${NOW} env: RPC_URL: http://127.0.0.1:9933/ - - - name: Upload Test Report Before Node upgrade - uses: phoenix-actions/test-reporting@v8 - id: test-report-before - if: success() || failure() # run this step even if previous step failed - with: - name: Tests before node upgrade ${{ matrix.network }} # Name of the check run which will be created - path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-before-*.json # Path to test results - reporter: mochawesome-json - fail-on-error: 'false' - # TODO uncomment thease steps after the merge - #- name: Run Parallel tests before Node Parachain upgrade - # working-directory: ${{ matrix.mainnet_branch }}/tests - # run: | - # yarn install - # yarn add mochawesome - # echo "Ready to start tests" - # yarn polkadot-types - # NOW=$(date +%s) && yarn testParallel --reporter mochawesome --reporter-options reportFilename=test-parallel-${NOW} - # env: - # RPC_URL: http://127.0.0.1:9933/ - - #- name: Upload Parallel Test Report Before Node upgrade - # uses: phoenix-actions/test-reporting@v8 - # id: test-parallel-report-before - # if: success() || failure() # run this step even if previous step failed - # with: - # name: Tests before node upgrade ${{ matrix.network }} # Name of the check run which will be created - # path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-parallel-*.json # Path to test results - # reporter: mochawesome-json - # fail-on-error: 'false' + # - name: Upload Parallel Test Report Before Node upgrade + # uses: phoenix-actions/test-reporting@v8 + # id: test-parallel-report-before + # if: success() || failure() # run this step even if previous step failed + # with: + # name: Tests before node upgrade ${{ matrix.network }} # Name of the check run which will be created + # path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-parallel-*.json # Path to test results + # reporter: mochawesome-json + # fail-on-error: 'false' - # - name: Run Sequential tests before Node Parachain upgrade - # if: success() || failure() - # working-directory: ${{ matrix.mainnet_branch }}/tests - # run: NOW=$(date +%s) && yarn testSequential --reporter mochawesome --reporter-options reportFilename=test-sequential-${NOW} - # env: - # RPC_URL: http://127.0.0.1:9933/ + - name: Run Sequential tests before Node Parachain upgrade + if: success() || failure() + working-directory: ${{ matrix.mainnet_branch }}/tests + run: NOW=$(date +%s) && yarn testSequential --reporter mochawesome --reporter-options reportFilename=test-sequential-${NOW} + env: + RPC_URL: http://127.0.0.1:9933/ # - name: Upload Sequential Test Report Before Node upgrade # uses: phoenix-actions/test-reporting@v8 @@ -220,7 +199,7 @@ # path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-sequential-*.json # Path to test results # reporter: mochawesome-json # fail-on-error: 'false' - + - name: Send SIGUSR1 to polkadot-launch process if: success() || failure() run: | @@ -228,24 +207,37 @@ ContainerID=$(docker ps -aqf "name=node-parachain") PID=$(docker exec node-parachain pidof 'polkadot-launch') sleep 30s - echo -e "Show logs of node-parachain container.\n" - docker logs ${ContainerID} echo -e "\n" echo -e "Restart polkadot-launch process: $PID\n" docker exec node-parachain kill -SIGUSR1 ${PID} echo "SIGUSR1 sent to Polkadot-launch PID: $PID" + sleep 60s + echo -e "Show logs of node-parachain container.\n" docker logs ${ContainerID} - + - name: Get chain logs in case of docker image crashed after Polkadot Launch restart if: failure() # run this step only at failure run: | - docker exec node-parachain cat /polkadot-launch/9944.log - docker exec node-parachain cat /polkadot-launch/9945.log - docker exec node-parachain cat /polkadot-launch/alice.log - docker exec node-parachain cat /polkadot-launch/eve.log - docker exec node-parachain cat /polkadot-launch/dave.log - docker exec node-parachain cat /polkadot-launch/charlie.log + docker exec node-parachain tail -n 1000 /polkadot-launch/9944.log + docker exec node-parachain tail -n 1000 /polkadot-launch/9945.log + docker exec node-parachain tail -n 1000 /polkadot-launch/alice.log + + - name: copy chain log files from container to the host + if: success() || failure() # run this step even if previous step failed + run: | + mkdir -p /tmp/node-only-update + docker cp node-parachain:/polkadot-launch/9944.log /tmp/node-only-update/ + docker cp node-parachain:/polkadot-launch/9945.log /tmp/node-only-update/ + docker cp node-parachain:/polkadot-launch/alice.log /tmp/node-only-update/ + - name: Upload chain log files + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: node-only-update-chain-logs + path: /tmp/node-only-update/ + if-no-files-found: warn + - name: Check if docker logs consist messages related to testing of Node Parachain Upgrade. if: success() run: | @@ -290,43 +282,20 @@ echo "Halting script" exit 0 shell: bash - - ## TODO: Remove next two blocks before switch to Parrallel & Sequental tests. Uncoment commented blocks. - - name: Run tests after Node Parachain upgrade + + - name: Run Parallel tests after Node Parachain upgrade working-directory: ${{ matrix.mainnet_branch }}/tests + if: success() || failure() # run this step even if previous step failed run: | yarn install yarn add mochawesome node scripts/readyness.js echo "Ready to start tests" yarn polkadot-types - NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-after-${NOW} + NOW=$(date +%s) && yarn testParallel --reporter mochawesome --reporter-options reportFilename=test-parallel-${NOW} env: RPC_URL: http://127.0.0.1:9933/ - - name: Test Report After Node upgrade - uses: phoenix-actions/test-reporting@v8 - id: test-report-after - if: success() || failure() # run this step even if previous step failed - with: - name: Tests after node upgrade ${{ matrix.network }} # Name of the check run which will be created - path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-after-*.json # Path to test results - reporter: mochawesome-json - fail-on-error: 'false' - - # TODO uncomment thease steps after the merge - #- name: Run Parallel tests after Node Parachain upgrade - # working-directory: ${{ matrix.mainnet_branch }}/tests - # run: | - # yarn install - # yarn add mochawesome - # node scripts/readyness.js - # echo "Ready to start tests" - # yarn polkadot-types - # NOW=$(date +%s) && yarn testParallel --reporter mochawesome --reporter-options reportFilename=test-parallel-${NOW} - # env: - # RPC_URL: http://127.0.0.1:9933/ - #- name: Test Report Parallel After Node upgrade # uses: phoenix-actions/test-reporting@v8 # id: test-report-parallel-after @@ -336,14 +305,14 @@ # path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-parallel-*.json # Path to test results # reporter: mochawesome-json # fail-on-error: 'false' - - #- name: Run Sequential tests after Node Parachain upgrade - # if: success() || failure() - # working-directory: ${{ matrix.mainnet_branch }}/tests - # run: NOW=$(date +%s) && yarn testSequential --reporter mochawesome --reporter-options reportFilename=test-sequential-${NOW} - # env: - # RPC_URL: http://127.0.0.1:9933/ + - name: Run Sequential tests after Node Parachain upgrade + if: success() || failure() + working-directory: ${{ matrix.mainnet_branch }}/tests + run: NOW=$(date +%s) && yarn testSequential --reporter mochawesome --reporter-options reportFilename=test-sequential-${NOW} + env: + RPC_URL: http://127.0.0.1:9933/ + #- name: Upload Sequential Test Report After Node upgrade # uses: phoenix-actions/test-reporting@v8 # id: test-sequential-report-after @@ -353,7 +322,6 @@ # path: ${{ matrix.mainnet_branch }}/tests/mochawesome-report/test-sequential-*.json # Path to test results # reporter: mochawesome-json # fail-on-error: 'false' - - name: Stop running containers if: always() # run this step always --- a/.maintain/scripts/generate_abi.sh +++ b/.maintain/scripts/generate_abi.sh @@ -4,6 +4,7 @@ dir=$PWD tmp=$(mktemp -d) +echo "Tmp file: $tmp/input.sol" cd $tmp cp $dir/$INPUT input.sol solcjs --abi -p input.sol --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -137,9 +137,9 @@ [[package]] name = "array-bytes" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a913633b0c922e6b745072795f50d90ebea78ba31a57e2ac8c2fc7b50950949" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" [[package]] name = "arrayref" @@ -196,30 +196,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ - "concurrent-queue", + "concurrent-queue 1.2.4", "event-listener", "futures-core", ] [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", - "concurrent-queue", + "concurrent-queue 2.0.0", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", @@ -232,16 +232,16 @@ [[package]] name = "async-io" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" dependencies = [ + "async-lock", "autocfg", - "concurrent-queue", + "concurrent-queue 1.2.4", "futures-lite", "libc", "log", - "once_cell", "parking", "polling", "slab", @@ -340,9 +340,9 @@ [[package]] name = "asynchronous-codec" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" +checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182" dependencies = [ "bytes", "futures-sink", @@ -595,16 +595,16 @@ "funty 2.0.0", "radium 0.7.0", "tap", - "wyz 0.5.0", + "wyz 0.5.1", ] [[package]] name = "blake2" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" +checksum = "b12e5fd123190ce1c2e559308a94c9bacad77907d4c6005d9e58fe1a0689e55e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -614,7 +614,7 @@ checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" dependencies = [ "arrayvec 0.4.12", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] @@ -625,7 +625,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.2", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] @@ -636,21 +636,21 @@ dependencies = [ "arrayref", "arrayvec 0.7.2", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] name = "blake3" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +checksum = "895adc16c8b3273fbbc32685a7d55227705eda08c01e77704020f3491924b44b" dependencies = [ "arrayref", "arrayvec 0.7.2", "cc", "cfg-if 1.0.0", - "constant_time_eq", - "digest 0.10.5", + "constant_time_eq 0.2.4", + "digest 0.10.6", ] [[package]] @@ -769,9 +769,9 @@ [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -787,9 +787,9 @@ [[package]] name = "bytes" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bzip2-sys" @@ -841,9 +841,9 @@ [[package]] name = "cc" -version = "1.0.73" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" dependencies = [ "jobserver", ] @@ -911,9 +911,9 @@ [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", @@ -973,7 +973,7 @@ dependencies = [ "glob", "libc", - "libloading 0.7.3", + "libloading 0.7.4", ] [[package]] @@ -1017,9 +1017,9 @@ [[package]] name = "cmake" -version = "0.1.48" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" dependencies = [ "cc", ] @@ -1048,9 +1048,9 @@ [[package]] name = "comfy-table" -version = "6.1.1" +version = "6.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3d16bb3da60be2f7c7acfc438f2ae6f3496897ce68c291d0509bb67b4e248e" +checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" dependencies = [ "strum", "strum_macros", @@ -1058,22 +1058,21 @@ ] [[package]] -name = "concat-idents" -version = "1.1.3" +name = "concurrent-queue" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6f90860248d75014b7b103db8fee4f291c07bfb41306cdf77a0a5ab7a10d2f" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ - "quote", - "syn", + "cache-padded", ] [[package]] name = "concurrent-queue" -version = "1.2.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" dependencies = [ - "cache-padded", + "crossbeam-utils", ] [[package]] @@ -1102,6 +1101,12 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] +name = "constant_time_eq" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" + +[[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1152,18 +1157,18 @@ [[package]] name = "cranelift-bforest" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a" +checksum = "52056f6d0584484b57fa6c1a65c1fcb15f3780d8b6a758426d9e3084169b2ddd" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf" +checksum = "18fed94c8770dc25d01154c3ffa64ed0b3ba9d583736f305fed7beebe5d9cf74" dependencies = [ "arrayvec 0.7.2", "bumpalo", @@ -1181,33 +1186,33 @@ [[package]] name = "cranelift-codegen-meta" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5" +checksum = "1c451b81faf237d11c7e4f3165eeb6bac61112762c5cfe7b4c0fb7241474358f" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e" +checksum = "e7c940133198426d26128f08be2b40b0bd117b84771fd36798969c4d712d81fc" [[package]] name = "cranelift-entity" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103" +checksum = "87a0f1b2fdc18776956370cf8d9b009ded3f855350c480c1c52142510961f352" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc" +checksum = "34897538b36b216cc8dd324e73263596d51b8cf610da6498322838b2546baf8a" dependencies = [ "cranelift-codegen", "log", @@ -1217,15 +1222,15 @@ [[package]] name = "cranelift-isle" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293" +checksum = "1b2629a569fae540f16a76b70afcc87ad7decb38dc28fa6c648ac73b51e78470" [[package]] name = "cranelift-native" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4" +checksum = "20937dab4e14d3e225c5adfc9c7106bafd4ac669bdb43027b911ff794c6fb318" dependencies = [ "cranelift-codegen", "libc", @@ -1234,9 +1239,9 @@ [[package]] name = "cranelift-wasm" -version = "0.88.1" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c699873f7b30bc5f20dd03a796b4183e073a46616c91704792ec35e45d13f913" +checksum = "80fc2288957a94fd342a015811479de1837850924166d1f1856d8406e6f3609b" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1280,22 +1285,22 @@ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1303,9 +1308,9 @@ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1872,9 +1877,9 @@ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" dependencies = [ "cc", "cxxbridge-flags", @@ -1884,9 +1889,9 @@ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" dependencies = [ "cc", "codespan-reporting", @@ -1899,15 +1904,15 @@ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ "proc-macro2", "quote", @@ -1993,9 +1998,9 @@ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -2216,9 +2221,9 @@ [[package]] name = "env_logger" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -2332,9 +2337,8 @@ [[package]] name = "evm-coder" -version = "0.1.4" +version = "0.1.5" dependencies = [ - "concat-idents", "ethereum", "evm-coder-procedural", "evm-core", @@ -2352,7 +2356,7 @@ [[package]] name = "evm-coder-procedural" -version = "0.2.1" +version = "0.2.2" dependencies = [ "Inflector", "hex", @@ -2479,7 +2483,7 @@ [[package]] name = "fc-consensus" version = "2.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "async-trait", "fc-db", @@ -2498,14 +2502,16 @@ [[package]] name = "fc-db" version = "2.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "fp-storage", "kvdb-rocksdb", + "log", "parity-db", "parity-scale-codec 3.2.1", "parking_lot 0.12.1", "sc-client-db", + "sp-blockchain", "sp-core", "sp-database", "sp-runtime", @@ -2514,7 +2520,7 @@ [[package]] name = "fc-mapping-sync" version = "2.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "fc-db", "fp-consensus", @@ -2531,13 +2537,15 @@ [[package]] name = "fc-rpc" version = "2.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "ethereum-types", "evm", "fc-db", "fc-rpc-core", + "fp-ethereum", + "fp-evm", "fp-rpc", "fp-storage", "futures 0.3.25", @@ -2545,12 +2553,11 @@ "jsonrpsee", "libsecp256k1", "log", - "lru 0.7.8", + "lru 0.8.1", "parity-scale-codec 3.2.1", "prometheus", "rand 0.8.5", "rlp", - "rustc-hex", "sc-client-api", "sc-network", "sc-network-common", @@ -2573,7 +2580,7 @@ [[package]] name = "fc-rpc-core" version = "1.1.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "ethereum-types", @@ -2713,7 +2720,7 @@ [[package]] name = "fp-consensus" version = "2.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "parity-scale-codec 3.2.1", @@ -2723,9 +2730,24 @@ ] [[package]] +name = "fp-ethereum" +version = "1.0.0-dev" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm", + "frame-support", + "num_enum", + "parity-scale-codec 3.2.1", + "sp-core", + "sp-std", +] + +[[package]] name = "fp-evm" version = "3.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "evm", "frame-support", @@ -2739,7 +2761,7 @@ [[package]] name = "fp-evm-mapping" version = "0.1.0" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "frame-support", "sp-core", @@ -2748,7 +2770,7 @@ [[package]] name = "fp-rpc" version = "3.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "ethereum-types", @@ -2765,7 +2787,7 @@ [[package]] name = "fp-self-contained" version = "1.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "frame-support", @@ -2773,17 +2795,16 @@ "parity-util-mem", "scale-info", "serde", - "sp-debug-derive", - "sp-io", "sp-runtime", ] [[package]] name = "fp-storage" version = "2.0.0" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "parity-scale-codec 3.2.1", + "serde", ] [[package]] @@ -3040,9 +3061,9 @@ [[package]] name = "fs-err" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64db3e262960f0662f43a6366788d5f10f7f244b8f7d7d987f560baf5ded5c50" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] name = "fs-swap" @@ -3512,9 +3533,9 @@ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -3536,9 +3557,9 @@ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" dependencies = [ "http", "hyper", @@ -3551,9 +3572,9 @@ [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3662,9 +3683,9 @@ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -3706,9 +3727,19 @@ [[package]] name = "io-lifetimes" -version = "0.7.4" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074" + +[[package]] +name = "io-lifetimes" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e481ccbe3dea62107216d0d1138bb8ad8e5e5c43009a098bd1990272c497b0" +checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] [[package]] name = "ip_network" @@ -3718,9 +3749,9 @@ [[package]] name = "ipconfig" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98" +checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" dependencies = [ "socket2", "widestring", @@ -3730,9 +3761,9 @@ [[package]] name = "ipnet" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "itertools" @@ -3925,9 +3956,12 @@ [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "kusama-runtime" @@ -4113,9 +4147,9 @@ [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if 1.0.0", "winapi", @@ -4123,9 +4157,9 @@ [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libp2p" @@ -4757,6 +4791,12 @@ checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" [[package]] +name = "linux-raw-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121" + +[[package]] name = "lock_api" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4880,18 +4920,18 @@ [[package]] name = "memfd" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "480b5a5de855d11ff13195950bdc8b98b5e942ef47afc447f6615cdcc4e15d80" +checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" dependencies = [ - "rustix", + "rustix 0.36.2", ] [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] @@ -4906,6 +4946,15 @@ ] [[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] name = "memory-db" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5020,7 +5069,7 @@ "blake2s_simd", "blake3", "core2", - "digest 0.10.5", + "digest 0.10.6", "multihash-derive", "sha2 0.10.6", "sha3", @@ -5291,15 +5340,36 @@ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", ] [[package]] +name = "num_enum" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "num_threads" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5322,9 +5392,9 @@ [[package]] name = "once_cell" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opal-runtime" @@ -5577,9 +5647,9 @@ [[package]] name = "os_str_bytes" -version = "6.3.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "owning_ref" @@ -5724,7 +5794,7 @@ [[package]] name = "pallet-base-fee" version = "1.0.0" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "fp-evm", "frame-support", @@ -5831,7 +5901,7 @@ [[package]] name = "pallet-common" -version = "0.1.11" +version = "0.1.12" dependencies = [ "ethereum", "evm-coder", @@ -5940,12 +6010,13 @@ [[package]] name = "pallet-ethereum" version = "4.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ "ethereum", "ethereum-types", "evm", "fp-consensus", + "fp-ethereum", "fp-evm", "fp-evm-mapping", "fp-rpc", @@ -5953,14 +6024,12 @@ "fp-storage", "frame-support", "frame-system", - "log", "pallet-evm", "pallet-timestamp", "parity-scale-codec 3.2.1", "rlp", "scale-info", "serde", - "sha3", "sp-io", "sp-runtime", "sp-std", @@ -5969,8 +6038,9 @@ [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4" +source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0" dependencies = [ + "environmental", "evm", "fp-evm", "fp-evm-mapping", @@ -5986,7 +6056,6 @@ "rlp", "scale-info", "serde", - "sha3", "sp-core", "sp-io", "sp-runtime", @@ -7163,9 +7232,9 @@ [[package]] name = "pest" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a" +checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" dependencies = [ "thiserror", "ucd-trie", @@ -7173,9 +7242,9 @@ [[package]] name = "pest_derive" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2" +checksum = "d5fd9bc6500181952d34bd0b2b0163a54d794227b498be0b7afa7698d0a7b18f" dependencies = [ "pest", "pest_generator", @@ -7183,9 +7252,9 @@ [[package]] name = "pest_generator" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db" +checksum = "d2610d5ac5156217b4ff8e46ddcef7cdf44b273da2ac5bca2ecbfa86a330e7c4" dependencies = [ "pest", "pest_meta", @@ -7196,9 +7265,9 @@ [[package]] name = "pest_meta" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d" +checksum = "824749bf7e21dd66b36fbe26b3f45c713879cccd4a009a917ab8e045ca8246fe" dependencies = [ "once_cell", "pest", @@ -8556,9 +8625,19 @@ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" +dependencies = [ + "proc-macro2", + "syn", +] [[package]] name = "primitive-types" @@ -8682,12 +8761,12 @@ [[package]] name = "prost" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7" +checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" dependencies = [ "bytes", - "prost-derive 0.11.0", + "prost-derive 0.11.2", ] [[package]] @@ -8714,9 +8793,9 @@ [[package]] name = "prost-build" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f835c582e6bd972ba8347313300219fed5bfa52caf175298d860b61ff6069bb" +checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511" dependencies = [ "bytes", "heck", @@ -8725,9 +8804,11 @@ "log", "multimap", "petgraph", - "prost 0.11.0", - "prost-types 0.11.1", + "prettyplease", + "prost 0.11.2", + "prost-types 0.11.2", "regex", + "syn", "tempfile", "which", ] @@ -8760,9 +8841,9 @@ [[package]] name = "prost-derive" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364" +checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" dependencies = [ "anyhow", "itertools", @@ -8783,12 +8864,12 @@ [[package]] name = "prost-types" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dfaa718ad76a44b3415e6c4d53b17c8f99160dcb3a99b10470fce8ad43f6e3e" +checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" dependencies = [ "bytes", - "prost 0.11.0", + "prost 0.11.2", ] [[package]] @@ -9039,11 +9120,10 @@ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ - "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -9051,9 +9131,9 @@ [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -9096,18 +9176,18 @@ [[package]] name = "ref-cast" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a733f1746c929b4913fe48f8697fcf9c55e3304ba251a79ffb41adfeaf49c2" +checksum = "53b15debb4f9d60d767cd8ca9ef7abb2452922f3214671ff052defc7f3502c44" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5887de4a01acafd221861463be6113e6e87275e79804e56779f4cdc131c60368" +checksum = "abfa8511e9e94fd3de6585a3d3cd00e01ed556dc9814829280af0e8dc72a8f36" dependencies = [ "proc-macro2", "quote", @@ -9128,9 +9208,9 @@ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -9148,9 +9228,9 @@ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remote-externalities" @@ -9426,19 +9506,33 @@ [[package]] name = "rustix" -version = "0.35.12" +version = "0.35.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985947f9b6423159c4726323f373be0a21bdb514c5af06a849cb3d2dce2d01e8" +checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9" dependencies = [ "bitflags", "errno", - "io-lifetimes", + "io-lifetimes 0.7.5", "libc", - "linux-raw-sys", - "windows-sys 0.36.1", + "linux-raw-sys 0.0.46", + "windows-sys 0.42.0", ] [[package]] +name = "rustix" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "203974af07ea769452490ee8de3e5947971efc3a090dca8a779dd432d3fa46a7" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes 1.0.1", + "libc", + "linux-raw-sys 0.1.2", + "windows-sys 0.42.0", +] + +[[package]] name = "rustls" version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -9976,7 +10070,7 @@ "once_cell", "parity-scale-codec 3.2.1", "parity-wasm 0.45.0", - "rustix", + "rustix 0.35.13", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -10135,8 +10229,8 @@ "futures 0.3.25", "libp2p", "log", - "prost 0.11.0", - "prost-build 0.11.1", + "prost 0.11.2", + "prost-build 0.11.2", "sc-client-api", "sc-network-common", "sp-blockchain", @@ -10612,9 +10706,9 @@ [[package]] name = "scale-info" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333af15b02563b8182cd863f925bd31ef8fa86a0e095d30c091956057d436153" +checksum = "88d8a765117b237ef233705cc2cc4c6a27fccd46eea6ef0c8c6dae5f3ef407f8" dependencies = [ "bitvec 1.0.1", "cfg-if 1.0.0", @@ -10626,9 +10720,9 @@ [[package]] name = "scale-info-derive" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f56acbd0743d29ffa08f911ab5397def774ad01bab3786804cf6ee057fb5e1" +checksum = "cdcd47b380d8c4541044e341dcd9475f55ba37ddc50c908d945fc036a8642496" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -10804,9 +10898,9 @@ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", @@ -10843,7 +10937,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -10879,7 +10973,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -10888,7 +10982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "keccak", ] @@ -10956,9 +11050,9 @@ [[package]] name = "similar" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" dependencies = [ "bstr", "unicode-segmentation", @@ -11018,9 +11112,9 @@ [[package]] name = "snap" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451" +checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" [[package]] name = "snow" @@ -11318,7 +11412,7 @@ dependencies = [ "blake2", "byteorder", - "digest 0.10.5", + "digest 0.10.6", "sha2 0.10.6", "sha3", "sp-std", @@ -11816,9 +11910,9 @@ [[package]] name = "ss58-registry" -version = "1.33.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab7554f8a8b6f8d71cd5a8e6536ef116e2ce0504cf97ebf16311d58065dc8a6" +checksum = "fa0813c10b9dbdc842c2305f949f724c64866e4ef4d09c9151e96f6a2106773c" dependencies = [ "Inflector", "num-format", @@ -12141,9 +12235,9 @@ [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" @@ -12368,9 +12462,9 @@ [[package]] name = "tokio" -version = "1.21.2" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ "autocfg", "bytes", @@ -12694,7 +12788,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if 1.0.0", - "digest 0.10.5", + "digest 0.10.6", "rand 0.8.5", "static_assertions", ] @@ -13340,9 +13434,9 @@ [[package]] name = "wasmtime" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f511c4917c83d04da68333921107db75747c4e11a2f654a8e909cc5e0520dc" +checksum = "4ad5af6ba38311282f2a21670d96e78266e8c8e2f38cbcd52c254df6ccbc7731" dependencies = [ "anyhow", "bincode", @@ -13368,18 +13462,18 @@ [[package]] name = "wasmtime-asm-macros" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39bf3debfe744bf19dd3732990ce6f8c0ced7439e2370ba4e1d8f5a3660a3178" +checksum = "45de63ddfc8b9223d1adc8f7b2ee5f35d1f6d112833934ad7ea66e4f4339e597" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "wasmtime-cache" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece42fa4676a263f7558cdaaf5a71c2592bebcbac22a0580e33cf3406c103da2" +checksum = "bcd849399d17d2270141cfe47fa0d91ee52d5f8ea9b98cf7ddde0d53e5f79882" dependencies = [ "anyhow", "base64", @@ -13387,7 +13481,7 @@ "directories-next", "file-per-thread-logger", "log", - "rustix", + "rustix 0.35.13", "serde", "sha2 0.9.9", "toml", @@ -13397,9 +13491,9 @@ [[package]] name = "wasmtime-cranelift" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058217e28644b012bdcdf0e445f58d496d78c2e0b6a6dd93558e701591dad705" +checksum = "4bd91339b742ff20bfed4532a27b73c86b5bcbfedd6bea2dcdf2d64471e1b5c6" dependencies = [ "anyhow", "cranelift-codegen", @@ -13418,9 +13512,9 @@ [[package]] name = "wasmtime-environ" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7af06848df28b7661471d9a80d30a973e0f401f2e3ed5396ad7e225ed217047" +checksum = "ebb881c61f4f627b5d45c54e629724974f8a8890d455bcbe634330cc27309644" dependencies = [ "anyhow", "cranelift-entity", @@ -13437,9 +13531,9 @@ [[package]] name = "wasmtime-jit" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9028fb63a54185b3c192b7500ef8039c7bb8d7f62bfc9e7c258483a33a3d13bb" +checksum = "1985c628011fe26adf5e23a5301bdc79b245e0e338f14bb58b39e4e25e4d8681" dependencies = [ "addr2line", "anyhow", @@ -13450,7 +13544,7 @@ "log", "object", "rustc-demangle", - "rustix", + "rustix 0.35.13", "serde", "target-lexicon", "thiserror", @@ -13462,20 +13556,20 @@ [[package]] name = "wasmtime-jit-debug" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e82d4ef93296785de7efca92f7679dc67fe68a13b625a5ecc8d7503b377a37" +checksum = "f671b588486f5ccec8c5a3dba6b4c07eac2e66ab8c60e6f4e53717c77f709731" dependencies = [ "object", "once_cell", - "rustix", + "rustix 0.35.13", ] [[package]] name = "wasmtime-runtime" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0e9bea7d517d114fe66b930b2124ee086516ee93eeebfd97f75f366c5b0553" +checksum = "ee8f92ad4b61736339c29361da85769ebc200f184361959d1792832e592a1afd" dependencies = [ "anyhow", "cc", @@ -13485,10 +13579,10 @@ "log", "mach", "memfd", - "memoffset", + "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix", + "rustix 0.35.13", "thiserror", "wasmtime-asm-macros", "wasmtime-environ", @@ -13498,9 +13592,9 @@ [[package]] name = "wasmtime-types" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b83e93ed41b8fdc936244cfd5e455480cf1eca1fd60c78a0040038b4ce5075" +checksum = "d23d61cb4c46e837b431196dd06abb11731541021916d03476a178b54dc07aeb" dependencies = [ "cranelift-entity", "serde", @@ -13841,9 +13935,9 @@ [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] @@ -13856,9 +13950,9 @@ [[package]] name = "wyz" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -19,4 +19,4 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } --- a/crates/evm-coder/CHANGELOG.md +++ b/crates/evm-coder/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. +## [v0.1.5] - 2022-11-30 + +### Added +- Derive macro to support structures and enums. ## [v0.1.4] - 2022-11-02 --- a/crates/evm-coder/Cargo.toml +++ b/crates/evm-coder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evm-coder" -version = "0.1.4" +version = "0.1.5" license = "GPLv3" edition = "2021" @@ -19,14 +19,13 @@ # We have tuple-heavy code in solidity.rs impl-trait-for-tuples = "0.2.2" -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [dev-dependencies] # We want to assert some large binary blobs equality in tests hex = "0.4.3" hex-literal = "0.3.4" similar-asserts = "1.4.2" -concat-idents = "1.1.3" trybuild = "1.0" [features] --- a/crates/evm-coder/procedural/Cargo.toml +++ b/crates/evm-coder/procedural/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evm-coder-procedural" -version = "0.2.1" +version = "0.2.2" license = "GPLv3" edition = "2021" --- /dev/null +++ b/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs @@ -0,0 +1,211 @@ +use quote::quote; + +pub fn impl_solidity_option<'a>( + name: &proc_macro2::Ident, + enum_options: impl Iterator, +) -> proc_macro2::TokenStream { + let enum_options = enum_options.map(|opt| { + let s = name.to_string() + "." + opt.to_string().as_str(); + let as_string = proc_macro2::Literal::string(s.as_str()); + quote!(#name::#opt => #as_string,) + }); + quote!( + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityEnum for #name { + fn solidity_option(&self) -> &str { + match self { + #(#enum_options)* + } + } + } + ) +} + +pub fn impl_enum_from_u8<'a>( + name: &proc_macro2::Ident, + enum_options: impl Iterator, +) -> proc_macro2::TokenStream { + let error_str = format!("Value not convertible into enum \"{name}\""); + let error_str = proc_macro2::Literal::string(&error_str); + let enum_options = enum_options.enumerate().map(|(i, opt)| { + let n = proc_macro2::Literal::u8_suffixed(i as u8); + quote! {#n => Ok(#name::#opt),} + }); + + quote!( + impl TryFrom for #name { + type Error = &'static str; + + fn try_from(value: u8) -> ::core::result::Result { + const err: &'static str = #error_str; + match value { + #(#enum_options)* + _ => Err(err) + } + } + } + ) +} + +pub fn impl_enum_abi_type(name: &syn::Ident) -> proc_macro2::TokenStream { + quote! { + impl ::evm_coder::abi::AbiType for #name { + const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = ::SIGNATURE; + + fn is_dynamic() -> bool { + ::is_dynamic() + } + fn size() -> usize { + ::size() + } + } + } +} + +pub fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream { + quote!( + impl ::evm_coder::abi::AbiRead for #name { + fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result { + Ok( + ::abi_read(reader)? + .try_into()? + ) + } + } + ) +} + +pub fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream { + quote!( + impl ::evm_coder::abi::AbiWrite for #name { + fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) { + ::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer); + } + } + ) +} + +pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream { + quote!( + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityTypeName for #name { + fn solidity_name( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}", tc.collect_struct::()) + } + + fn is_simple() -> bool { + true + } + + fn solidity_default( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default())) + } + } + ) +} + +pub fn impl_enum_solidity_struct_collect<'a>( + name: &syn::Ident, + enum_options: impl Iterator, + option_count: usize, + enum_options_docs: impl Iterator>>, + docs: &[proc_macro2::TokenStream], +) -> proc_macro2::TokenStream { + let string_name = name.to_string(); + let enum_options = enum_options + .zip(enum_options_docs) + .enumerate() + .map(|(i, (opt, doc))| { + let opt = proc_macro2::Literal::string(opt.to_string().as_str()); + let doc = doc.expect("Doc parsing error"); + let comma = if i != option_count - 1 { "," } else { "" }; + quote! { + #(#doc)* + writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option"); + } + }); + + quote!( + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::StructCollect for #name { + fn name() -> String { + #string_name.into() + } + + fn declaration() -> String { + use std::fmt::Write; + + let mut str = String::new(); + #(#docs)* + writeln!(str, "enum {} {{", ::name()).unwrap(); + #(#enum_options)* + writeln!(str, "}}").unwrap(); + str + } + } + ) +} + +pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result { + let mut count = 0; + for v in de.variants.iter() { + if !v.fields.is_empty() { + return Err(syn::Error::new( + v.ident.span(), + "Enumeration parameters should not have fields", + )); + } else if v.discriminant.is_some() { + return Err(syn::Error::new( + v.ident.span(), + "Enumeration options should not have an explicit specified value", + )); + } else { + count += 1; + } + } + + Ok(count) +} + +pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> { + let mut has_repr = false; + for attr in attrs.iter() { + if attr.path.is_ident("repr") { + has_repr = true; + let meta = attr.parse_meta()?; + check_meta_u8(&meta)?; + } + } + + if !has_repr { + return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\"")); + } + + Ok(()) +} + +fn check_meta_u8(meta: &syn::Meta) -> Result<(), syn::Error> { + if let syn::Meta::List(p) = meta { + for nm in p.nested.iter() { + if let syn::NestedMeta::Meta(syn::Meta::Path(p)) = nm { + if !p.is_ident("u8") { + return Err(syn::Error::new( + p.segments + .first() + .expect("repr segments are empty") + .ident + .span(), + "Enum is not \"repr(u8)\"", + )); + } + } + } + } + Ok(()) +} --- /dev/null +++ b/crates/evm-coder/procedural/src/abi_derive/derive_struct.rs @@ -0,0 +1,260 @@ +use super::extract_docs; +use quote::quote; + +pub fn tuple_type<'a>( + field_types: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let field_types = field_types.map(|ty| quote!(#ty,)); + quote! {(#(#field_types)*)} +} + +pub fn tuple_ref_type<'a>( + field_types: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let field_types = field_types.map(|ty| quote!(&#ty,)); + quote! {(#(#field_types)*)} +} + +pub fn tuple_data_as_ref( + is_named_fields: bool, + field_names: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let field_names = field_names.enumerate().map(|(i, field)| { + if is_named_fields { + quote!(&self.#field,) + } else { + let field = proc_macro2::Literal::usize_unsuffixed(i); + quote!(&self.#field,) + } + }); + quote! {(#(#field_names)*)} +} + +pub fn tuple_names( + is_named_fields: bool, + field_names: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let field_names = field_names.enumerate().map(|(i, field)| { + if is_named_fields { + quote!(#field,) + } else { + let field = proc_macro2::Ident::new( + format!("field{}", i).as_str(), + proc_macro2::Span::call_site(), + ); + quote!(#field,) + } + }); + quote! {(#(#field_names)*)} +} + +pub fn struct_from_tuple( + name: &syn::Ident, + is_named_fields: bool, + field_names: impl Iterator + Clone, +) -> proc_macro2::TokenStream { + let field_names = field_names.enumerate().map(|(i, field)| { + if is_named_fields { + quote!(#field,) + } else { + let field = proc_macro2::Ident::new( + format!("field{}", i).as_str(), + proc_macro2::Span::call_site(), + ); + quote!(#field,) + } + }); + + if is_named_fields { + quote! {#name {#(#field_names)*}} + } else { + quote! {#name (#(#field_names)*)} + } +} + +pub fn map_field_to_name(field: (usize, &syn::Field)) -> syn::Ident { + match field.1.ident.as_ref() { + Some(name) => name.clone(), + None => { + let mut name = "field".to_string(); + name.push_str(field.0.to_string().as_str()); + syn::Ident::new(name.as_str(), proc_macro2::Span::call_site()) + } + } +} + +pub fn map_field_to_type(field: &syn::Field) -> &syn::Type { + &field.ty +} + +pub fn map_field_to_doc(field: &syn::Field) -> syn::Result> { + extract_docs(&field.attrs, true) +} + +pub fn impl_can_be_placed_in_vec(ident: &syn::Ident) -> proc_macro2::TokenStream { + quote! { + impl ::evm_coder::sealed::CanBePlacedInVec for #ident {} + } +} + +pub fn impl_struct_abi_type( + name: &syn::Ident, + tuple_type: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + quote! { + impl ::evm_coder::abi::AbiType for #name { + const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <#tuple_type as ::evm_coder::abi::AbiType>::SIGNATURE; + fn is_dynamic() -> bool { + <#tuple_type as ::evm_coder::abi::AbiType>::is_dynamic() + } + fn size() -> usize { + <#tuple_type as ::evm_coder::abi::AbiType>::size() + } + } + } +} + +pub fn impl_struct_abi_read( + name: &syn::Ident, + tuple_type: proc_macro2::TokenStream, + tuple_names: proc_macro2::TokenStream, + struct_from_tuple: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + quote!( + impl ::evm_coder::abi::AbiRead for #name { + fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result { + let #tuple_names = <#tuple_type as ::evm_coder::abi::AbiRead>::abi_read(reader)?; + Ok(#struct_from_tuple) + } + } + ) +} + +pub fn impl_struct_abi_write( + name: &syn::Ident, + _is_named_fields: bool, + tuple_type: proc_macro2::TokenStream, + tuple_data: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + quote!( + impl ::evm_coder::abi::AbiWrite for #name { + fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) { + <#tuple_type as ::evm_coder::abi::AbiWrite>::abi_write(&#tuple_data, writer) + } + } + ) +} + +pub fn impl_struct_solidity_type<'a>( + name: &syn::Ident, + field_types: impl Iterator + Clone, + params_count: usize, +) -> proc_macro2::TokenStream { + let len = proc_macro2::Literal::usize_suffixed(params_count); + quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityType for #name { + fn names(tc: &::evm_coder::solidity::TypeCollector) -> Vec { + let mut collected = + Vec::with_capacity(::len()); + #({ + let mut out = String::new(); + <#field_types as ::evm_coder::solidity::SolidityTypeName>::solidity_name(&mut out, tc) + .expect("no fmt error"); + collected.push(out); + })* + collected + } + + fn len() -> usize { + #len + } + } + } +} + +pub fn impl_struct_solidity_type_name<'a>( + name: &syn::Ident, + field_types: impl Iterator + Clone, + params_count: usize, +) -> proc_macro2::TokenStream { + let arg_dafaults = field_types.enumerate().map(|(i, ty)| { + let mut defult_value = quote!(<#ty as ::evm_coder::solidity::SolidityTypeName + >::solidity_default(writer, tc)?;); + let last_item = params_count - 1; + if i != last_item { + defult_value.extend(quote! {write!(writer, ",")?;}) + } + defult_value + }); + + quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::SolidityTypeName for #name { + fn solidity_name( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}", tc.collect_struct::()) + } + + fn is_simple() -> bool { + false + } + + fn solidity_default( + writer: &mut impl ::core::fmt::Write, + tc: &::evm_coder::solidity::TypeCollector, + ) -> ::core::fmt::Result { + write!(writer, "{}(", tc.collect_struct::())?; + + #(#arg_dafaults)* + + write!(writer, ")") + } + } + } +} + +pub fn impl_struct_solidity_struct_collect<'a>( + name: &syn::Ident, + field_names: impl Iterator + Clone, + field_types: impl Iterator + Clone, + field_docs: impl Iterator>> + Clone, + docs: &[proc_macro2::TokenStream], +) -> syn::Result { + let string_name = name.to_string(); + let name_type = field_names + .into_iter() + .zip(field_types) + .zip(field_docs) + .map(|((name, ty), doc)| { + let field_docs = doc.expect("Doc parse error"); + let name = format!("{}", name); + quote!( + #(#field_docs)* + write!(str, "\t{} ", <#ty as ::evm_coder::solidity::StructCollect>::name()).unwrap(); + writeln!(str, "{};", #name).unwrap(); + ) + }); + + Ok(quote! { + #[cfg(feature = "stubgen")] + impl ::evm_coder::solidity::StructCollect for #name { + fn name() -> String { + #string_name.into() + } + + fn declaration() -> String { + use std::fmt::Write; + + let mut str = String::new(); + #(#docs)* + writeln!(str, "struct {} {{", Self::name()).unwrap(); + #(#name_type)* + writeln!(str, "}}").unwrap(); + str + } + } + }) +} --- /dev/null +++ b/crates/evm-coder/procedural/src/abi_derive/mod.rs @@ -0,0 +1,145 @@ +mod derive_enum; +mod derive_struct; + +use quote::quote; +use derive_struct::*; +use derive_enum::*; + +pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result { + let name = &ast.ident; + match &ast.data { + syn::Data::Struct(ds) => expand_struct(ds, ast), + syn::Data::Enum(de) => expand_enum(de, ast), + syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")), + } +} + +fn expand_struct( + ds: &syn::DataStruct, + ast: &syn::DeriveInput, +) -> syn::Result { + let name = &ast.ident; + let docs = extract_docs(&ast.attrs, false)?; + let (is_named_fields, field_names, field_types, field_docs, params_count) = match ds.fields { + syn::Fields::Named(ref fields) => Ok(( + true, + fields.named.iter().enumerate().map(map_field_to_name), + fields.named.iter().map(map_field_to_type), + fields.named.iter().map(map_field_to_doc), + fields.named.len(), + )), + syn::Fields::Unnamed(ref fields) => Ok(( + false, + fields.unnamed.iter().enumerate().map(map_field_to_name), + fields.unnamed.iter().map(map_field_to_type), + fields.unnamed.iter().map(map_field_to_doc), + fields.unnamed.len(), + )), + syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")), + }?; + + if params_count == 0 { + return Err(syn::Error::new(name.span(), "Empty structs not supported")); + }; + + let tuple_type = tuple_type(field_types.clone()); + let tuple_ref_type = tuple_ref_type(field_types.clone()); + let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone()); + let tuple_names = tuple_names(is_named_fields, field_names.clone()); + let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone()); + + let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name); + let abi_type = impl_struct_abi_type(name, tuple_type.clone()); + let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple); + let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data); + let solidity_type = impl_struct_solidity_type(name, field_types.clone(), params_count); + let solidity_type_name = + impl_struct_solidity_type_name(name, field_types.clone(), params_count); + let solidity_struct_collect = + impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?; + + Ok(quote! { + #can_be_plcaed_in_vec + #abi_type + #abi_read + #abi_write + #solidity_type + #solidity_type_name + #solidity_struct_collect + }) +} + +fn expand_enum( + de: &syn::DataEnum, + ast: &syn::DeriveInput, +) -> syn::Result { + let name = &ast.ident; + check_repr_u8(name, &ast.attrs)?; + let docs = extract_docs(&ast.attrs, false)?; + let option_count = check_and_count_options(de)?; + let enum_options = de.variants.iter().map(|v| &v.ident); + let enum_options_docs = de.variants.iter().map(|v| extract_docs(&v.attrs, true)); + + let from = impl_enum_from_u8(name, enum_options.clone()); + let solidity_option = impl_solidity_option(name, enum_options.clone()); + let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name); + let abi_type = impl_enum_abi_type(name); + let abi_read = impl_enum_abi_read(name); + let abi_write = impl_enum_abi_write(name); + let solidity_type_name = impl_enum_solidity_type_name(name); + let solidity_struct_collect = impl_enum_solidity_struct_collect( + name, + enum_options, + option_count, + enum_options_docs, + &docs, + ); + + Ok(quote! { + #from + #solidity_option + #can_be_plcaed_in_vec + #abi_type + #abi_read + #abi_write + #solidity_type_name + #solidity_struct_collect + }) +} + +fn extract_docs( + attrs: &[syn::Attribute], + is_field_doc: bool, +) -> syn::Result> { + attrs + .iter() + .filter_map(|attr| { + if let Some(ps) = attr.path.segments.first() { + if ps.ident == "doc" { + let meta = match attr.parse_meta() { + Ok(meta) => meta, + Err(e) => return Some(Err(e)), + }; + match meta { + syn::Meta::NameValue(mnv) => match &mnv.lit { + syn::Lit::Str(ls) => return Some(Ok(ls.value())), + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + } + None + }) + .enumerate() + .map(|(i, doc)| { + let doc = doc?; + let doc = doc.trim(); + let dev = if i == 0 { " @dev" } else { "" }; + let tab = if is_field_doc { "\t" } else { "" }; + Ok(quote! { + writeln!(str, "{}///{} {}", #tab, #dev, #doc).unwrap(); + }) + }) + .collect() +} --- a/crates/evm-coder/procedural/src/lib.rs +++ b/crates/evm-coder/procedural/src/lib.rs @@ -25,6 +25,7 @@ parse_macro_input, spanned::Spanned, }; +mod abi_derive; mod solidity_interface; mod to_log; @@ -242,3 +243,13 @@ } .into() } + +#[proc_macro_derive(AbiCoder)] +pub fn abi_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ast = syn::parse(input).unwrap(); + let ts = match abi_derive::impl_abi_macro(&ast) { + Ok(e) => e, + Err(e) => e.to_compile_error(), + }; + ts.into() +} --- a/crates/evm-coder/procedural/src/solidity_interface.rs +++ b/crates/evm-coder/procedural/src/solidity_interface.rs @@ -404,7 +404,11 @@ let name = &self.name; let ty = &self.ty; quote! { - #name: <#ty>::abi_read(reader)? + #name: { + let value = <#ty as ::evm_coder::abi::AbiRead>::abi_read(reader)?; + if !is_dynamic {reader.bytes_read(<#ty as ::evm_coder::abi::AbiType>::size())}; + value + } } } @@ -630,17 +634,18 @@ let pascal_name = &self.pascal_name; let screaming_name = &self.screaming_name; if self.has_normal_args { - let parsers = self - .args - .iter() - .filter(|a| !a.is_special()) - .map(|a| a.expand_parse()); + let args_iter = self.args.iter().filter(|a| !a.is_special()); + let arg_type = args_iter.clone().map(|a| &a.ty); + let parsers = args_iter.map(|a| a.expand_parse()); quote! { - Self::#screaming_name => return Ok(Some(Self::#pascal_name { - #( - #parsers, - )* - })) + Self::#screaming_name => { + let is_dynamic = false #(|| <#arg_type as ::evm_coder::abi::AbiType>::is_dynamic())*; + return Ok(Some(Self::#pascal_name { + #( + #parsers, + )* + })) + } } } else { quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) } --- a/crates/evm-coder/src/abi/impls.rs +++ b/crates/evm-coder/src/abi/impls.rs @@ -1,8 +1,8 @@ use crate::{ + custom_signature::SignatureUnit, execution::{Result, ResultWithPostInfo, WithPostDispatchInfo}, + make_signature, sealed, types::*, - make_signature, - custom_signature::SignatureUnit, }; use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter}; use primitive_types::{U256, H160}; @@ -10,12 +10,12 @@ #[cfg(not(feature = "std"))] use alloc::vec::Vec; -macro_rules! impl_abi_readable { - ($ty:ty, $method:ident, $dynamic:literal) => { +macro_rules! impl_abi_type { + ($ty:ty, $name:ident, $dynamic:literal) => { impl sealed::CanBePlacedInVec for $ty {} impl AbiType for $ty { - const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($ty))); + const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($name))); fn is_dynamic() -> bool { $dynamic @@ -25,7 +25,11 @@ ABI_ALIGNMENT } } + }; +} +macro_rules! impl_abi_readable { + ($ty:ty, $method:ident) => { impl AbiRead for $ty { fn abi_read(reader: &mut AbiReader) -> Result<$ty> { reader.$method() @@ -34,79 +38,93 @@ }; } -impl_abi_readable!(uint32, uint32, false); -impl_abi_readable!(uint64, uint64, false); -impl_abi_readable!(uint128, uint128, false); -impl_abi_readable!(uint256, uint256, false); -impl_abi_readable!(bytes4, bytes4, false); -impl_abi_readable!(address, address, false); -impl_abi_readable!(string, string, true); +macro_rules! impl_abi_writeable { + ($ty:ty, $method:ident) => { + impl AbiWrite for $ty { + fn abi_write(&self, writer: &mut AbiWriter) { + writer.$method(&self) + } + } + }; +} -impl sealed::CanBePlacedInVec for bool {} +macro_rules! impl_abi { + ($ty:ty, $method:ident, $dynamic:literal) => { + impl_abi_type!($ty, $method, $dynamic); + impl_abi_readable!($ty, $method); + impl_abi_writeable!($ty, $method); + }; +} -impl AbiType for bool { - const SIGNATURE: SignatureUnit = make_signature!(new fixed("bool")); +impl_abi!(bool, bool, false); +impl_abi!(u8, uint8, false); +impl_abi!(u32, uint32, false); +impl_abi!(u64, uint64, false); +impl_abi!(u128, uint128, false); +impl_abi!(U256, uint256, false); +impl_abi!(H160, address, false); +impl_abi!(string, string, true); - fn is_dynamic() -> bool { - false - } - fn size() -> usize { - ABI_ALIGNMENT +impl_abi_writeable!(&str, string); + +impl_abi_type!(bytes, bytes, true); + +impl AbiRead for bytes { + fn abi_read(reader: &mut AbiReader) -> Result { + Ok(bytes(reader.bytes()?)) } } -impl AbiRead for bool { - fn abi_read(reader: &mut AbiReader) -> Result { - reader.bool() + +impl AbiWrite for bytes { + fn abi_write(&self, writer: &mut AbiWriter) { + writer.bytes(self.0.as_slice()) } } - -impl AbiType for uint8 { - const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8")); - fn is_dynamic() -> bool { - false - } - fn size() -> usize { - ABI_ALIGNMENT +impl_abi_type!(bytes4, bytes4, false); +impl AbiRead for bytes4 { + fn abi_read(reader: &mut AbiReader) -> Result { + reader.bytes4() } } -impl AbiRead for uint8 { - fn abi_read(reader: &mut AbiReader) -> Result { - reader.uint8() + +impl AbiWrite for &T { + fn abi_write(&self, writer: &mut AbiWriter) { + T::abi_write(self, writer); } } -impl AbiType for bytes { - const SIGNATURE: SignatureUnit = make_signature!(new fixed("bytes")); +impl AbiType for &T { + const SIGNATURE: SignatureUnit = T::SIGNATURE; fn is_dynamic() -> bool { - true + T::is_dynamic() } + fn size() -> usize { - ABI_ALIGNMENT - } -} -impl AbiRead for bytes { - fn abi_read(reader: &mut AbiReader) -> Result { - Ok(bytes(reader.bytes()?)) + T::size() } } -impl AbiRead for Vec { - fn abi_read(reader: &mut AbiReader) -> Result> { +impl AbiRead for Vec { + fn abi_read(reader: &mut AbiReader) -> Result> { let mut sub = reader.subresult(None)?; let size = sub.uint32()? as usize; sub.subresult_offset = sub.offset; + let is_dynamic = ::is_dynamic(); let mut out = Vec::with_capacity(size); for _ in 0..size { - out.push(::abi_read(&mut sub)?); + out.push(::abi_read(&mut sub)?); + if !is_dynamic { + sub.bytes_read(::size()); + }; } Ok(out) } } -impl AbiType for Vec { - const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]")); +impl AbiType for Vec { + const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]")); fn is_dynamic() -> bool { true @@ -114,42 +132,6 @@ fn size() -> usize { ABI_ALIGNMENT - } -} - -impl sealed::CanBePlacedInVec for EthCrossAccount {} - -impl AbiType for EthCrossAccount { - const SIGNATURE: SignatureUnit = make_signature!(new fixed("(address,uint256)")); - - fn is_dynamic() -> bool { - address::is_dynamic() || uint256::is_dynamic() - } - - fn size() -> usize { -
::size() + ::size() - } -} - -impl AbiRead for EthCrossAccount { - fn abi_read(reader: &mut AbiReader) -> Result { - let size = if !EthCrossAccount::is_dynamic() { - Some(::size()) - } else { - None - }; - let mut subresult = reader.subresult(size)?; - let eth =
::abi_read(&mut subresult)?; - let sub = ::abi_read(&mut subresult)?; - - Ok(EthCrossAccount { eth, sub }) - } -} - -impl AbiWrite for EthCrossAccount { - fn abi_write(&self, writer: &mut AbiWriter) { - self.eth.abi_write(writer); - self.sub.abi_write(writer); } } @@ -188,36 +170,6 @@ } } -macro_rules! impl_abi_writeable { - ($ty:ty, $method:ident) => { - impl AbiWrite for $ty { - fn abi_write(&self, writer: &mut AbiWriter) { - writer.$method(&self) - } - } - }; -} - -impl_abi_writeable!(u8, uint8); -impl_abi_writeable!(u32, uint32); -impl_abi_writeable!(u128, uint128); -impl_abi_writeable!(U256, uint256); -impl_abi_writeable!(H160, address); -impl_abi_writeable!(bool, bool); -impl_abi_writeable!(&str, string); - -impl AbiWrite for string { - fn abi_write(&self, writer: &mut AbiWriter) { - writer.string(self) - } -} - -impl AbiWrite for bytes { - fn abi_write(&self, writer: &mut AbiWriter) { - writer.bytes(self.0.as_slice()) - } -} - impl AbiWrite for Vec { fn abi_write(&self, writer: &mut AbiWriter) { let is_dynamic = T::is_dynamic(); @@ -295,14 +247,19 @@ impl<$($ident),+> AbiRead for ($($ident,)+) where - $($ident: AbiRead,)+ - ($($ident,)+): AbiType, + Self: AbiType, + $($ident: AbiRead + AbiType,)+ { fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> { - let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None }; + let is_dynamic = ::is_dynamic(); + let size = if !is_dynamic { Some(::size()) } else { None }; let mut subresult = reader.subresult(size)?; Ok(( - $(<$ident>::abi_read(&mut subresult)?,)+ + $({ + let value = <$ident>::abi_read(&mut subresult)?; + if !is_dynamic {subresult.bytes_read(<$ident as AbiType>::size())}; + value + },)+ )) } } @@ -310,11 +267,11 @@ #[allow(non_snake_case)] impl<$($ident),+> AbiWrite for ($($ident,)+) where - $($ident: AbiWrite,)+ + $($ident: AbiWrite + AbiType,)+ { fn abi_write(&self, writer: &mut AbiWriter) { let ($($ident,)+) = self; - if writer.is_dynamic { + if ::is_dynamic() { let mut sub = AbiWriter::new(); $($ident.abi_write(&mut sub);)+ writer.write_subresult(sub); --- a/crates/evm-coder/src/abi/mod.rs +++ b/crates/evm-coder/src/abi/mod.rs @@ -75,19 +75,19 @@ buf: &[u8], offset: usize, pad_start: usize, - pad_size: usize, + pad_end: usize, block_start: usize, - block_size: usize, + block_end: usize, ) -> Result<[u8; S]> { if buf.len() - offset < ABI_ALIGNMENT { return Err(Error::Error(ExitError::OutOfOffset)); } let mut block = [0; S]; - let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0); + let is_pad_zeroed = buf[pad_start..pad_end].iter().all(|&v| v == 0); if !is_pad_zeroed { return Err(Error::Error(ExitError::InvalidRange)); } - block.copy_from_slice(&buf[block_start..block_size]); + block.copy_from_slice(&buf[block_start..block_end]); Ok(block) } @@ -186,11 +186,10 @@ /// Slice recursive buffer, advance one word for buffer offset /// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`]. - fn subresult(&mut self, size: Option) -> Result> { + pub fn subresult(&mut self, size: Option) -> Result> { let subresult_offset = self.subresult_offset; let offset = if let Some(size) = size { self.offset += size; - self.subresult_offset += size; 0 } else { self.uint32()? as usize @@ -208,6 +207,11 @@ }) } + /// Notify about readed data portion. + pub fn bytes_read(&mut self, size: usize) { + self.subresult_offset += size; + } + /// Is this parser reached end of buffer? pub fn is_finished(&self) -> bool { self.buf.len() == self.offset @@ -277,6 +281,11 @@ self.write_padleft(&u32::to_be_bytes(*value)) } + /// Write [`u64`] to end of buffer + pub fn uint64(&mut self, value: &u64) { + self.write_padleft(&u64::to_be_bytes(*value)) + } + /// Write [`u128`] to end of buffer pub fn uint128(&mut self, value: &u128) { self.write_padleft(&u128::to_be_bytes(*value)) --- a/crates/evm-coder/src/abi/test.rs +++ b/crates/evm-coder/src/abi/test.rs @@ -6,36 +6,25 @@ use super::{AbiReader, AbiWriter}; use hex_literal::hex; use primitive_types::{H160, U256}; -use concat_idents::concat_idents; -macro_rules! test_impl { - ($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => { - concat_idents!(test_name = encode_decode_, $name { - #[test] - fn test_name() { - let function_identifier: u32 = $function_identifier; - let decoded_data = $decoded_data; - let encoded_data = $encoded_data; - - let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap(); - assert_eq!(call, u32::to_be_bytes(function_identifier)); - let data = <$type>::abi_read(&mut decoder).unwrap(); - assert_eq!(data, decoded_data); +fn test_impl(function_identifier: u32, decoded_data: T, encoded_data: &[u8]) +where + T: AbiWrite + AbiRead + std::cmp::PartialEq + std::fmt::Debug, +{ + let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap(); + assert_eq!(call, u32::to_be_bytes(function_identifier)); + let data = ::abi_read(&mut decoder).unwrap(); + assert_eq!(data, decoded_data); - let mut writer = AbiWriter::new_call(function_identifier); - decoded_data.abi_write(&mut writer); - let ed = writer.finish(); - similar_asserts::assert_eq!(encoded_data, ed.as_slice()); - } - }); - }; + let mut writer = AbiWriter::new_call(function_identifier); + decoded_data.abi_write(&mut writer); + let ed = writer.finish(); + similar_asserts::assert_eq!(encoded_data, ed.as_slice()); } macro_rules! test_impl_uint { ($type:ident) => { - test_impl!( - $type, - $type, + test_impl::<$type>( 0xdeadbeef, 255 as $type, &hex!( @@ -43,101 +32,148 @@ deadbeef 00000000000000000000000000000000000000000000000000000000000000ff " - ) + ), ); }; } -test_impl_uint!(uint8); -test_impl_uint!(uint32); -test_impl_uint!(uint128); +#[test] +fn encode_decode_uint8() { + test_impl_uint!(uint8); +} -test_impl!( - uint256, - uint256, - 0xdeadbeef, - U256([255, 0, 0, 0]), - &hex!( - " - deadbeef - 00000000000000000000000000000000000000000000000000000000000000ff - " - ) -); +#[test] +fn encode_decode_uint32() { + test_impl_uint!(uint32); +} -test_impl!( - vec_tuple_address_uint256, - Vec<(address, uint256)>, - 0x1ACF2D55, - vec![ - ( - H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")), - U256([10, 0, 0, 0]), - ), - ( - H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")), - U256([20, 0, 0, 0]), - ), - ( - H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")), - U256([30, 0, 0, 0]), - ), - ], - &hex!( - " - 1ACF2D55 - 0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[] - 0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[] +#[test] +fn encode_decode_uint128() { + test_impl_uint!(uint128); +} - 0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address - 000000000000000000000000000000000000000000000000000000000000000A // uint256 +#[test] +fn encode_decode_uint256() { + test_impl::( + 0xdeadbeef, + U256([255, 0, 0, 0]), + &hex!( + " + deadbeef + 00000000000000000000000000000000000000000000000000000000000000ff + " + ), + ); +} - 000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address - 0000000000000000000000000000000000000000000000000000000000000014 // uint256 +#[test] +fn encode_decode_string() { + test_impl::( + 0xdeadbeef, + "some string".to_string(), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + " + ), + ); +} - 0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address - 000000000000000000000000000000000000000000000000000000000000001E // uint256 - " - ) -); +#[test] +fn encode_decode_tuple_string() { + test_impl::<(String,)>( + 0xdeadbeef, + ("some string".to_string(),), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + " + ), + ); +} -test_impl!( - vec_tuple_uint256_string, - Vec<(uint256, string)>, - 0xdeadbeef, - vec![ - (1.into(), "Test URI 0".to_string()), - (11.into(), "Test URI 1".to_string()), - (12.into(), "Test URI 2".to_string()), - ], - &hex!( - " - deadbeef - 0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[] - 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[] +#[test] +fn encode_decode_vec_tuple_address_uint256() { + test_impl::>( + 0x1ACF2D55, + vec![ + ( + H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")), + U256([10, 0, 0, 0]), + ), + ( + H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")), + U256([20, 0, 0, 0]), + ), + ( + H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")), + U256([30, 0, 0, 0]), + ), + ], + &hex!( + " + 1ACF2D55 + 0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[] + 0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[] - 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem - 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem - 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem + 0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address + 000000000000000000000000000000000000000000000000000000000000000A // uint256 - 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60 - 0000000000000000000000000000000000000000000000000000000000000040 // offset of string - 000000000000000000000000000000000000000000000000000000000000000a // size of string - 5465737420555249203000000000000000000000000000000000000000000000 // string + 000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address + 0000000000000000000000000000000000000000000000000000000000000014 // uint256 - 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0 - 0000000000000000000000000000000000000000000000000000000000000040 // offset of string - 000000000000000000000000000000000000000000000000000000000000000a // size of string - 5465737420555249203100000000000000000000000000000000000000000000 // string + 0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address + 000000000000000000000000000000000000000000000000000000000000001E // uint256 + " + ) + ); +} - 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160 - 0000000000000000000000000000000000000000000000000000000000000040 // offset of string - 000000000000000000000000000000000000000000000000000000000000000a // size of string - 5465737420555249203200000000000000000000000000000000000000000000 // string - " - ) -); +#[test] +fn encode_decode_vec_tuple_uint256_string() { + test_impl::>( + 0xdeadbeef, + vec![ + (1.into(), "Test URI 0".to_string()), + (11.into(), "Test URI 1".to_string()), + (12.into(), "Test URI 2".to_string()), + ], + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[] + 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[] + 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem + 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem + 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem + + 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60 + 0000000000000000000000000000000000000000000000000000000000000040 // offset of string + 000000000000000000000000000000000000000000000000000000000000000a // size of string + 5465737420555249203000000000000000000000000000000000000000000000 // string + + 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0 + 0000000000000000000000000000000000000000000000000000000000000040 // offset of string + 000000000000000000000000000000000000000000000000000000000000000a // size of string + 5465737420555249203100000000000000000000000000000000000000000000 // string + + 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160 + 0000000000000000000000000000000000000000000000000000000000000040 // offset of string + 000000000000000000000000000000000000000000000000000000000000000a // size of string + 5465737420555249203200000000000000000000000000000000000000000000 // string + " + ) + ); +} + #[test] fn dynamic_after_static() { let mut encoder = AbiWriter::new(); @@ -235,63 +271,270 @@ similar_asserts::assert_eq!(encoded_data, ed.as_slice()); } -test_impl!( - vec_tuple_string_bytes, - Vec<(string, bytes)>, - 0xdeadbeef, - vec![ - ( - "Test URI 0".to_string(), - bytes(vec![ - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 - ]) +#[test] +fn encode_decode_vec_tuple_string_bytes() { + test_impl::>( + 0xdeadbeef, + vec![ + ( + "Test URI 0".to_string(), + bytes(vec![ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + ]), + ), + ( + "Test URI 1".to_string(), + bytes(vec![ + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + ]), + ), + ("Test URI 2".to_string(), bytes(vec![0x33, 0x33])), + ], + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000003 + + 0000000000000000000000000000000000000000000000000000000000000060 + 0000000000000000000000000000000000000000000000000000000000000140 + 0000000000000000000000000000000000000000000000000000000000000220 + + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000080 + 000000000000000000000000000000000000000000000000000000000000000a + 5465737420555249203000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000030 + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111100000000000000000000000000000000 + + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000080 + 000000000000000000000000000000000000000000000000000000000000000a + 5465737420555249203100000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000002f + 2222222222222222222222222222222222222222222222222222222222222222 + 2222222222222222222222222222220000000000000000000000000000000000 + + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000080 + 000000000000000000000000000000000000000000000000000000000000000a + 5465737420555249203200000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000002 + 3333000000000000000000000000000000000000000000000000000000000000 + " + ), + ); +} + +#[test] +// #[ignore = "reason"] +fn encode_decode_tuple0_tuple1_uint8_tuple1_string_bytes_tuple1_uint8_bytes() { + let int = 0xff; + let by = bytes(vec![0x11, 0x22, 0x33]); + let string = "some string".to_string(); + + test_impl::<((u8,), (String, bytes), (u8, bytes))>( + 0xdeadbeef, + ((int,), (string.clone(), by.clone()), (int, by)), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 00000000000000000000000000000000000000000000000000000000000000ff + 0000000000000000000000000000000000000000000000000000000000000060 + 0000000000000000000000000000000000000000000000000000000000000120 + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000080 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000003 + 1122330000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000000000000000ff + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000003 + 1122330000000000000000000000000000000000000000000000000000000000 + " + ), + ); +} + +#[test] +fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8_uint8_tuple1_uint8_uint8() { + test_impl::<((u8,), (u8, u8), (u8, u8))>( + 0xdeadbeef, + ((43,), (44, 45), (46, 47)), + &hex!( + " + deadbeef + 000000000000000000000000000000000000000000000000000000000000002b + 000000000000000000000000000000000000000000000000000000000000002c + 000000000000000000000000000000000000000000000000000000000000002d + 000000000000000000000000000000000000000000000000000000000000002e + 000000000000000000000000000000000000000000000000000000000000002f + " + ), + ); +} + +#[test] +fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8() { + test_impl::<((u8,), (u8,))>( + 0xdeadbeef, + ((43,), (44,)), + &hex!( + " + deadbeef + 000000000000000000000000000000000000000000000000000000000000002b + 000000000000000000000000000000000000000000000000000000000000002c + " + ), + ); +} + +#[test] +fn encode_decode_tuple0_tuple1_uint8_uint8() { + test_impl::<((u8, u8),)>( + 0xdeadbeef, + ((43, 44),), + &hex!( + " + deadbeef + 000000000000000000000000000000000000000000000000000000000000002b + 000000000000000000000000000000000000000000000000000000000000002c + " + ), + ); +} + +#[test] +fn encode_decode_tuple_uint8_uint8() { + test_impl::<(u8, u8)>( + 0xdeadbeef, + (43, 44), + &hex!( + " + deadbeef + 000000000000000000000000000000000000000000000000000000000000002b + 000000000000000000000000000000000000000000000000000000000000002c + " + ), + ); +} + +#[test] +fn encode_decode_tuple0_tuple1_uint8_uint8_tuple1_uint8_uint8_and_uint8() { + test_impl::<((u8, u8), (u8, u8), u8)>( + 0xdeadbeef, + ((10, 11), (12, 13), 14), + &hex!( + " + deadbeef + 000000000000000000000000000000000000000000000000000000000000000a + 000000000000000000000000000000000000000000000000000000000000000b + 000000000000000000000000000000000000000000000000000000000000000c + 000000000000000000000000000000000000000000000000000000000000000d + 000000000000000000000000000000000000000000000000000000000000000e + " ), - ( - "Test URI 1".to_string(), - bytes(vec![ - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22 - ]) + ); +} + +#[test] +fn encode_decode_tuple0_tuple1_string() { + test_impl::<((String,),)>( + 0xdeadbeef, + (("some string".to_string(),),), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + " ), - ("Test URI 2".to_string(), bytes(vec![0x33, 0x33])), - ], - &hex!( - " - deadbeef - 0000000000000000000000000000000000000000000000000000000000000020 - 0000000000000000000000000000000000000000000000000000000000000003 - - 0000000000000000000000000000000000000000000000000000000000000060 - 0000000000000000000000000000000000000000000000000000000000000140 - 0000000000000000000000000000000000000000000000000000000000000220 + ); +} - 0000000000000000000000000000000000000000000000000000000000000040 - 0000000000000000000000000000000000000000000000000000000000000080 - 000000000000000000000000000000000000000000000000000000000000000a - 5465737420555249203000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000030 - 1111111111111111111111111111111111111111111111111111111111111111 - 1111111111111111111111111111111100000000000000000000000000000000 +#[test] +fn encode_decode_tuple0_tuple1_uint8_string() { + test_impl::<((u8, String),)>( + 0xdeadbeef, + ((0xff, "some string".to_string()),), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 00000000000000000000000000000000000000000000000000000000000000ff + 0000000000000000000000000000000000000000000000000000000000000040 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + " + ), + ); +} - 0000000000000000000000000000000000000000000000000000000000000040 - 0000000000000000000000000000000000000000000000000000000000000080 - 000000000000000000000000000000000000000000000000000000000000000a - 5465737420555249203100000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000000000000002f - 2222222222222222222222222222222222222222222222222222222222222222 - 2222222222222222222222222222220000000000000000000000000000000000 +#[test] +fn encode_decode_tuple0_tuple1_string_bytes() { + test_impl::<((String, bytes),)>( + 0xdeadbeef, + (("some string".to_string(), bytes(vec![1, 2, 3])),), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000080 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000003 + 0102030000000000000000000000000000000000000000000000000000000000 + " + ), + ); +} - 0000000000000000000000000000000000000000000000000000000000000040 - 0000000000000000000000000000000000000000000000000000000000000080 +#[test] +fn encode_decode_tuple0_tuple1_uint8_tuple1_string() { + test_impl::<((u8,), (String,))>( + 0xdeadbeef, + ((0xff,), ("some string".to_string(),)), + &hex!( + " + deadbeef + 0000000000000000000000000000000000000000000000000000000000000020 + 00000000000000000000000000000000000000000000000000000000000000ff + 0000000000000000000000000000000000000000000000000000000000000040 + 0000000000000000000000000000000000000000000000000000000000000020 + 000000000000000000000000000000000000000000000000000000000000000b + 736f6d6520737472696e67000000000000000000000000000000000000000000 + " + ), + ); +} + +#[test] +fn parse_multiple_params() { + let encoded_data = hex!( + " + deadbeef 000000000000000000000000000000000000000000000000000000000000000a - 5465737420555249203200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000002 - 3333000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000000b " - ) -); + ); + let (_, mut decoder) = AbiReader::new_call(&encoded_data).unwrap(); + let p1 = ::abi_read(&mut decoder).unwrap(); + let p2 = ::abi_read(&mut decoder).unwrap(); + assert_eq!(p1, 0x0a); + assert_eq!(p2, 0x0b); +} --- a/crates/evm-coder/src/abi/traits.rs +++ b/crates/evm-coder/src/abi/traits.rs @@ -22,12 +22,6 @@ fn size() -> usize; } -/// Sealed traits. -pub mod sealed { - /// Not all types can be placed in vec, i.e `Vec` is restricted, `bytes` should be used instead - pub trait CanBePlacedInVec {} -} - /// [`AbiReader`] implements reading of many types. pub trait AbiRead { /// Read item from current position, advanding decoder @@ -47,11 +41,5 @@ let mut writer = AbiWriter::new(); self.abi_write(&mut writer); Ok(writer.into()) - } -} - -impl AbiWrite for &T { - fn abi_write(&self, writer: &mut AbiWriter) { - T::abi_write(self, writer); } } --- a/crates/evm-coder/src/lib.rs +++ b/crates/evm-coder/src/lib.rs @@ -93,6 +93,7 @@ pub use evm_coder_procedural::solidity; /// See [`solidity_interface`] pub use evm_coder_procedural::weight; +pub use evm_coder_procedural::AbiCoder; pub use sha3_const; /// Derives [`ToLog`] for enum @@ -111,6 +112,15 @@ #[cfg(feature = "stubgen")] pub mod solidity; +/// Sealed traits. +pub mod sealed { + /// Not every type should be directly placed in vec. + /// Vec encoding is not memory efficient, as every item will be padded + /// to 32 bytes. + /// Instead you should use specialized types (`bytes` in case of `Vec`) + pub trait CanBePlacedInVec {} +} + /// Solidity type definitions (aliases from solidity name to rust type) /// To be used in [`solidity_interface`] definitions, to make sure there is no /// type conflict between Rust code and generated definitions @@ -119,7 +129,6 @@ #[cfg(not(feature = "std"))] use alloc::{vec::Vec}; - use pallet_evm::account::CrossAccountId; use primitive_types::{U256, H160, H256}; pub type address = H160; @@ -137,7 +146,7 @@ #[cfg(feature = "std")] pub type string = ::std::string::String; - #[derive(Default, Debug, PartialEq)] + #[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct bytes(pub Vec); /// Solidity doesn't have `void` type, however we have special implementation @@ -185,73 +194,7 @@ #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 - } - } - - #[derive(Debug, Default)] - pub struct EthCrossAccount { - pub(crate) eth: address, - pub(crate) sub: uint256, - } - - impl EthCrossAccount { - pub fn from_sub_cross_account(cross_account_id: &T::CrossAccountId) -> Self - where - T: pallet_evm::account::Config, - T::AccountId: AsRef<[u8; 32]>, - { - if cross_account_id.is_canonical_substrate() { - Self { - eth: Default::default(), - sub: convert_cross_account_to_uint256::(cross_account_id), - } - } else { - Self { - eth: *cross_account_id.as_eth(), - sub: Default::default(), - } - } } - - pub fn into_sub_cross_account(&self) -> crate::execution::Result - where - T: pallet_evm::account::Config, - T::AccountId: From<[u8; 32]>, - { - if self.eth == Default::default() && self.sub == Default::default() { - Err("All fields of cross account is zeroed".into()) - } else if self.eth == Default::default() { - Ok(convert_uint256_to_cross_account::(self.sub)) - } else if self.sub == Default::default() { - Ok(T::CrossAccountId::from_eth(self.eth)) - } else { - Err("All fields of cross account is non zeroed".into()) - } - } - } - - /// Convert `CrossAccountId` to `uint256`. - pub fn convert_cross_account_to_uint256( - from: &T::CrossAccountId, - ) -> uint256 - where - T::AccountId: AsRef<[u8; 32]>, - { - let slice = from.as_sub().as_ref(); - uint256::from_big_endian(slice) - } - - /// Convert `uint256` to `CrossAccountId`. - pub fn convert_uint256_to_cross_account( - from: uint256, - ) -> T::CrossAccountId - where - T::AccountId: From<[u8; 32]>, - { - let mut new_admin_arr = [0_u8; 32]; - from.to_big_endian(&mut new_admin_arr); - let account_id = T::AccountId::from(new_admin_arr); - T::CrossAccountId::from_sub(account_id) } #[derive(Debug, Default)] --- a/crates/evm-coder/src/solidity.rs +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -//! Implementation detail of [`crate::solidity_interface`] macro code-generation. -//! You should not rely on any public item from this module, as it is only intended to be used -//! by procedural macro, API and output format may be changed at any time. -//! -//! Purpose of this module is to receive solidity contract definition in module-specified -//! format, and then output string, representing interface of this contract in solidity language - -#[cfg(not(feature = "std"))] -use alloc::{string::String, vec::Vec, collections::BTreeMap, format}; -#[cfg(feature = "std")] -use std::collections::BTreeMap; -use core::{ - fmt::{self, Write}, - marker::PhantomData, - cell::{Cell, RefCell}, - cmp::Reverse, -}; -use impl_trait_for_tuples::impl_for_tuples; -use crate::{types::*, custom_signature::SignatureUnit}; - -#[derive(Default)] -pub struct TypeCollector { - /// Code => id - /// id ordering is required to perform topo-sort on the resulting data - structs: RefCell>, - anonymous: RefCell, usize>>, - id: Cell, -} -impl TypeCollector { - pub fn new() -> Self { - Self::default() - } - pub fn collect(&self, item: string) { - let id = self.next_id(); - self.structs.borrow_mut().insert(item, id); - } - pub fn next_id(&self) -> usize { - let v = self.id.get(); - self.id.set(v + 1); - v - } - pub fn collect_tuple(&self) -> String { - let names = T::names(self); - if let Some(id) = self.anonymous.borrow().get(&names).cloned() { - return format!("Tuple{}", id); - } - let id = self.next_id(); - let mut str = String::new(); - writeln!(str, "/// @dev anonymous struct").unwrap(); - writeln!(str, "struct Tuple{} {{", id).unwrap(); - for (i, name) in names.iter().enumerate() { - writeln!(str, "\t{} field_{};", name, i).unwrap(); - } - writeln!(str, "}}").unwrap(); - self.collect(str); - self.anonymous.borrow_mut().insert(names, id); - format!("Tuple{}", id) - } - pub fn collect_struct(&self) -> String { - self.collect(::declaration()); - ::name() - } - pub fn finish(self) -> Vec { - let mut data = self.structs.into_inner().into_iter().collect::>(); - data.sort_by_key(|(_, id)| Reverse(*id)); - data.into_iter().map(|(code, _)| code).collect() - } -} - -pub trait StructCollect: 'static { - /// Structure name. - fn name() -> String; - /// Structure declaration. - fn declaration() -> String; -} - -pub trait SolidityTypeName: 'static { - fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; - /// "simple" types are stored inline, no `memory` modifier should be used in solidity - fn is_simple() -> bool; - fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; - /// Specialization - fn is_void() -> bool { - false - } -} -macro_rules! solidity_type_name { - ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => { - $( - impl SolidityTypeName for $ty { - fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result { - write!(writer, $name) - } - fn is_simple() -> bool { - $simple - } - fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result { - write!(writer, $default) - } - } - )* - }; -} - -solidity_type_name! { - uint8 => "uint8" true = "0", - uint32 => "uint32" true = "0", - uint64 => "uint64" true = "0", - uint128 => "uint128" true = "0", - uint256 => "uint256" true = "0", - bytes4 => "bytes4" true = "bytes4(0)", - address => "address" true = "0x0000000000000000000000000000000000000000", - string => "string" false = "\"\"", - bytes => "bytes" false = "hex\"\"", - bool => "bool" true = "false", -} -impl SolidityTypeName for void { - fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { - Ok(()) - } - fn is_simple() -> bool { - true - } - fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { - Ok(()) - } - fn is_void() -> bool { - true - } -} - -mod sealed { - /// Not every type should be directly placed in vec. - /// Vec encoding is not memory efficient, as every item will be padded - /// to 32 bytes. - /// Instead you should use specialized types (`bytes` in case of `Vec`) - pub trait CanBePlacedInVec {} -} - -impl sealed::CanBePlacedInVec for uint256 {} -impl sealed::CanBePlacedInVec for string {} -impl sealed::CanBePlacedInVec for address {} -impl sealed::CanBePlacedInVec for EthCrossAccount {} -impl sealed::CanBePlacedInVec for Property {} - -impl SolidityTypeName for Vec { - fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - T::solidity_name(writer, tc)?; - write!(writer, "[]") - } - fn is_simple() -> bool { - false - } - fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "new ")?; - T::solidity_name(writer, tc)?; - write!(writer, "[](0)") - } -} - -impl SolidityTupleType for EthCrossAccount { - fn names(tc: &TypeCollector) -> Vec { - let mut collected = Vec::with_capacity(Self::len()); - { - let mut out = string::new(); - address::solidity_name(&mut out, tc).expect("no fmt error"); - collected.push(out); - } - { - let mut out = string::new(); - uint256::solidity_name(&mut out, tc).expect("no fmt error"); - collected.push(out); - } - collected - } - - fn len() -> usize { - 2 - } -} - -impl SolidityTypeName for EthCrossAccount { - fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}", tc.collect_struct::()) - } - - fn is_simple() -> bool { - false - } - - fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}(", tc.collect_struct::())?; - address::solidity_default(writer, tc)?; - write!(writer, ",")?; - uint256::solidity_default(writer, tc)?; - write!(writer, ")") - } -} - -impl StructCollect for EthCrossAccount { - fn name() -> String { - "EthCrossAccount".into() - } - - fn declaration() -> String { - let mut str = String::new(); - writeln!(str, "/// @dev Cross account struct").unwrap(); - writeln!(str, "struct {} {{", Self::name()).unwrap(); - writeln!(str, "\taddress eth;").unwrap(); - writeln!(str, "\tuint256 sub;").unwrap(); - writeln!(str, "}}").unwrap(); - str - } -} - -impl StructCollect for Property { - fn name() -> String { - "Property".into() - } - - fn declaration() -> String { - let mut str = String::new(); - writeln!(str, "/// @dev Property struct").unwrap(); - writeln!(str, "struct {} {{", Self::name()).unwrap(); - writeln!(str, "\tstring key;").unwrap(); - writeln!(str, "\tbytes value;").unwrap(); - writeln!(str, "}}").unwrap(); - str - } -} - -impl SolidityTypeName for Property { - fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}", tc.collect_struct::()) - } - - fn is_simple() -> bool { - false - } - - fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}(", tc.collect_struct::())?; - address::solidity_default(writer, tc)?; - write!(writer, ",")?; - uint256::solidity_default(writer, tc)?; - write!(writer, ")") - } -} - -impl SolidityTupleType for Property { - fn names(tc: &TypeCollector) -> Vec { - let mut collected = Vec::with_capacity(Self::len()); - { - let mut out = string::new(); - string::solidity_name(&mut out, tc).expect("no fmt error"); - collected.push(out); - } - { - let mut out = string::new(); - bytes::solidity_name(&mut out, tc).expect("no fmt error"); - collected.push(out); - } - collected - } - - fn len() -> usize { - 2 - } -} - -pub trait SolidityTupleType { - fn names(tc: &TypeCollector) -> Vec; - fn len() -> usize; -} - -macro_rules! count { - () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); -} - -macro_rules! impl_tuples { - ($($ident:ident)+) => { - impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {} - impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleType for ($($ident,)+) { - fn names(tc: &TypeCollector) -> Vec { - let mut collected = Vec::with_capacity(Self::len()); - $({ - let mut out = string::new(); - $ident::solidity_name(&mut out, tc).expect("no fmt error"); - collected.push(out); - })*; - collected - } - - fn len() -> usize { - count!($($ident)*) - } - } - impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) { - fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}", tc.collect_tuple::()) - } - fn is_simple() -> bool { - false - } - #[allow(unused_assignments)] - fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - write!(writer, "{}(", tc.collect_tuple::())?; - let mut first = true; - $( - if !first { - write!(writer, ",")?; - } else { - first = false; - } - <$ident>::solidity_default(writer, tc)?; - )* - write!(writer, ")") - } - } - }; -} - -impl_tuples! {A} -impl_tuples! {A B} -impl_tuples! {A B C} -impl_tuples! {A B C D} -impl_tuples! {A B C D E} -impl_tuples! {A B C D E F} -impl_tuples! {A B C D E F G} -impl_tuples! {A B C D E F G H} -impl_tuples! {A B C D E F G H I} -impl_tuples! {A B C D E F G H I J} - -pub trait SolidityArguments { - fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; - fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result; - fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; - fn is_empty(&self) -> bool { - self.len() == 0 - } - fn len(&self) -> usize; -} - -#[derive(Default)] -pub struct UnnamedArgument(PhantomData<*const T>); - -impl SolidityArguments for UnnamedArgument { - fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - if !T::is_void() { - T::solidity_name(writer, tc)?; - if !T::is_simple() { - write!(writer, " memory")?; - } - Ok(()) - } else { - Ok(()) - } - } - fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result { - Ok(()) - } - fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - T::solidity_default(writer, tc) - } - fn len(&self) -> usize { - if T::is_void() { - 0 - } else { - 1 - } - } -} - -pub struct NamedArgument(&'static str, PhantomData<*const T>); - -impl NamedArgument { - pub fn new(name: &'static str) -> Self { - Self(name, Default::default()) - } -} - -impl SolidityArguments for NamedArgument { - fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - if !T::is_void() { - T::solidity_name(writer, tc)?; - if !T::is_simple() { - write!(writer, " memory")?; - } - write!(writer, " {}", self.0) - } else { - Ok(()) - } - } - fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { - writeln!(writer, "\t{prefix}\t{};", self.0) - } - fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - T::solidity_default(writer, tc) - } - fn len(&self) -> usize { - if T::is_void() { - 0 - } else { - 1 - } - } -} - -pub struct SolidityEventArgument(pub bool, &'static str, PhantomData<*const T>); - -impl SolidityEventArgument { - pub fn new(indexed: bool, name: &'static str) -> Self { - Self(indexed, name, Default::default()) - } -} - -impl SolidityArguments for SolidityEventArgument { - fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - if !T::is_void() { - T::solidity_name(writer, tc)?; - if self.0 { - write!(writer, " indexed")?; - } - write!(writer, " {}", self.1) - } else { - Ok(()) - } - } - fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { - writeln!(writer, "\t{prefix}\t{};", self.1) - } - fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - T::solidity_default(writer, tc) - } - fn len(&self) -> usize { - if T::is_void() { - 0 - } else { - 1 - } - } -} - -impl SolidityArguments for () { - fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { - Ok(()) - } - fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result { - Ok(()) - } - fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { - Ok(()) - } - fn len(&self) -> usize { - 0 - } -} - -#[impl_for_tuples(1, 12)] -impl SolidityArguments for Tuple { - for_tuples!( where #( Tuple: SolidityArguments ),* ); - - fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - let mut first = true; - for_tuples!( #( - if !Tuple.is_empty() { - if !first { - write!(writer, ", ")?; - } - first = false; - Tuple.solidity_name(writer, tc)?; - } - )* ); - Ok(()) - } - fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { - for_tuples!( #( - Tuple.solidity_get(prefix, writer)?; - )* ); - Ok(()) - } - fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { - if self.is_empty() { - Ok(()) - } else if self.len() == 1 { - for_tuples!( #( - Tuple.solidity_default(writer, tc)?; - )* ); - Ok(()) - } else { - write!(writer, "(")?; - let mut first = true; - for_tuples!( #( - if !Tuple.is_empty() { - if !first { - write!(writer, ", ")?; - } - first = false; - Tuple.solidity_default(writer, tc)?; - } - )* ); - write!(writer, ")")?; - Ok(()) - } - } - fn len(&self) -> usize { - for_tuples!( #( Tuple.len() )+* ) - } -} - -pub trait SolidityFunctions { - fn solidity_name( - &self, - is_impl: bool, - writer: &mut impl fmt::Write, - tc: &TypeCollector, - ) -> fmt::Result; -} - -pub enum SolidityMutability { - Pure, - View, - Mutable, -} -pub struct SolidityFunction { - pub docs: &'static [&'static str], - pub selector: u32, - pub hide: bool, - pub custom_signature: SignatureUnit, - pub name: &'static str, - pub args: A, - pub result: R, - pub mutability: SolidityMutability, - pub is_payable: bool, -} -impl SolidityFunctions for SolidityFunction { - fn solidity_name( - &self, - is_impl: bool, - writer: &mut impl fmt::Write, - tc: &TypeCollector, - ) -> fmt::Result { - let hide_comment = self.hide.then(|| "// ").unwrap_or(""); - for doc in self.docs { - writeln!(writer, "\t{hide_comment}///{}", doc)?; - } - writeln!( - writer, - "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},", - self.selector - )?; - writeln!( - writer, - "\t{hide_comment}/// or in textual repr: {}", - self.custom_signature.as_str().expect("bad utf-8") - )?; - write!(writer, "\t{hide_comment}function {}(", self.name)?; - self.args.solidity_name(writer, tc)?; - write!(writer, ")")?; - if is_impl { - write!(writer, " public")?; - } else { - write!(writer, " external")?; - } - match &self.mutability { - SolidityMutability::Pure => write!(writer, " pure")?, - SolidityMutability::View => write!(writer, " view")?, - SolidityMutability::Mutable => {} - } - if self.is_payable { - write!(writer, " payable")?; - } - if !self.result.is_empty() { - write!(writer, " returns (")?; - self.result.solidity_name(writer, tc)?; - write!(writer, ")")?; - } - if is_impl { - writeln!(writer, " {{")?; - writeln!(writer, "\t{hide_comment}\trequire(false, stub_error);")?; - self.args.solidity_get(hide_comment, writer)?; - match &self.mutability { - SolidityMutability::Pure => {} - SolidityMutability::View => writeln!(writer, "\t{hide_comment}\tdummy;")?, - SolidityMutability::Mutable => writeln!(writer, "\t{hide_comment}\tdummy = 0;")?, - } - if !self.result.is_empty() { - write!(writer, "\t{hide_comment}\treturn ")?; - self.result.solidity_default(writer, tc)?; - writeln!(writer, ";")?; - } - writeln!(writer, "\t{hide_comment}}}")?; - } else { - writeln!(writer, ";")?; - } - if self.hide { - writeln!(writer, "// FORMATTING: FORCE NEWLINE")?; - } - Ok(()) - } -} - -#[impl_for_tuples(0, 48)] -impl SolidityFunctions for Tuple { - for_tuples!( where #( Tuple: SolidityFunctions ),* ); - - fn solidity_name( - &self, - is_impl: bool, - writer: &mut impl fmt::Write, - tc: &TypeCollector, - ) -> fmt::Result { - let mut first = false; - for_tuples!( #( - Tuple.solidity_name(is_impl, writer, tc)?; - )* ); - Ok(()) - } -} - -pub struct SolidityInterface { - pub docs: &'static [&'static str], - pub selector: bytes4, - pub name: &'static str, - pub is: &'static [&'static str], - pub functions: F, -} - -impl SolidityInterface { - pub fn format( - &self, - is_impl: bool, - out: &mut impl fmt::Write, - tc: &TypeCollector, - ) -> fmt::Result { - const ZERO_BYTES: [u8; 4] = [0; 4]; - for doc in self.docs { - writeln!(out, "///{}", doc)?; - } - if self.selector != ZERO_BYTES { - writeln!( - out, - "/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}", - u32::from_be_bytes(self.selector) - )?; - } - if is_impl { - write!(out, "contract ")?; - } else { - write!(out, "interface ")?; - } - write!(out, "{}", self.name)?; - if !self.is.is_empty() { - write!(out, " is")?; - for (i, n) in self.is.iter().enumerate() { - if i != 0 { - write!(out, ",")?; - } - write!(out, " {}", n)?; - } - } - writeln!(out, " {{")?; - self.functions.solidity_name(is_impl, out, tc)?; - writeln!(out, "}}")?; - Ok(()) - } -} - -pub struct SolidityEvent { - pub name: &'static str, - pub args: A, -} - -impl SolidityFunctions for SolidityEvent { - fn solidity_name( - &self, - _is_impl: bool, - writer: &mut impl fmt::Write, - tc: &TypeCollector, - ) -> fmt::Result { - write!(writer, "\tevent {}(", self.name)?; - self.args.solidity_name(writer, tc)?; - writeln!(writer, ");") - } -} --- /dev/null +++ b/crates/evm-coder/src/solidity/impls.rs @@ -0,0 +1,190 @@ +use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect}; +use crate::{sealed, types::*}; +use core::fmt; +use primitive_types::{U256, H160}; + +macro_rules! solidity_type_name { + ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => { + $( + impl SolidityTypeName for $ty { + fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result { + write!(writer, $name) + } + fn is_simple() -> bool { + $simple + } + fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result { + write!(writer, $default) + } + } + + impl StructCollect for $ty { + fn name() -> String { + $name.to_string() + } + + fn declaration() -> String { + String::default() + } + } + )* + }; +} + +solidity_type_name! { + u8 => "uint8" true = "0", + u32 => "uint32" true = "0", + u64 => "uint64" true = "0", + u128 => "uint128" true = "0", + U256 => "uint256" true = "0", + bytes4 => "bytes4" true = "bytes4(0)", + H160 => "address" true = "0x0000000000000000000000000000000000000000", + string => "string" false = "\"\"", + bytes => "bytes" false = "hex\"\"", + bool => "bool" true = "false", +} + +impl SolidityTypeName for void { + fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { + Ok(()) + } + fn is_simple() -> bool { + true + } + fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { + Ok(()) + } + fn is_void() -> bool { + true + } +} + +impl SolidityTypeName for Vec { + fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + T::solidity_name(writer, tc)?; + write!(writer, "[]") + } + fn is_simple() -> bool { + false + } + fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + write!(writer, "new ")?; + T::solidity_name(writer, tc)?; + write!(writer, "[](0)") + } +} + +macro_rules! count { + () => (0usize); + ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); +} + +macro_rules! impl_tuples { + ($($ident:ident)+) => { + impl<$($ident: SolidityTypeName + 'static),+> SolidityType for ($($ident,)+) { + fn names(tc: &TypeCollector) -> Vec { + let mut collected = Vec::with_capacity(Self::len()); + $({ + let mut out = string::new(); + $ident::solidity_name(&mut out, tc).expect("no fmt error"); + collected.push(out); + })*; + collected + } + + fn len() -> usize { + count!($($ident)*) + } + } + impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) { + fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + write!(writer, "{}", tc.collect_tuple::()) + } + fn is_simple() -> bool { + false + } + #[allow(unused_assignments)] + fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + write!(writer, "{}(", tc.collect_tuple::())?; + let mut first = true; + $( + if !first { + write!(writer, ",")?; + } else { + first = false; + } + <$ident>::solidity_default(writer, tc)?; + )* + write!(writer, ")") + } + } + }; +} + +impl_tuples! {A} +impl_tuples! {A B} +impl_tuples! {A B C} +impl_tuples! {A B C D} +impl_tuples! {A B C D E} +impl_tuples! {A B C D E F} +impl_tuples! {A B C D E F G} +impl_tuples! {A B C D E F G H} +impl_tuples! {A B C D E F G H I} +impl_tuples! {A B C D E F G H I J} + +impl StructCollect for Property { + fn name() -> String { + "Property".into() + } + + fn declaration() -> String { + use std::fmt::Write; + + let mut str = String::new(); + writeln!(str, "/// @dev Property struct").unwrap(); + writeln!(str, "struct {} {{", Self::name()).unwrap(); + writeln!(str, "\tstring key;").unwrap(); + writeln!(str, "\tbytes value;").unwrap(); + writeln!(str, "}}").unwrap(); + str + } +} + +impl SolidityTypeName for Property { + fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + write!(writer, "{}", tc.collect_struct::()) + } + + fn is_simple() -> bool { + false + } + + fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + write!(writer, "{}(", tc.collect_struct::())?; + address::solidity_default(writer, tc)?; + write!(writer, ",")?; + uint256::solidity_default(writer, tc)?; + write!(writer, ")") + } +} + +impl SolidityType for Property { + fn names(tc: &TypeCollector) -> Vec { + let mut collected = Vec::with_capacity(Self::len()); + { + let mut out = string::new(); + string::solidity_name(&mut out, tc).expect("no fmt error"); + collected.push(out); + } + { + let mut out = string::new(); + bytes::solidity_name(&mut out, tc).expect("no fmt error"); + collected.push(out); + } + collected + } + + fn len() -> usize { + 2 + } +} --- /dev/null +++ b/crates/evm-coder/src/solidity/mod.rs @@ -0,0 +1,421 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +//! Implementation detail of [`crate::solidity_interface`] macro code-generation. +//! You should not rely on any public item from this module, as it is only intended to be used +//! by procedural macro, API and output format may be changed at any time. +//! +//! Purpose of this module is to receive solidity contract definition in module-specified +//! format, and then output string, representing interface of this contract in solidity language + +mod traits; +pub use traits::*; +mod impls; + +#[cfg(not(feature = "std"))] +use alloc::{string::String, vec::Vec, collections::BTreeMap, format}; +#[cfg(feature = "std")] +use std::collections::BTreeMap; +use core::{ + fmt::{self, Write}, + marker::PhantomData, + cell::{Cell, RefCell}, + cmp::Reverse, +}; +use impl_trait_for_tuples::impl_for_tuples; +use crate::{types::*, custom_signature::SignatureUnit}; + +#[derive(Default)] +pub struct TypeCollector { + /// Code => id + /// id ordering is required to perform topo-sort on the resulting data + structs: RefCell>, + anonymous: RefCell, usize>>, + id: Cell, +} +impl TypeCollector { + pub fn new() -> Self { + Self::default() + } + pub fn collect(&self, item: string) { + let id = self.next_id(); + self.structs.borrow_mut().insert(item, id); + } + pub fn next_id(&self) -> usize { + let v = self.id.get(); + self.id.set(v + 1); + v + } + pub fn collect_tuple(&self) -> String { + let names = T::names(self); + if let Some(id) = self.anonymous.borrow().get(&names).cloned() { + return format!("Tuple{}", id); + } + let id = self.next_id(); + let mut str = String::new(); + writeln!(str, "/// @dev anonymous struct").unwrap(); + writeln!(str, "struct Tuple{} {{", id).unwrap(); + for (i, name) in names.iter().enumerate() { + writeln!(str, "\t{} field_{};", name, i).unwrap(); + } + writeln!(str, "}}").unwrap(); + self.collect(str); + self.anonymous.borrow_mut().insert(names, id); + format!("Tuple{}", id) + } + pub fn collect_struct(&self) -> String { + self.collect(::declaration()); + ::name() + } + pub fn finish(self) -> Vec { + let mut data = self.structs.into_inner().into_iter().collect::>(); + data.sort_by_key(|(_, id)| Reverse(*id)); + data.into_iter().map(|(code, _)| code).collect() + } +} +#[derive(Default)] +pub struct UnnamedArgument(PhantomData<*const T>); + +impl SolidityArguments for UnnamedArgument { + fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + if !T::is_void() { + T::solidity_name(writer, tc)?; + if !T::is_simple() { + write!(writer, " memory")?; + } + Ok(()) + } else { + Ok(()) + } + } + fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } + fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + T::solidity_default(writer, tc) + } + fn len(&self) -> usize { + if T::is_void() { + 0 + } else { + 1 + } + } +} + +pub struct NamedArgument(&'static str, PhantomData<*const T>); + +impl NamedArgument { + pub fn new(name: &'static str) -> Self { + Self(name, Default::default()) + } +} + +impl SolidityArguments for NamedArgument { + fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + if !T::is_void() { + T::solidity_name(writer, tc)?; + if !T::is_simple() { + write!(writer, " memory")?; + } + write!(writer, " {}", self.0) + } else { + Ok(()) + } + } + fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { + writeln!(writer, "\t{prefix}\t{};", self.0) + } + fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + T::solidity_default(writer, tc) + } + fn len(&self) -> usize { + if T::is_void() { + 0 + } else { + 1 + } + } +} + +pub struct SolidityEventArgument(pub bool, &'static str, PhantomData<*const T>); + +impl SolidityEventArgument { + pub fn new(indexed: bool, name: &'static str) -> Self { + Self(indexed, name, Default::default()) + } +} + +impl SolidityArguments for SolidityEventArgument { + fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + if !T::is_void() { + T::solidity_name(writer, tc)?; + if self.0 { + write!(writer, " indexed")?; + } + write!(writer, " {}", self.1) + } else { + Ok(()) + } + } + fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { + writeln!(writer, "\t{prefix}\t{};", self.1) + } + fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + T::solidity_default(writer, tc) + } + fn len(&self) -> usize { + if T::is_void() { + 0 + } else { + 1 + } + } +} + +impl SolidityArguments for () { + fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { + Ok(()) + } + fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result { + Ok(()) + } + fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result { + Ok(()) + } + fn len(&self) -> usize { + 0 + } +} + +#[impl_for_tuples(1, 12)] +impl SolidityArguments for Tuple { + for_tuples!( where #( Tuple: SolidityArguments ),* ); + + fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + let mut first = true; + for_tuples!( #( + if !Tuple.is_empty() { + if !first { + write!(writer, ", ")?; + } + first = false; + Tuple.solidity_name(writer, tc)?; + } + )* ); + Ok(()) + } + fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result { + for_tuples!( #( + Tuple.solidity_get(prefix, writer)?; + )* ); + Ok(()) + } + fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result { + if self.is_empty() { + Ok(()) + } else if self.len() == 1 { + for_tuples!( #( + Tuple.solidity_default(writer, tc)?; + )* ); + Ok(()) + } else { + write!(writer, "(")?; + let mut first = true; + for_tuples!( #( + if !Tuple.is_empty() { + if !first { + write!(writer, ", ")?; + } + first = false; + Tuple.solidity_default(writer, tc)?; + } + )* ); + write!(writer, ")")?; + Ok(()) + } + } + fn len(&self) -> usize { + for_tuples!( #( Tuple.len() )+* ) + } +} + +pub enum SolidityMutability { + Pure, + View, + Mutable, +} +pub struct SolidityFunction { + pub docs: &'static [&'static str], + pub selector: u32, + pub hide: bool, + pub custom_signature: SignatureUnit, + pub name: &'static str, + pub args: A, + pub result: R, + pub mutability: SolidityMutability, + pub is_payable: bool, +} +impl SolidityFunctions for SolidityFunction { + fn solidity_name( + &self, + is_impl: bool, + writer: &mut impl fmt::Write, + tc: &TypeCollector, + ) -> fmt::Result { + let hide_comment = self.hide.then_some("// ").unwrap_or(""); + for doc in self.docs { + writeln!(writer, "\t{hide_comment}///{}", doc)?; + } + writeln!( + writer, + "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},", + self.selector + )?; + writeln!( + writer, + "\t{hide_comment}/// or in textual repr: {}", + self.custom_signature.as_str().expect("bad utf-8") + )?; + write!(writer, "\t{hide_comment}function {}(", self.name)?; + self.args.solidity_name(writer, tc)?; + write!(writer, ")")?; + if is_impl { + write!(writer, " public")?; + } else { + write!(writer, " external")?; + } + match &self.mutability { + SolidityMutability::Pure => write!(writer, " pure")?, + SolidityMutability::View => write!(writer, " view")?, + SolidityMutability::Mutable => {} + } + if self.is_payable { + write!(writer, " payable")?; + } + if !self.result.is_empty() { + write!(writer, " returns (")?; + self.result.solidity_name(writer, tc)?; + write!(writer, ")")?; + } + if is_impl { + writeln!(writer, " {{")?; + writeln!(writer, "\t{hide_comment}\trequire(false, stub_error);")?; + self.args.solidity_get(hide_comment, writer)?; + match &self.mutability { + SolidityMutability::Pure => {} + SolidityMutability::View => writeln!(writer, "\t{hide_comment}\tdummy;")?, + SolidityMutability::Mutable => writeln!(writer, "\t{hide_comment}\tdummy = 0;")?, + } + if !self.result.is_empty() { + write!(writer, "\t{hide_comment}\treturn ")?; + self.result.solidity_default(writer, tc)?; + writeln!(writer, ";")?; + } + writeln!(writer, "\t{hide_comment}}}")?; + } else { + writeln!(writer, ";")?; + } + if self.hide { + writeln!(writer, "// FORMATTING: FORCE NEWLINE")?; + } + Ok(()) + } +} + +#[impl_for_tuples(0, 48)] +impl SolidityFunctions for Tuple { + for_tuples!( where #( Tuple: SolidityFunctions ),* ); + + fn solidity_name( + &self, + is_impl: bool, + writer: &mut impl fmt::Write, + tc: &TypeCollector, + ) -> fmt::Result { + let mut first = false; + for_tuples!( #( + Tuple.solidity_name(is_impl, writer, tc)?; + )* ); + Ok(()) + } +} + +pub struct SolidityInterface { + pub docs: &'static [&'static str], + pub selector: bytes4, + pub name: &'static str, + pub is: &'static [&'static str], + pub functions: F, +} + +impl SolidityInterface { + pub fn format( + &self, + is_impl: bool, + out: &mut impl fmt::Write, + tc: &TypeCollector, + ) -> fmt::Result { + const ZERO_BYTES: [u8; 4] = [0; 4]; + for doc in self.docs { + writeln!(out, "///{}", doc)?; + } + if self.selector != ZERO_BYTES { + writeln!( + out, + "/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}", + u32::from_be_bytes(self.selector) + )?; + } + if is_impl { + write!(out, "contract ")?; + } else { + write!(out, "interface ")?; + } + write!(out, "{}", self.name)?; + if !self.is.is_empty() { + write!(out, " is")?; + for (i, n) in self.is.iter().enumerate() { + if i != 0 { + write!(out, ",")?; + } + write!(out, " {}", n)?; + } + } + writeln!(out, " {{")?; + self.functions.solidity_name(is_impl, out, tc)?; + writeln!(out, "}}")?; + Ok(()) + } +} + +pub struct SolidityEvent { + pub name: &'static str, + pub args: A, +} + +impl SolidityFunctions for SolidityEvent { + fn solidity_name( + &self, + _is_impl: bool, + writer: &mut impl fmt::Write, + tc: &TypeCollector, + ) -> fmt::Result { + write!(writer, "\tevent {}(", self.name)?; + self.args.solidity_name(writer, tc)?; + writeln!(writer, ");") + } +} --- /dev/null +++ b/crates/evm-coder/src/solidity/traits.rs @@ -0,0 +1,48 @@ +use super::TypeCollector; +use core::fmt; + +pub trait StructCollect: 'static { + /// Structure name. + fn name() -> String; + /// Structure declaration. + fn declaration() -> String; +} + +pub trait SolidityEnum: 'static { + fn solidity_option(&self) -> &str; +} + +pub trait SolidityTypeName: 'static { + fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; + /// "simple" types are stored inline, no `memory` modifier should be used in solidity + fn is_simple() -> bool; + fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; + /// Specialization + fn is_void() -> bool { + false + } +} + +pub trait SolidityType { + fn names(tc: &TypeCollector) -> Vec; + fn len() -> usize; +} + +pub trait SolidityArguments { + fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; + fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result; + fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result; + fn is_empty(&self) -> bool { + self.len() == 0 + } + fn len(&self) -> usize; +} + +pub trait SolidityFunctions { + fn solidity_name( + &self, + is_impl: bool, + writer: &mut impl fmt::Write, + tc: &TypeCollector, + ) -> fmt::Result; +} --- /dev/null +++ b/crates/evm-coder/tests/abi_derive_generation.rs @@ -0,0 +1,841 @@ +mod test_struct { + use evm_coder_procedural::AbiCoder; + use evm_coder::types::bytes; + + #[test] + fn empty_struct() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/build_failed/abi_derive_struct_generation.rs"); + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct1SimpleParam { + _a: u8, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct1DynamicParam { + _a: String, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2SimpleParam { + _a: u8, + _b: u32, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2DynamicParam { + _a: String, + _b: bytes, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2MixedParam { + _a: u8, + _b: bytes, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct1DerivedSimpleParam { + _a: TypeStruct1SimpleParam, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2DerivedSimpleParam { + _a: TypeStruct1SimpleParam, + _b: TypeStruct2SimpleParam, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct1DerivedDynamicParam { + _a: TypeStruct1DynamicParam, + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2DerivedDynamicParam { + _a: TypeStruct1DynamicParam, + _b: TypeStruct2DynamicParam, + } + + /// Some docs + /// At multi + /// line + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct3DerivedMixedParam { + /// Docs for A + /// multi + /// line + _a: TypeStruct1SimpleParam, + /// Docs for B + _b: TypeStruct2DynamicParam, + /// Docs for C + _c: TypeStruct2MixedParam, + } + + #[test] + #[cfg(feature = "stubgen")] + fn struct_collect_type_struct3_derived_mixed_param() { + assert_eq!( + ::name(), + "TypeStruct3DerivedMixedParam" + ); + similar_asserts::assert_eq!( + ::declaration(), + r#"/// @dev Some docs +/// At multi +/// line +struct TypeStruct3DerivedMixedParam { + /// @dev Docs for A + /// multi + /// line + TypeStruct1SimpleParam _a; + /// @dev Docs for B + TypeStruct2DynamicParam _b; + /// @dev Docs for C + TypeStruct2MixedParam _c; +} +"# + ); + } + + #[test] + fn impl_abi_type_signature() { + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "(uint8)" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "(string)" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "(uint8,uint32)" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "(string,bytes)" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "(uint8,bytes)" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "((uint8))" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "((uint8),(uint8,uint32))" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "((string))" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "((string),(string,bytes))" + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + "((uint8),(string,bytes),(uint8,bytes))" + ); + } + + #[test] + fn impl_abi_type_is_dynamic() { + assert_eq!( + ::is_dynamic(), + false + ); + assert_eq!( + ::is_dynamic(), + true + ); + assert_eq!( + ::is_dynamic(), + false + ); + assert_eq!( + ::is_dynamic(), + true + ); + assert_eq!( + ::is_dynamic(), + true + ); + assert_eq!( + ::is_dynamic(), + false + ); + assert_eq!( + ::is_dynamic(), + false + ); + assert_eq!( + ::is_dynamic(), + true + ); + assert_eq!( + ::is_dynamic(), + true + ); + assert_eq!( + ::is_dynamic(), + true + ); + } + + #[test] + fn impl_abi_type_size() { + const ABI_ALIGNMENT: usize = 32; + assert_eq!( + ::size(), + ABI_ALIGNMENT + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 2 + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 2 + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 2 + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 3 + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 3 + ); + assert_eq!( + ::size(), + ABI_ALIGNMENT * 5 + ); + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct1SimpleParam(u8); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct1DynamicParam(String); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2SimpleParam(u8, u32); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2DynamicParam(String, bytes); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2MixedParam(u8, bytes); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam); + + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam); + + /// Some docs + /// At multi + /// line + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct3DerivedMixedParam( + /// Docs for A + /// multi + /// line + TupleStruct1SimpleParam, + TupleStruct2DynamicParam, + /// Docs for C + TupleStruct2MixedParam, + ); + + #[test] + #[cfg(feature = "stubgen")] + fn struct_collect_tuple_struct3_derived_mixed_param() { + assert_eq!( + ::name(), + "TupleStruct3DerivedMixedParam" + ); + similar_asserts::assert_eq!( + ::declaration(), + r#"/// @dev Some docs +/// At multi +/// line +struct TupleStruct3DerivedMixedParam { + /// @dev Docs for A + /// multi + /// line + TupleStruct1SimpleParam field0; + TupleStruct2DynamicParam field1; + /// @dev Docs for C + TupleStruct2MixedParam field2; +} +"# + ); + } + + #[test] + fn impl_abi_type_signature_same_for_structs() { + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap() + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap() + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap() + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap() + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE + .as_str() + .unwrap(), + ); + } + + #[test] + fn impl_abi_type_is_dynamic_same_for_structs() { + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + } + + #[test] + fn impl_abi_type_size_same_for_structs() { + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + assert_eq!( + ::size(), + ::size() + ); + } + + const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef; + + fn test_impl( + tuple_data: Tuple, + tuple_struct_data: TupleStruct, + type_struct_data: TypeStruct, + ) where + TypeStruct: evm_coder::abi::AbiWrite + + evm_coder::abi::AbiRead + + std::cmp::PartialEq + + std::fmt::Debug, + TupleStruct: evm_coder::abi::AbiWrite + + evm_coder::abi::AbiRead + + std::cmp::PartialEq + + std::fmt::Debug, + Tuple: evm_coder::abi::AbiWrite + + evm_coder::abi::AbiRead + + std::cmp::PartialEq + + std::fmt::Debug, + { + let encoded_type_struct = test_abi_write_impl(&type_struct_data); + let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data); + let encoded_tuple = test_abi_write_impl(&tuple_data); + + similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct); + similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct); + + { + let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap(); + let restored_struct_data = ::abi_read(&mut decoder).unwrap(); + assert_eq!(restored_struct_data, type_struct_data); + } + { + let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap(); + let restored_struct_data = ::abi_read(&mut decoder).unwrap(); + assert_eq!(restored_struct_data, tuple_struct_data); + } + + { + let (_, mut decoder) = + evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap(); + let restored_tuple_data = ::abi_read(&mut decoder).unwrap(); + assert_eq!(restored_tuple_data, tuple_data); + } + { + let (_, mut decoder) = + evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap(); + let restored_tuple_data = ::abi_read(&mut decoder).unwrap(); + assert_eq!(restored_tuple_data, tuple_data); + } + } + + fn test_abi_write_impl(data: &A) -> Vec + where + A: evm_coder::abi::AbiWrite + + evm_coder::abi::AbiRead + + std::cmp::PartialEq + + std::fmt::Debug, + { + let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER); + data.abi_write(&mut writer); + let encoded_tuple = writer.finish(); + encoded_tuple + } + + #[test] + fn codec_struct_1_simple() { + let _a = 0xff; + test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>( + (_a,), + TupleStruct1SimpleParam(_a), + TypeStruct1SimpleParam { _a }, + ); + } + + #[test] + fn codec_struct_1_dynamic() { + let _a: String = "some string".into(); + test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>( + (_a.clone(),), + TupleStruct1DynamicParam(_a.clone()), + TypeStruct1DynamicParam { _a }, + ); + } + + #[test] + fn codec_struct_1_derived_simple() { + let _a: u8 = 0xff; + test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>( + ((_a,),), + TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)), + TypeStruct1DerivedSimpleParam { + _a: TypeStruct1SimpleParam { _a }, + }, + ); + } + + #[test] + fn codec_struct_1_derived_dynamic() { + let _a: String = "some string".into(); + test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>( + ((_a.clone(),),), + TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())), + TypeStruct1DerivedDynamicParam { + _a: TypeStruct1DynamicParam { _a }, + }, + ); + } + + #[test] + fn codec_struct_2_simple() { + let _a = 0xff; + let _b = 0xbeefbaba; + test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>( + (_a, _b), + TupleStruct2SimpleParam(_a, _b), + TypeStruct2SimpleParam { _a, _b }, + ); + } + + #[test] + fn codec_struct_2_dynamic() { + let _a: String = "some string".into(); + let _b: bytes = bytes(vec![0x11, 0x22, 0x33]); + test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>( + (_a.clone(), _b.clone()), + TupleStruct2DynamicParam(_a.clone(), _b.clone()), + TypeStruct2DynamicParam { _a, _b }, + ); + } + + #[test] + fn codec_struct_2_mixed() { + let _a: u8 = 0xff; + let _b: bytes = bytes(vec![0x11, 0x22, 0x33]); + test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>( + (_a.clone(), _b.clone()), + TupleStruct2MixedParam(_a.clone(), _b.clone()), + TypeStruct2MixedParam { _a, _b }, + ); + } + + #[test] + fn codec_struct_2_derived_simple() { + let _a = 0xff; + let _b = 0xbeefbaba; + test_impl::< + ((u8,), (u8, u32)), + TupleStruct2DerivedSimpleParam, + TypeStruct2DerivedSimpleParam, + >( + ((_a,), (_a, _b)), + TupleStruct2DerivedSimpleParam( + TupleStruct1SimpleParam(_a), + TupleStruct2SimpleParam(_a, _b), + ), + TypeStruct2DerivedSimpleParam { + _a: TypeStruct1SimpleParam { _a }, + _b: TypeStruct2SimpleParam { _a, _b }, + }, + ); + } + + #[test] + fn codec_struct_2_derived_dynamic() { + let _a = "some string".to_string(); + let _b = bytes(vec![0x11, 0x22, 0x33]); + test_impl::< + ((String,), (String, bytes)), + TupleStruct2DerivedDynamicParam, + TypeStruct2DerivedDynamicParam, + >( + ((_a.clone(),), (_a.clone(), _b.clone())), + TupleStruct2DerivedDynamicParam( + TupleStruct1DynamicParam(_a.clone()), + TupleStruct2DynamicParam(_a.clone(), _b.clone()), + ), + TypeStruct2DerivedDynamicParam { + _a: TypeStruct1DynamicParam { _a: _a.clone() }, + _b: TypeStruct2DynamicParam { _a, _b }, + }, + ); + } + + #[test] + fn codec_struct_3_derived_mixed() { + let int = 0xff; + let by = bytes(vec![0x11, 0x22, 0x33]); + let string = "some string".to_string(); + test_impl::< + ((u8,), (String, bytes), (u8, bytes)), + TupleStruct3DerivedMixedParam, + TypeStruct3DerivedMixedParam, + >( + ((int,), (string.clone(), by.clone()), (int, by.clone())), + TupleStruct3DerivedMixedParam( + TupleStruct1SimpleParam(int), + TupleStruct2DynamicParam(string.clone(), by.clone()), + TupleStruct2MixedParam(int, by.clone()), + ), + TypeStruct3DerivedMixedParam { + _a: TypeStruct1SimpleParam { _a: int }, + _b: TypeStruct2DynamicParam { + _a: string.clone(), + _b: by.clone(), + }, + _c: TypeStruct2MixedParam { _a: int, _b: by }, + }, + ); + } + + #[derive(AbiCoder, PartialEq, Debug)] + struct TypeStruct2SimpleStruct1Simple { + _a: TypeStruct2SimpleParam, + _b: TypeStruct2SimpleParam, + _c: u8, + } + #[derive(AbiCoder, PartialEq, Debug)] + struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8); + + #[test] + fn codec_struct_2_struct_simple_1_simple() { + let _a = 0xff; + let _b = 0xbeefbaba; + test_impl::< + ((u8, u32), (u8, u32), u8), + TupleStruct2SimpleStruct1Simple, + TypeStruct2SimpleStruct1Simple, + >( + ((_a, _b), (_a, _b), _a), + TupleStruct2SimpleStruct1Simple( + TupleStruct2SimpleParam(_a, _b), + TupleStruct2SimpleParam(_a, _b), + _a, + ), + TypeStruct2SimpleStruct1Simple { + _a: TypeStruct2SimpleParam { _a, _b }, + _b: TypeStruct2SimpleParam { _a, _b }, + _c: _a, + }, + ); + } +} + +mod test_enum { + use evm_coder::AbiCoder; + + /// Some docs + /// At multi + /// line + #[derive(AbiCoder, Debug, PartialEq, Default)] + #[repr(u8)] + enum Color { + /// Docs for Red + /// multi + /// line + Red, + Green, + /// Docs for Blue + #[default] + Blue, + } + + #[test] + fn empty() {} + + #[test] + fn bad_enums() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs"); + } + + #[test] + fn impl_abi_type_signature_same_for_structs() { + assert_eq!( + ::SIGNATURE + .as_str() + .unwrap(), + ::SIGNATURE.as_str().unwrap() + ); + } + + #[test] + fn impl_abi_type_is_dynamic_same_for_structs() { + assert_eq!( + ::is_dynamic(), + ::is_dynamic() + ); + } + + #[test] + fn impl_abi_type_size_same_for_structs() { + assert_eq!( + ::size(), + ::size() + ); + } + + #[test] + fn test_coder() { + const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef; + + let encoded_enum = { + let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER); + ::abi_write(&Color::Green, &mut writer); + writer.finish() + }; + + let encoded_u8 = { + let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER); + ::abi_write(&(Color::Green as u8), &mut writer); + writer.finish() + }; + + similar_asserts::assert_eq!(encoded_enum, encoded_u8); + + { + let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap(); + let restored_enum_data = + ::abi_read(&mut decoder).unwrap(); + assert_eq!(restored_enum_data, Color::Green); + } + } + + #[test] + #[cfg(feature = "stubgen")] + fn struct_collect_enum() { + assert_eq!( + ::name(), + "Color" + ); + similar_asserts::assert_eq!( + ::declaration(), + r#"/// @dev Some docs +/// At multi +/// line +enum Color { + /// @dev Docs for Red + /// multi + /// line + Red, + Green, + /// @dev Docs for Blue + Blue +} +"# + ); + } +} --- /dev/null +++ b/crates/evm-coder/tests/build_failed/abi_derive_enum_generation.rs @@ -0,0 +1,36 @@ +use evm_coder_procedural::AbiCoder; + +#[derive(AbiCoder)] +enum NonRepr { + A, + B, + C, +} + +#[derive(AbiCoder)] +#[repr(u32)] +enum NonReprU8 { + A, + B, + C, +} + +#[derive(AbiCoder)] +#[repr(u8)] +enum RustEnum { + A(u128), + B, + C, +} + +#[derive(AbiCoder)] +#[repr(u8)] +enum WithExplicit { + A = 128, + B, + C, +} + +fn main() { + assert!(false); +} --- /dev/null +++ b/crates/evm-coder/tests/build_failed/abi_derive_enum_generation.stderr @@ -0,0 +1,23 @@ +error: Enum is not "repr(u8)" + --> tests/build_failed/abi_derive_enum_generation.rs:4:6 + | +4 | enum NonRepr { + | ^^^^^^^ + +error: Enum is not "repr(u8)" + --> tests/build_failed/abi_derive_enum_generation.rs:11:8 + | +11 | #[repr(u32)] + | ^^^ + +error: Enumeration parameters should not have fields + --> tests/build_failed/abi_derive_enum_generation.rs:21:2 + | +21 | A(u128), + | ^ + +error: Enumeration options should not have an explicit specified value + --> tests/build_failed/abi_derive_enum_generation.rs:29:2 + | +29 | A = 128, + | ^ --- /dev/null +++ b/crates/evm-coder/tests/build_failed/abi_derive_struct_generation.rs @@ -0,0 +1,11 @@ +use evm_coder_procedural::AbiCoder; + +#[derive(AbiCoder, PartialEq, Debug)] +struct EmptyStruct {} + +#[derive(AbiCoder, PartialEq, Debug)] +struct EmptyTupleStruct(); + +fn main() { + assert!(false); +} --- /dev/null +++ b/crates/evm-coder/tests/build_failed/abi_derive_struct_generation.stderr @@ -0,0 +1,11 @@ +error: Empty structs not supported + --> tests/build_failed/abi_derive_struct_generation.rs:4:8 + | +4 | struct EmptyStruct {} + | ^^^^^^^^^^^ + +error: Empty structs not supported + --> tests/build_failed/abi_derive_struct_generation.rs:7:8 + | +7 | struct EmptyTupleStruct(); + | ^^^^^^^^^^^^^^^^ --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -309,13 +309,13 @@ jsonrpsee = { version = "0.15.1", features = ["server", "macros"] } tokio = { version = "1.19.2", features = ["time"] } -fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } unique-rpc = { default-features = false, path = "../rpc" } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } @@ -335,3 +335,7 @@ 'quartz-runtime?/try-runtime', 'opal-runtime?/try-runtime', ] +sapphire-runtime = [ + 'opal-runtime', + 'opal-runtime/become-sapphire', +] --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -66,7 +66,7 @@ } #[cfg(not(feature = "unique-runtime"))] -/// PARA_ID for Opal/Quartz +/// PARA_ID for Opal/Sapphire/Quartz const PARA_ID: u32 = 2095; #[cfg(feature = "unique-runtime")] @@ -89,7 +89,11 @@ return RuntimeId::Quartz; } - if self.id().starts_with("opal") || self.id() == "dev" || self.id() == "local_testnet" { + if self.id().starts_with("opal") + || self.id().starts_with("sapphire") + || self.id() == "dev" + || self.id() == "local_testnet" + { return RuntimeId::Opal; } --- a/node/cli/src/cli.rs +++ b/node/cli/src/cli.rs @@ -101,6 +101,8 @@ "Unique" } else if cfg!(feature = "quartz-runtime") { "Quartz" + } else if cfg!(feature = "sapphire-runtime") { + "Sapphire" } else { "Opal" } --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -46,6 +46,7 @@ use cumulus_relay_chain_rpc_interface::{RelayChainRpcInterface, create_client_and_start_worker}; // Substrate Imports +use sp_api::BlockT; use sc_executor::NativeElseWasmExecutor; use sc_executor::NativeExecutionDispatch; use sc_network::{NetworkService, NetworkBlock}; @@ -159,7 +160,10 @@ } } -pub fn open_frontier_backend(config: &Configuration) -> Result>, String> { +pub fn open_frontier_backend>( + client: Arc, + config: &Configuration, +) -> Result>, String> { let config_dir = config .base_path .as_ref() @@ -170,6 +174,7 @@ let database_dir = config_dir.join("frontier").join("db"); Ok(Arc::new(fc_db::Backend::::new( + client, &fc_db::DatabaseSettings { source: fc_db::DatabaseSource::RocksDb { path: database_dir, @@ -285,7 +290,7 @@ let filter_pool: Option = Some(Arc::new(Mutex::new(BTreeMap::new()))); - let frontier_backend = open_frontier_backend(config)?; + let frontier_backend = open_frontier_backend(client.clone(), config)?; let import_queue = build_import_queue( client.clone(), --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -40,20 +40,20 @@ substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } tokio = { version = "1.19.2", features = ["macros", "sync"] } -pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-common = { default-features = false, path = "../../pallets/common" } up-common = { path = "../../primitives/common" } pallet-unique = { path = "../../pallets/unique" } uc-rpc = { path = "../../client/rpc" } up-rpc = { path = "../../primitives/rpc" } -app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"} +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc" } rmrk-rpc = { path = "../../primitives/rmrk-rpc" } up-data-structs = { default-features = false, path = "../../primitives/data-structs" } --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -216,6 +216,7 @@ let overrides = overrides_handle::<_, _, R>(client.clone()); + let execute_gas_limit_multiplier = 10; io.merge( Eth::new( client.clone(), @@ -230,6 +231,7 @@ block_data_cache.clone(), fee_history_cache, fee_history_limit, + execute_gas_limit_multiplier, ) .into_rpc(), )?; --- a/pallets/app-promotion/Cargo.toml +++ b/pallets/app-promotion/Cargo.toml @@ -47,28 +47,30 @@ ################################################################################ # Substrate Dependencies -codec = { default-features = false, features = ['derive'], package = 'parity-scale-codec', version = '3.1.2' } -frame-benchmarking = {default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +codec = { default-features = false, features = [ + 'derive', +], package = 'parity-scale-codec', version = '3.1.2' } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -frame-system ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-randomness-collective-flip = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -sp-io ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } serde = { default-features = false, features = ['derive'], version = '1.0.130' } ################################################################################ # local dependencies -up-data-structs ={ default-features = false, path = "../../primitives/data-structs" } -pallet-common ={ default-features = false, path = "../common" } -pallet-unique ={ default-features = false, path = "../unique" } -pallet-evm-contract-helpers ={ default-features = false, path = "../evm-contract-helpers" } -pallet-evm-migration ={ default-features = false, path = "../evm-migration" } +up-data-structs = { default-features = false, path = "../../primitives/data-structs" } +pallet-common = { default-features = false, path = "../common" } +pallet-unique = { default-features = false, path = "../unique" } +pallet-evm-contract-helpers = { default-features = false, path = "../evm-contract-helpers" } +pallet-evm-migration = { default-features = false, path = "../evm-migration" } # [dev-dependencies] --- a/pallets/app-promotion/src/lib.rs +++ b/pallets/app-promotion/src/lib.rs @@ -102,7 +102,7 @@ use frame_system::pallet_prelude::*; #[pallet::config] - pub trait Config: frame_system::Config + pallet_evm::account::Config { + pub trait Config: frame_system::Config + pallet_evm::Config { /// Type to interact with the native token type Currency: ExtendedLockableCurrency + ReservableCurrency; @@ -274,11 +274,13 @@ if !block_pending.is_empty() { block_pending.into_iter().for_each(|(staker, amount)| { - >::unreserve(&staker, amount); + <::Currency as ReservableCurrency>::unreserve( + &staker, amount, + ); }); } - T::WeightInfo::on_initialize(counter) + ::WeightInfo::on_initialize(counter) } } @@ -297,7 +299,7 @@ /// # Arguments /// /// * `admin`: account of the new admin. - #[pallet::weight(T::WeightInfo::set_admin_address())] + #[pallet::weight(::WeightInfo::set_admin_address())] pub fn set_admin_address(origin: OriginFor, admin: T::CrossAccountId) -> DispatchResult { ensure_root(origin)?; @@ -315,7 +317,7 @@ /// # Arguments /// /// * `amount`: in native tokens. - #[pallet::weight(T::WeightInfo::stake())] + #[pallet::weight(::WeightInfo::stake())] pub fn stake(staker: OriginFor, amount: BalanceOf) -> DispatchResult { let staker_id = ensure_signed(staker)?; @@ -388,7 +390,7 @@ /// Moves the sum of all stakes to the `reserved` state. /// After the end of `PendingInterval` this sum becomes completely /// free for further use. - #[pallet::weight(T::WeightInfo::unstake())] + #[pallet::weight(::WeightInfo::unstake())] pub fn unstake(staker: OriginFor) -> DispatchResultWithPostInfo { let staker_id = ensure_signed(staker)?; @@ -421,7 +423,10 @@ Self::unlock_balance(&staker_id, total_staked)?; - >::reserve(&staker_id, total_staked)?; + <::Currency as ReservableCurrency>::reserve( + &staker_id, + total_staked, + )?; TotalStaked::::set( TotalStaked::::get() @@ -445,7 +450,7 @@ /// # Arguments /// /// * `collection_id`: ID of the collection that will be sponsored by `pallet_id` - #[pallet::weight(T::WeightInfo::sponsor_collection())] + #[pallet::weight(::WeightInfo::sponsor_collection())] pub fn sponsor_collection( admin: OriginFor, collection_id: CollectionId, @@ -470,7 +475,7 @@ /// # Arguments /// /// * `collection_id`: ID of the collection that is sponsored by `pallet_id` - #[pallet::weight(T::WeightInfo::stop_sponsoring_collection())] + #[pallet::weight(::WeightInfo::stop_sponsoring_collection())] pub fn stop_sponsoring_collection( admin: OriginFor, collection_id: CollectionId, @@ -499,7 +504,7 @@ /// # Arguments /// /// * `contract_id`: the contract address that will be sponsored by `pallet_id` - #[pallet::weight(T::WeightInfo::sponsor_contract())] + #[pallet::weight(::WeightInfo::sponsor_contract())] pub fn sponsor_contract(admin: OriginFor, contract_id: H160) -> DispatchResult { let admin_id = ensure_signed(admin)?; @@ -525,7 +530,7 @@ /// # Arguments /// /// * `contract_id`: the contract address that is sponsored by `pallet_id` - #[pallet::weight(T::WeightInfo::stop_sponsoring_contract())] + #[pallet::weight(::WeightInfo::stop_sponsoring_contract())] pub fn stop_sponsoring_contract(admin: OriginFor, contract_id: H160) -> DispatchResult { let admin_id = ensure_signed(admin)?; @@ -555,7 +560,7 @@ /// # Arguments /// /// * `stakers_number`: the number of stakers for which recalculation will be performed - #[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))] + #[pallet::weight(::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))] pub fn payout_stakers(admin: OriginFor, stakers_number: Option) -> DispatchResult { let admin_id = ensure_signed(admin)?; @@ -589,7 +594,7 @@ let flush_stake = || -> DispatchResult { if let Some(last_id) = &*last_id.borrow() { if !income_acc.borrow().is_zero() { - >::transfer( + <::Currency as Currency>::transfer( &T::TreasuryAccountId::get(), last_id, *income_acc.borrow(), @@ -700,9 +705,12 @@ /// - `amount`: amount of locked funds. fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf) { if amount.is_zero() { - >::remove_lock(LOCK_IDENTIFIER, &staker); + <::Currency as LockableCurrency>::remove_lock( + LOCK_IDENTIFIER, + &staker, + ); } else { - >::set_lock( + <::Currency as LockableCurrency>::set_lock( LOCK_IDENTIFIER, staker, amount, @@ -717,7 +725,7 @@ pub fn get_locked_balance( staker: impl EncodeLike, ) -> Option>> { - >::locks(staker) + <::Currency as ExtendedLockableCurrency>::locks(staker) .into_iter() .find(|l| l.id == LOCK_IDENTIFIER) } --- a/pallets/common/CHANGELOG.md +++ b/pallets/common/CHANGELOG.md @@ -4,7 +4,7 @@ -## [0.1.11] - 2022-11-16 +## [0.1.12] - 2022-11-16 ### Changed @@ -12,6 +12,14 @@ Removed method overload: single signature `(string, uint256)` is used for both cases. +## [0.1.11] - 2022-11-12 + +### Changed + +- In the `Collection` solidity interface, + the `allowed` function has been renamed to `allow_listed_cross`. + Also `EthCrossAccount` type is now used as `user` arg. + ## [0.1.10] - 2022-11-02 ### Changed --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-common" -version = "0.1.11" +version = "0.1.12" license = "GPLv3" edition = "2021" @@ -17,12 +17,12 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' } evm-coder = { default-features = false, path = '../../crates/evm-coder' } ethereum = { version = "0.12.0", default-features = false } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } serde = { version = "1.0.130", default-features = false } scale-info = { version = "2.0.1", default-features = false, features = [ --- a/pallets/common/src/erc.rs +++ b/pallets/common/src/erc.rs @@ -16,6 +16,7 @@ //! This module contains the implementation of pallet methods for evm. +pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId}; use evm_coder::{ abi::AbiType, solidity_interface, solidity, ToLog, @@ -24,7 +25,6 @@ execution::{Result, Error}, weight, }; -pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId}; use pallet_evm_coder_substrate::dispatch_to_evm; use sp_std::vec::Vec; use up_data_structs::{ @@ -35,7 +35,8 @@ use crate::{ Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf, - eth::convert_cross_account_to_uint256, weights::WeightInfo, + eth::{EthCrossAccount, convert_cross_account_to_uint256}, + weights::WeightInfo, }; /// Events for ethereum collection helper. @@ -529,11 +530,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - fn allowed(&self, user: address) -> Result { - Ok(Pallet::::allowed( - self.id, - T::CrossAccountId::from_eth(user), - )) + fn allowlisted_cross(&self, user: EthCrossAccount) -> Result { + let user = user.into_sub_cross_account::()?; + Ok(Pallet::::allowed(self.id, user)) } /// Add the user to the allowed list. --- a/pallets/common/src/eth.rs +++ b/pallets/common/src/eth.rs @@ -16,8 +16,11 @@ //! The module contains a number of functions for converting and checking ethereum identifiers. -use evm_coder::types::{uint256, address}; -pub use pallet_evm::account::{Config, CrossAccountId}; +use evm_coder::{ + AbiCoder, + types::{uint256, address}, +}; +pub use pallet_evm::{Config, account::CrossAccountId}; use sp_core::H160; use up_data_structs::CollectionId; @@ -109,3 +112,46 @@ Err("All fields of cross account is non zeroed".into()) } } + +/// Cross account struct +#[derive(Debug, Default, AbiCoder)] +pub struct EthCrossAccount { + pub(crate) eth: address, + pub(crate) sub: uint256, +} + +impl EthCrossAccount { + pub fn from_sub_cross_account(cross_account_id: &T::CrossAccountId) -> Self + where + T: pallet_evm::Config, + T::AccountId: AsRef<[u8; 32]>, + { + if cross_account_id.is_canonical_substrate() { + Self { + eth: Default::default(), + sub: convert_cross_account_to_uint256::(cross_account_id), + } + } else { + Self { + eth: *cross_account_id.as_eth(), + sub: Default::default(), + } + } + } + + pub fn into_sub_cross_account(&self) -> evm_coder::execution::Result + where + T: pallet_evm::Config, + T::AccountId: From<[u8; 32]>, + { + if self.eth == Default::default() && self.sub == Default::default() { + Err("All fields of cross account is zeroed".into()) + } else if self.eth == Default::default() { + Ok(convert_uint256_to_cross_account::(self.sub)) + } else if self.sub == Default::default() { + Ok(T::CrossAccountId::from_eth(self.eth)) + } else { + Err("All fields of cross account is non zeroed".into()) + } + } +} --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -342,7 +342,6 @@ #[frame_support::pallet] pub mod pallet { use super::*; - use pallet_evm::account; use dispatch::CollectionDispatch; use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion}; use frame_system::pallet_prelude::*; @@ -353,11 +352,7 @@ #[pallet::config] pub trait Config: - frame_system::Config - + pallet_evm_coder_substrate::Config - + pallet_evm::Config - + TypeInfo - + account::Config + frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config + TypeInfo { /// Weight information for functions of this pallet. type WeightInfo: WeightInfo; @@ -381,6 +376,7 @@ type TreasuryAccountId: Get; /// Address under which the CollectionHelper contract would be available. + #[pallet::constant] type ContractAddress: Get; /// Mapper for token addresses to Ethereum addresses. --- a/pallets/configuration/Cargo.toml +++ b/pallets/configuration/Cargo.toml @@ -16,7 +16,7 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } smallvec = "1.6.1" [features] --- a/pallets/evm-coder-substrate/Cargo.toml +++ b/pallets/evm-coder-substrate/Cargo.toml @@ -12,8 +12,8 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } ethereum = { version = "0.12.0", default-features = false } evm-coder = { default-features = false, path = "../../crates/evm-coder" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } --- a/pallets/evm-contract-helpers/Cargo.toml +++ b/pallets/evm-contract-helpers/Cargo.toml @@ -19,8 +19,8 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } # Unique -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30" } # Locals --- a/pallets/evm-contract-helpers/src/lib.rs +++ b/pallets/evm-contract-helpers/src/lib.rs @@ -41,12 +41,13 @@ #[pallet::config] pub trait Config: - frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config + frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config { /// Overarching event type. type RuntimeEvent: IsType<::RuntimeEvent> + From>; /// Address, under which magic contract will be available + #[pallet::constant] type ContractAddress: Get; /// In case of enabled sponsoring, but no sponsoring rate limit set, --- a/pallets/evm-migration/Cargo.toml +++ b/pallets/evm-migration/Cargo.toml @@ -16,8 +16,8 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [dependencies.codec] default-features = false --- a/pallets/evm-transaction-payment/Cargo.toml +++ b/pallets/evm-transaction-payment/Cargo.toml @@ -14,11 +14,11 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30" } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [dependencies.codec] default-features = false --- a/pallets/evm-transaction-payment/src/lib.rs +++ b/pallets/evm-transaction-payment/src/lib.rs @@ -44,7 +44,7 @@ } #[pallet::config] - pub trait Config: frame_system::Config + pallet_evm::account::Config { + pub trait Config: frame_system::Config + pallet_evm::Config { /// Loosly-coupled handlers for evm call sponsoring type EvmSponsorshipHandler: SponsorshipHandler; } --- a/pallets/fungible/Cargo.toml +++ b/pallets/fungible/Cargo.toml @@ -23,7 +23,7 @@ pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' } ethereum = { version = "0.12.0", default-features = false } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } scale-info = { version = "2.0.1", default-features = false, features = [ "derive", ] } --- a/pallets/fungible/src/erc.rs +++ b/pallets/fungible/src/erc.rs @@ -24,12 +24,16 @@ weight, }; use up_data_structs::CollectionMode; -use pallet_common::erc::{CommonEvmHandler, PrecompileResult}; +use pallet_common::{ + CollectionHandle, + erc::{CommonEvmHandler, PrecompileResult, CollectionCall}, + eth::EthCrossAccount, +}; use sp_std::vec::Vec; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::{call, dispatch_to_evm}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; -use pallet_common::{CollectionHandle, erc::CollectionCall}; +use sp_core::Get; use crate::{ Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply, @@ -132,6 +136,11 @@ Ok(>::get((self.id, owner, spender)).into()) } + + /// @notice Returns collection helper contract address + fn collection_helper_address(&self) -> Result
{ + Ok(T::ContractAddress::get()) + } } #[solidity_interface(name = ERC20Mintable)] --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -106,7 +106,7 @@ pub mod erc; pub mod weights; -pub type CreateItemData = (::CrossAccountId, u128); +pub type CreateItemData = (::CrossAccountId, u128); pub(crate) type SelfWeightOf = ::WeightInfo; #[frame_support::pallet] @@ -379,7 +379,7 @@ let balance_from = >::get((collection.id, from)) .checked_sub(amount) .ok_or(>::TokenValueTooLow)?; - let balance_to = if from != to { + let balance_to = if from != to && amount != 0 { Some( >::get((collection.id, to)) .checked_add(amount) @@ -390,17 +390,18 @@ }; // ========= - - >::nest_if_sent_to_token( - from.clone(), - to, - collection.id, - TokenId::default(), - nesting_budget, - )?; if let Some(balance_to) = balance_to { - // from != to + // from != to && amount != 0 + + >::nest_if_sent_to_token( + from.clone(), + to, + collection.id, + TokenId::default(), + nesting_budget, + )?; + if balance_from == 0 { >::remove((collection.id, from)); >::unnest_if_nested(from, collection.id, TokenId::default()); --- a/pallets/fungible/src/stubs/UniqueFungible.sol +++ b/pallets/fungible/src/stubs/UniqueFungible.sol @@ -18,7 +18,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca contract Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -269,9 +269,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) public view returns (bool) { + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) public view returns (bool) { require(false, stub_error); user; dummy; @@ -547,7 +547,7 @@ event Approval(address indexed owner, address indexed spender, uint256 value); } -/// @dev the ERC-165 identifier for this interface is 0x942e8b22 +/// @dev the ERC-165 identifier for this interface is 0x8cb847c4 contract ERC20 is Dummy, ERC165, ERC20Events { /// @dev EVM selector for this function is: 0x06fdde03, /// or in textual repr: name() @@ -634,6 +634,15 @@ dummy; return 0; } + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() public view returns (address) { + require(false, stub_error); + dummy; + return 0x0000000000000000000000000000000000000000; + } } contract UniqueFungible is Dummy, ERC165, ERC20, ERC20Mintable, ERC20UniqueExtensions, Collection {} --- a/pallets/nonfungible/Cargo.toml +++ b/pallets/nonfungible/Cargo.toml @@ -16,7 +16,7 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-common = { default-features = false, path = '../common' } pallet-structure = { default-features = false, path = '../structure' } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -291,6 +291,7 @@ >::burn_item(), ) } else { + >::check_token_immediate_ownership(self, token, &sender)?; Ok(().into()) } } @@ -320,6 +321,7 @@ >::transfer(), ) } else { + >::check_token_immediate_ownership(self, token, &from)?; Ok(().into()) } } @@ -360,6 +362,8 @@ >::transfer_from(), ) } else { + >::check_allowed(self, &sender, &from, token, nesting_budget)?; + Ok(().into()) } } @@ -380,6 +384,8 @@ >::burn_from(), ) } else { + >::check_allowed(self, &sender, &from, token, nesting_budget)?; + Ok(().into()) } } --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -36,12 +36,14 @@ use pallet_evm_coder_substrate::dispatch_to_evm; use sp_std::vec::Vec; use pallet_common::{ + CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key}, - CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, + eth::EthCrossAccount, }; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::call; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; +use sp_core::Get; use crate::{ AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted, @@ -489,6 +491,11 @@ // TODO: Not implemetable Err("not implemented".into()) } + + /// @notice Returns collection helper contract address + fn collection_helper_address(&self) -> Result
{ + Ok(T::ContractAddress::get()) + } } /// @title ERC721 Token that can be irreversibly burned (destroyed). @@ -721,11 +728,7 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - fn token_properties( - &self, - token_id: uint256, - keys: Vec, - ) -> Result> { + fn properties(&self, token_id: uint256, keys: Vec) -> Result> { let keys = keys .into_iter() .map(|key| { --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -127,7 +127,7 @@ pub mod erc; pub mod weights; -pub type CreateItemData = CreateNftExData<::CrossAccountId>; +pub type CreateItemData = CreateNftExData<::CrossAccountId>; pub(crate) type SelfWeightOf = ::WeightInfo; /// Token data, stored independently from other data used to describe it @@ -814,6 +814,20 @@ >::set_property_permission(collection, sender, permission) } + pub fn check_token_immediate_ownership( + collection: &NonfungibleHandle, + token: TokenId, + possible_owner: &T::CrossAccountId, + ) -> DispatchResult { + let token_data = + >::get((collection.id, token)).ok_or(>::TokenNotFound)?; + ensure!( + &token_data.owner == possible_owner, + >::NoPermission + ); + Ok(()) + } + /// Transfer NFT token from one account to another. /// /// `from` account stops being the owner and `to` account becomes the owner of the token. --- a/pallets/nonfungible/src/stubs/UniqueNFT.sol +++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol @@ -119,7 +119,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca contract Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -370,9 +370,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) public view returns (bool) { + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) public view returns (bool) { require(false, stub_error); user; dummy; @@ -676,7 +676,7 @@ } /// @title Unique extensions for ERC721. -/// @dev the ERC-165 identifier for this interface is 0xb8f094a0 +/// @dev the ERC-165 identifier for this interface is 0xb74c26b7 contract ERC721UniqueExtensions is Dummy, ERC165 { /// @notice A descriptive name for a collection of NFTs in this contract /// @dev EVM selector for this function is: 0x06fdde03, @@ -722,9 +722,9 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - /// @dev EVM selector for this function is: 0xefc26c69, - /// or in textual repr: tokenProperties(uint256,string[]) - function tokenProperties(uint256 tokenId, string[] memory keys) public view returns (Property[] memory) { + /// @dev EVM selector for this function is: 0xe07ede7e, + /// or in textual repr: properties(uint256,string[]) + function properties(uint256 tokenId, string[] memory keys) public view returns (Property[] memory) { require(false, stub_error); tokenId; keys; @@ -920,7 +920,7 @@ /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// @dev the ERC-165 identifier for this interface is 0x80ac58cd +/// @dev the ERC-165 identifier for this interface is 0x983a942b contract ERC721 is Dummy, ERC165, ERC721Events { /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this @@ -1050,6 +1050,15 @@ dummy; return 0x0000000000000000000000000000000000000000; } + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() public view returns (address) { + require(false, stub_error); + dummy; + return 0x0000000000000000000000000000000000000000; + } } contract UniqueNFT is --- a/pallets/proxy-rmrk-core/Cargo.toml +++ b/pallets/proxy-rmrk-core/Cargo.toml @@ -20,7 +20,7 @@ pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" } pallet-structure = { default-features = false, path = "../../pallets/structure" } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" } scale-info = { version = "2.0.1", default-features = false, features = [ --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -178,7 +178,7 @@ use RmrkProperty::*; -/// Maximum number of levels of depth in the token nesting tree. +/// A maximum number of levels of depth in the token nesting tree. pub const NESTING_BUDGET: u32 = 5; type PendingTarget = (CollectionId, TokenId); @@ -190,11 +190,13 @@ #[frame_support::pallet] pub mod pallet { use super::*; - use pallet_evm::account; #[pallet::config] pub trait Config: - frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config + frame_system::Config + + pallet_common::Config + + pallet_nonfungible::Config + + pallet_evm::Config { /// Overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; --- a/pallets/proxy-rmrk-equip/Cargo.toml +++ b/pallets/proxy-rmrk-equip/Cargo.toml @@ -19,7 +19,7 @@ pallet-common = { default-features = false, path = '../common' } pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" } scale-info = { version = "2.0.1", default-features = false, features = [ --- a/pallets/refungible/Cargo.toml +++ b/pallets/refungible/Cargo.toml @@ -16,7 +16,7 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' } pallet-common = { default-features = false, path = '../common' } --- a/pallets/refungible/src/erc.rs +++ b/pallets/refungible/src/erc.rs @@ -31,14 +31,15 @@ }; use frame_support::{BoundedBTreeMap, BoundedVec}; use pallet_common::{ - CollectionHandle, CollectionPropertyPermissions, + CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, erc::{CommonEvmHandler, CollectionCall, static_property::key}, - CommonCollectionOperations, + eth::EthCrossAccount, + Error as CommonError, }; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::{call, dispatch_to_evm}; use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _}; -use sp_core::H160; +use sp_core::{H160, Get}; use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec}; use up_data_structs::{ CollectionId, CollectionPropertiesVec, mapping::TokenAddressMapping, Property, PropertyKey, @@ -482,6 +483,11 @@ // TODO: Not implemetable Err("not implemented".into()) } + + /// @notice Returns collection helper contract address + fn collection_helper_address(&self) -> Result
{ + Ok(T::ContractAddress::get()) + } } /// Returns amount of pieces of `token` that `owner` have @@ -503,6 +509,13 @@ ) -> Result<()> { collection.consume_store_reads(1)?; let total_supply = >::get((collection.id, token)); + + if owner_balance == 0 { + return Err(dispatch_to_evm::( + >::MustBeTokenOwner.into(), + )); + } + if total_supply != owner_balance { return Err("token has multiple owners".into()); } @@ -749,11 +762,7 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - fn token_properties( - &self, - token_id: uint256, - keys: Vec, - ) -> Result> { + fn properties(&self, token_id: uint256, keys: Vec) -> Result> { let keys = keys .into_iter() .map(|key| { --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -452,6 +452,10 @@ token: TokenId, amount: u128, ) -> DispatchResult { + if >::get((collection.id, token, owner)) == 0 { + return Err(>::TokenValueTooLow.into()); + } + let total_supply = >::get((collection.id, token)) .checked_sub(amount) .ok_or(>::TokenValueTooLow)?; @@ -739,12 +743,17 @@ >::ensure_correct_receiver(to)?; let initial_balance_from = >::get((collection.id, token, from)); + + if initial_balance_from == 0 { + return Err(>::TokenValueTooLow.into()); + } + let updated_balance_from = initial_balance_from .checked_sub(amount) .ok_or(>::TokenValueTooLow)?; let mut create_target = false; let from_to_differ = from != to; - let updated_balance_to = if from != to { + let updated_balance_to = if from != to && amount != 0 { let old_balance = >::get((collection.id, token, to)); if old_balance == 0 { create_target = true; @@ -786,16 +795,17 @@ // ========= - >::nest_if_sent_to_token( - from.clone(), - to, - collection.id, - token, - nesting_budget, - )?; + if let Some(updated_balance_to) = updated_balance_to { + // from != to && amount != 0 + + >::nest_if_sent_to_token( + from.clone(), + to, + collection.id, + token, + nesting_budget, + )?; - if let Some(updated_balance_to) = updated_balance_to { - // from != to if updated_balance_from == 0 { >::remove((collection.id, token, from)); >::unnest_if_nested(from, collection.id, token); --- a/pallets/refungible/src/stubs/UniqueRefungible.sol +++ b/pallets/refungible/src/stubs/UniqueRefungible.sol @@ -119,7 +119,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca contract Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -370,9 +370,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) public view returns (bool) { + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) public view returns (bool) { require(false, stub_error); user; dummy; @@ -674,7 +674,7 @@ } /// @title Unique extensions for ERC721. -/// @dev the ERC-165 identifier for this interface is 0x1d4b64d6 +/// @dev the ERC-165 identifier for this interface is 0x12f7d6c1 contract ERC721UniqueExtensions is Dummy, ERC165 { /// @notice A descriptive name for a collection of NFTs in this contract /// @dev EVM selector for this function is: 0x06fdde03, @@ -720,9 +720,9 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - /// @dev EVM selector for this function is: 0xefc26c69, - /// or in textual repr: tokenProperties(uint256,string[]) - function tokenProperties(uint256 tokenId, string[] memory keys) public view returns (Property[] memory) { + /// @dev EVM selector for this function is: 0xe07ede7e, + /// or in textual repr: properties(uint256,string[]) + function properties(uint256 tokenId, string[] memory keys) public view returns (Property[] memory) { require(false, stub_error); tokenId; keys; @@ -919,7 +919,7 @@ /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// @dev the ERC-165 identifier for this interface is 0x58800161 +/// @dev the ERC-165 identifier for this interface is 0x4016cd87 contract ERC721 is Dummy, ERC165, ERC721Events { /// @notice Count all RFTs assigned to an owner /// @dev RFTs assigned to the zero address are considered invalid, and this @@ -1047,6 +1047,15 @@ dummy; return 0x0000000000000000000000000000000000000000; } + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() public view returns (address) { + require(false, stub_error); + dummy; + return 0x0000000000000000000000000000000000000000; + } } contract UniqueRefungible is --- a/pallets/structure/Cargo.toml +++ b/pallets/structure/Cargo.toml @@ -16,7 +16,7 @@ "derive", ] } up-data-structs = { path = "../../primitives/data-structs", default-features = false } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [features] default = ["std"] --- a/pallets/unique/Cargo.toml +++ b/pallets/unique/Cargo.toml @@ -100,7 +100,7 @@ scale-info = { version = "2.0.1", default-features = false, features = [ "derive", ] } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-common = { default-features = false, path = "../common" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' } --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -28,6 +28,7 @@ CollectionById, dispatch::CollectionDispatch, erc::{CollectionHelpersEvents, static_property::key}, + eth::{map_eth_to_id, collection_id_to_address}, Pallet as PalletCommon, }; use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult}; @@ -35,7 +36,7 @@ use sp_std::vec; use up_data_structs::{ CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix, - CreateCollectionData, + CreateCollectionData, CollectionId, }; use crate::{weights::WeightInfo, Config, SelfWeightOf}; @@ -361,6 +362,25 @@ .expect("Collection creation price should be convertible to u128"); Ok(price.into()) } + + /// Returns address of a collection. + /// @param collectionId - CollectionId of the collection + /// @return eth mirror address of the collection + fn collection_address(&self, collection_id: uint32) -> Result
{ + Ok(collection_id_to_address(collection_id.into())) + } + + /// Returns collectionId of a collection. + /// @param collectionAddress - Eth address of the collection + /// @return collectionId of the collection + fn collection_id(&self, collection_address: address) -> Result { + map_eth_to_id(&collection_address) + .map(|id| id.0) + .ok_or(Error::Revert(format!( + "failed to convert address {} into collectionId.", + collection_address + ))) + } } /// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`] --- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol +++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol @@ -24,7 +24,7 @@ } /// @title Contract, which allows users to operate with collections -/// @dev the ERC-165 identifier for this interface is 0x7dea03b1 +/// @dev the ERC-165 identifier for this interface is 0xe65011aa contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { /// Create an NFT collection /// @param name Name of the collection @@ -130,4 +130,28 @@ dummy; return 0; } + + /// Returns address of a collection. + /// @param collectionId - CollectionId of the collection + /// @return eth mirror address of the collection + /// @dev EVM selector for this function is: 0x2e716683, + /// or in textual repr: collectionAddress(uint32) + function collectionAddress(uint32 collectionId) public view returns (address) { + require(false, stub_error); + collectionId; + dummy; + return 0x0000000000000000000000000000000000000000; + } + + /// Returns collectionId of a collection. + /// @param collectionAddress - Eth address of the collection + /// @return collectionId of the collection + /// @dev EVM selector for this function is: 0xb5cb7498, + /// or in textual repr: collectionId(address) + function collectionId(address collectionAddress) public view returns (uint32) { + require(false, stub_error); + collectionAddress; + dummy; + return 0; + } } --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -86,6 +86,8 @@ use sp_std::{vec, vec::Vec}; use up_data_structs::{ MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, + MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH, + MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE, CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId, SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey, PropertyKeyPermission, @@ -102,7 +104,7 @@ pub mod weights; use weights::WeightInfo; -/// Maximum number of levels of depth in the token nesting tree. +/// A maximum number of levels of depth in the token nesting tree. pub const NESTING_BUDGET: u32 = 5; decl_error! { @@ -138,7 +140,7 @@ pub enum Event where ::AccountId, - ::CrossAccountId, + ::CrossAccountId, { /// Collection sponsor was removed /// @@ -277,6 +279,46 @@ { type Error = Error; + #[doc = "A maximum number of levels of depth in the token nesting tree."] + const NESTING_BUDGET: u32 = NESTING_BUDGET; + + #[doc = "Maximal length of a collection name."] + const MAX_COLLECTION_NAME_LENGTH: u32 = MAX_COLLECTION_NAME_LENGTH; + + #[doc = "Maximal length of a collection description."] + const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = MAX_COLLECTION_DESCRIPTION_LENGTH; + + #[doc = "Maximal length of a token prefix."] + const MAX_TOKEN_PREFIX_LENGTH: u32 = MAX_TOKEN_PREFIX_LENGTH; + + #[doc = "Maximum admins per collection."] + const COLLECTION_ADMINS_LIMIT: u32 = COLLECTION_ADMINS_LIMIT; + + #[doc = "Maximal length of a property key."] + const MAX_PROPERTY_KEY_LENGTH: u32 = MAX_PROPERTY_KEY_LENGTH; + + #[doc = "Maximal length of a property value."] + const MAX_PROPERTY_VALUE_LENGTH: u32 = MAX_PROPERTY_VALUE_LENGTH; + + #[doc = "A maximum number of token properties."] + const MAX_PROPERTIES_PER_ITEM: u32 = MAX_PROPERTIES_PER_ITEM; + + #[doc = "Maximum size for all collection properties."] + const MAX_COLLECTION_PROPERTIES_SIZE: u32 = MAX_COLLECTION_PROPERTIES_SIZE; + + #[doc = "Maximum size of all token properties."] + const MAX_TOKEN_PROPERTIES_SIZE: u32 = MAX_TOKEN_PROPERTIES_SIZE; + + #[doc = "Default NFT collection limit."] + const NFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::NFT); + + #[doc = "Default RFT collection limit."] + const RFT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::ReFungible); + + #[doc = "Default FT collection limit."] + const FT_DEFAULT_COLLECTION_LIMITS: CollectionLimits = CollectionLimits::with_default_limits(CollectionMode::Fungible(0)); + + pub fn deposit_event() = default; fn on_initialize(_now: T::BlockNumber) -> Weight { --- a/primitives/app_promotion_rpc/Cargo.toml +++ b/primitives/app_promotion_rpc/Cargo.toml @@ -14,7 +14,7 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [features] default = ["std"] --- a/primitives/common/Cargo.toml +++ b/primitives/common/Cargo.toml @@ -48,9 +48,9 @@ [dependencies.fp-rpc] default-features = false git = "https://github.com/uniquenetwork/frontier" -branch = "unique-polkadot-v0.9.30" +branch = "unique-polkadot-v0.9.30-2" [dependencies.pallet-evm] default-features = false git = "https://github.com/uniquenetwork/frontier" -branch = "unique-polkadot-v0.9.30" +branch = "unique-polkadot-v0.9.30-2" --- a/primitives/data-structs/CHANGELOG.md +++ b/primitives/data-structs/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. + ## [v0.2.2] 2022-08-16 ### Other changes @@ -28,12 +29,19 @@ multiple users into `RefungibleMultipleItems` call. ## [v0.2.0] - 2022-08-01 + ### Deprecated + - `CreateReFungibleData::const_data` ## [v0.1.2] - 2022-07-25 + ### Added + - Type aliases `CollectionName`, `CollectionDescription`, `CollectionTokenPrefix` + ## [v0.1.1] - 2022-07-22 + ### Added -- Аields with properties to `CreateReFungibleData` and `CreateRefungibleExData`. \ No newline at end of file + +- Fields with properties to `CreateReFungibleData` and `CreateRefungibleExData`. --- a/primitives/data-structs/Cargo.toml +++ b/primitives/data-structs/Cargo.toml @@ -25,9 +25,11 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } derivative = { version = "2.2.0", features = ["use_core"] } struct-versioning = { path = "../../crates/struct-versioning" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } rmrk-traits = { default-features = false, path = "../rmrk-traits" } -bondrewd = { version = "0.1.14", features = ["derive"], default-features = false } +bondrewd = { version = "0.1.14", features = [ + "derive", +], default-features = false } [features] default = ["std"] --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -120,22 +120,22 @@ // TODO: not used. Delete? pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT; -/// Maximum length for collection name. +/// Maximal length of a collection name. pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64; -/// Maximum length for collection description. +/// Maximal length of a collection description. pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256; -/// Maximal token prefix length. +/// Maximal length of a token prefix. pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16; -/// Maximal lenght of property key. +/// Maximal length of a property key. pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256; -/// Maximal lenght of property value. +/// Maximal length of a property value. pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768; -/// Maximum properties that can be assigned to token. +/// A maximum number of token properties. pub const MAX_PROPERTIES_PER_ITEM: u32 = 64; /// Maximal lenght of extended property value. @@ -144,7 +144,7 @@ /// Maximum size for all collection properties. pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960; -/// Maximum size for all token properties. +/// Maximum size of all token properties. pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768; /// How much items can be created per single @@ -609,6 +609,24 @@ } impl CollectionLimits { + pub fn with_default_limits(collection_type: CollectionMode) -> Self { + CollectionLimits { + account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT), + sponsored_data_size: Some(CUSTOM_DATA_LIMIT), + sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled), + token_limit: Some(COLLECTION_TOKEN_LIMIT), + sponsor_transfer_timeout: match collection_type { + CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT), + CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT), + CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT), + }, + sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT), + owner_can_transfer: Some(false), + owner_can_destroy: Some(true), + transfers_enabled: Some(true), + } + } + /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit). pub fn account_token_ownership_limit(&self) -> u32 { self.account_token_ownership_limit @@ -962,12 +980,15 @@ use scale_info::{ Type, Path, build::{FieldsBuilder, UnnamedFields}, + form::MetaForm, type_params, }; Type::builder() .path(Path::new("up_data_structs", "PhantomType")) .type_params(type_params!(T)) - .composite(>::default().field(|b| b.ty::<[T; 0]>())) + .composite( + >::default().field(|b| b.ty::<[T; 0]>()), + ) } } impl MaxEncodedLen for PhantomType { --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -14,7 +14,7 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } [features] default = ["std"] --- a/runtime/common/config/ethereum.rs +++ b/runtime/common/config/ethereum.rs @@ -17,19 +17,15 @@ pub type CrossAccountId = pallet_evm::account::BasicCrossAccountId; -impl pallet_evm::account::Config for Runtime { - type CrossAccountId = CrossAccountId; - type EvmAddressMapping = pallet_evm::HashedAddressMapping; - type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated; -} - // Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case // (contract, which only writes a lot of data), // approximating on top of our real store write weight parameter_types! { pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND.ref_time() / ::DbWeight::get().write; pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000; - pub const WeightPerGas: u64 = WEIGHT_PER_SECOND.ref_time() / GasPerSecond::get(); + pub const WeightTimePerGas: u64 = WEIGHT_PER_SECOND.ref_time() / GasPerSecond::get(); + + pub const WeightPerGas: Weight = Weight::from_ref_time(WeightTimePerGas::get()); } /// Limiting EVM execution to 50% of block for substrate users and management tasks @@ -37,17 +33,7 @@ /// scheduled fairly const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50); parameter_types! { - pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get()).ref_time()); -} - -pub enum FixedGasWeightMapping {} -impl pallet_evm::GasWeightMapping for FixedGasWeightMapping { - fn gas_to_weight(gas: u64) -> Weight { - Weight::from_ref_time(gas).saturating_mul(WeightPerGas::get()) - } - fn weight_to_gas(weight: Weight) -> u64 { - (weight / WeightPerGas::get()).ref_time() - } + pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightTimePerGas::get()).ref_time()); } pub struct EthereumFindAuthor(core::marker::PhantomData); @@ -65,9 +51,13 @@ } impl pallet_evm::Config for Runtime { + type CrossAccountId = CrossAccountId; + type EvmAddressMapping = pallet_evm::HashedAddressMapping; + type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated; type BlockGasLimit = BlockGasLimit; type FeeCalculator = pallet_configuration::FeeCalculator; - type GasWeightMapping = FixedGasWeightMapping; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; type CallOrigin = EnsureAddressTruncated; type WithdrawOrigin = EnsureAddressTruncated; --- a/runtime/common/config/pallets/app_promotion.rs +++ b/runtime/common/config/pallets/app_promotion.rs @@ -22,7 +22,7 @@ use frame_support::{parameter_types, PalletId}; use sp_arithmetic::Perbill; use up_common::{ - constants::{UNIQUE, RELAY_DAYS}, + constants::{UNIQUE, RELAY_DAYS, DAYS}, types::Balance, }; @@ -32,7 +32,6 @@ pub const RecalculationInterval: BlockNumber = 8; pub const PendingInterval: BlockNumber = 4; pub const Nominal: Balance = UNIQUE; - // pub const Day: BlockNumber = DAYS; pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000); } @@ -40,9 +39,8 @@ parameter_types! { pub const AppPromotionId: PalletId = PalletId(*b"appstake"); pub const RecalculationInterval: BlockNumber = RELAY_DAYS; - pub const PendingInterval: BlockNumber = 7 * RELAY_DAYS; + pub const PendingInterval: BlockNumber = 7 * DAYS; pub const Nominal: Balance = UNIQUE; - // pub const Day: BlockNumber = RELAY_DAYS; pub IntervalIncome: Perbill = Perbill::from_rational(5u32, 10_000); } @@ -56,7 +54,6 @@ type RelayBlockNumberProvider = RelayChainBlockNumberProvider; type RecalculationInterval = RecalculationInterval; type PendingInterval = PendingInterval; - // type Day = Day; type Nominal = Nominal; type IntervalIncome = IntervalIncome; type RuntimeEvent = RuntimeEvent; --- a/runtime/common/ethereum/self_contained_call.rs +++ b/runtime/common/ethereum/self_contained_call.rs @@ -69,9 +69,13 @@ fn pre_dispatch_self_contained( &self, info: &Self::SignedInfo, + dispatch_info: &DispatchInfoOf, + len: usize, ) -> Option> { match self { - RuntimeCall::Ethereum(call) => call.pre_dispatch_self_contained(info), + RuntimeCall::Ethereum(call) => { + call.pre_dispatch_self_contained(info, dispatch_info, len) + } _ => None, } } --- a/runtime/common/runtime_apis.rs +++ b/runtime/common/runtime_apis.rs @@ -482,6 +482,7 @@ }; let is_transactional = false; + let validate = false; ::Runner::call( CrossAccountId::from_eth(from), to, @@ -493,6 +494,7 @@ nonce, access_list.unwrap_or_default(), is_transactional, + validate, config.as_ref().unwrap_or_else(|| ::config()), ).map_err(|err| err.error.into()) } @@ -518,6 +520,7 @@ }; let is_transactional = false; + let validate = false; ::Runner::create( CrossAccountId::from_eth(from), data, @@ -528,6 +531,7 @@ nonce, access_list.unwrap_or_default(), is_transactional, + validate, config.as_ref().unwrap_or_else(|| ::config()), ).map_err(|err| err.error.into()) } --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -82,7 +82,6 @@ 'pallet-proxy-rmrk-equip/try-runtime', 'pallet-app-promotion/try-runtime', 'pallet-foreign-assets/try-runtime', - 'pallet-evm/try-runtime', 'pallet-ethereum/try-runtime', 'pallet-evm-coder-substrate/try-runtime', 'pallet-evm-contract-helpers/try-runtime', @@ -174,7 +173,15 @@ 'pallet-test-utils?/std', ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] -opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion', 'foreign-assets', 'pallet-test-utils'] +opal-runtime = [ + 'refungible', + 'scheduler', + 'rmrk', + 'app-promotion', + 'foreign-assets', + 'pallet-test-utils', +] +become-sapphire = [] refungible = [] scheduler = [] @@ -461,7 +468,7 @@ up-rpc = { path = "../../primitives/rpc", default-features = false } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-inflation = { path = '../../pallets/inflation', default-features = false } pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false } up-data-structs = { path = '../../primitives/data-structs', default-features = false } @@ -479,11 +486,11 @@ pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false } pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false } pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' } pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -42,7 +42,14 @@ pub use runtime_common::*; +#[cfg(feature = "become-sapphire")] +pub const RUNTIME_NAME: &str = "sapphire"; +#[cfg(feature = "become-sapphire")] +pub const TOKEN_SYMBOL: &str = "QTZ"; + +#[cfg(not(feature = "become-sapphire"))] pub const RUNTIME_NAME: &str = "opal"; +#[cfg(not(feature = "become-sapphire"))] pub const TOKEN_SYMBOL: &str = "OPL"; /// This runtime version. @@ -59,7 +66,16 @@ parameter_types! { pub const Version: RuntimeVersion = VERSION; - pub const SS58Prefix: u8 = 42; +} +#[cfg(feature = "become-sapphire")] +parameter_types! { + pub const SS58Prefix: u16 = 8883; + pub const ChainId: u64 = 8883; +} + +#[cfg(not(feature = "become-sapphire"))] +parameter_types! { + pub const SS58Prefix: u16 = 42; pub const ChainId: u64 = 8882; } --- a/runtime/quartz/Cargo.toml +++ b/runtime/quartz/Cargo.toml @@ -80,7 +80,6 @@ 'pallet-proxy-rmrk-equip/try-runtime', 'pallet-app-promotion/try-runtime', 'pallet-foreign-assets/try-runtime', - 'pallet-evm/try-runtime', 'pallet-ethereum/try-runtime', 'pallet-evm-coder-substrate/try-runtime', 'pallet-evm-contract-helpers/try-runtime', @@ -460,7 +459,7 @@ pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-inflation = { path = '../../pallets/inflation', default-features = false } pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false } up-data-structs = { path = '../../primitives/data-structs', default-features = false } @@ -478,11 +477,11 @@ pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false } pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false } pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' } pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } --- a/runtime/tests/Cargo.toml +++ b/runtime/tests/Cargo.toml @@ -16,7 +16,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } @@ -25,8 +25,8 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } pallet-common = { path = '../../pallets/common' } pallet-structure = { path = '../../pallets/structure' } --- a/runtime/tests/src/lib.rs +++ b/runtime/tests/src/lib.rs @@ -21,6 +21,7 @@ parameter_types, traits::{Everything, ConstU32, ConstU64}, weights::IdentityFee, + pallet_prelude::Weight, }; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, @@ -202,6 +203,7 @@ parameter_types! { pub BlockGasLimit: U256 = 0u32.into(); + pub WeightPerGas: Weight = Weight::from_ref_time(20); } impl pallet_ethereum::Config for Test { @@ -210,11 +212,15 @@ } impl pallet_evm::Config for Test { + type CrossAccountId = TestCrossAccountId; + type EvmAddressMapping = TestEvmAddressMapping; + type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping; type RuntimeEvent = RuntimeEvent; type FeeCalculator = (); - type GasWeightMapping = (); - type CallOrigin = EnsureAddressNever; - type WithdrawOrigin = EnsureAddressNever; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + type CallOrigin = EnsureAddressNever; + type WithdrawOrigin = EnsureAddressNever; type AddressMapping = TestEvmAddressMapping; type Currency = Balances; type PrecompilesType = (); @@ -242,12 +248,6 @@ type EvmTokenAddressMapping = EvmTokenAddressMapping; type CrossTokenAddressMapping = CrossTokenAddressMapping; type ContractAddress = EvmCollectionHelpersAddress; -} - -impl pallet_evm::account::Config for Test { - type CrossAccountId = TestCrossAccountId; - type EvmAddressMapping = TestEvmAddressMapping; - type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping; } impl pallet_structure::Config for Test { --- a/runtime/unique/Cargo.toml +++ b/runtime/unique/Cargo.toml @@ -81,7 +81,6 @@ 'pallet-proxy-rmrk-equip/try-runtime', 'pallet-app-promotion/try-runtime', 'pallet-foreign-assets/try-runtime', - 'pallet-evm/try-runtime', 'pallet-ethereum/try-runtime', 'pallet-evm-coder-substrate/try-runtime', 'pallet-evm-contract-helpers/try-runtime', @@ -472,12 +471,12 @@ pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false } pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false } pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" } -pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } -fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } +fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" } evm-coder = { default-features = false, path = '../../crates/evm-coder' } up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' } pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" } --- a/tests/package.json +++ b/tests/package.json @@ -102,6 +102,7 @@ "testXcmTransferStatemine": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferStatemine.test.ts statemineId=1000 uniqueId=5000", "testXcmTransferMoonbeam": "mocha --timeout 9999999 -r ts-node/register ./**/xcm/xcmTransferMoonbeam.test.ts", "benchMintingFee": "ts-node src/benchmarks/mintFee/benchmark.ts", + "testApiConsts": "mocha --timeout 9999999 -r ts-node/register ./**/apiConsts.test.ts", "load": "mocha --timeout 9999999 -r ts-node/register './**/*.load.ts'", "loadTransfer": "ts-node src/transfer.nload.ts", "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json", --- /dev/null +++ b/tests/scripts/functions.sh @@ -0,0 +1,4 @@ + +function do_rpc { + curl -s --header "Content-Type: application/json" -XPOST --data "{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"$1\",\"params\":[$2]}" $RPC_URL +} --- /dev/null +++ b/tests/scripts/generate_types_package.sh @@ -0,0 +1,214 @@ +#!/usr/bin/env bash + +set -eu + +DIR=$(realpath $(dirname "$0")) +TEMPLATE=$DIR/types_template +GIT_REPO=git@github.com:UniqueNetwork/unique-types-js.git + +. $DIR/functions.sh + +usage() { + echo "Usage: [RPC_URL=http://localhost:9933] $0 <--rc|--release|--sapphire> [--force] [--push] [--rpc-url=http://localhost:9933]" 1>&2 + exit 1 +} + +rc= +sapphire= +release= +force= +push= + +for i in "$@"; do +case $i in + --rc) + rc=1 + if test "$release" -o "$sapphire"; then usage; fi + ;; + --sapphire) + sapphire=1 + if test "$rc" -o "$release"; then usage; fi + ;; + --release) + release=1 + if test "$rc" -o "$sapphire"; then usage; fi + ;; + --force) + force=1 + ;; + --push) + push=1 + ;; + --rpc-url=*) + RPC_URL=${i#*=} + ;; + *) + usage + ;; +esac +done + +if test \( ! \( "$rc" -o "$release" -o "$sapphire" \) \) -o \( "${RPC_URL=}" = "" \); then + usage +elif test "$rc"; then + echo "Rc build" +else + echo "Release build" +fi + +cd $DIR/.. +yarn polkadot-types + +version=$(do_rpc state_getRuntimeVersion "") +spec_version=$(echo $version | jq -r .result.specVersion) +spec_name=$(echo $version | jq -r .result.specName) +echo "Spec version: $spec_version, name: $spec_name" + +case $spec_name in + opal) + package_name=@unique-nft/opal-testnet-types + repo_branch=opal-testnet + repo_tag=$repo_branch + ;; + quartz) + package_name=@unique-nft/quartz-mainnet-types + repo_branch=quartz-mainnet + repo_tag=$repo_branch + ;; + unique) + package_name=@unique-nft/unique-mainnet-types + repo_branch=master + repo_tag=unique-mainnet + ;; + *) + echo "unknown spec name: $spec_name" + exit 1 + ;; +esac + +if test "$rc" = 1; then + if "$spec_name" != opal; then + echo "rc types can only be based on opal spec" + exit 1 + fi + package_name=@unique-nft/rc-types + repo_branch=rc + repo_tag=$repo_branch +fi +if test "$sapphire" = 1; then + if "$spec_name" != opal; then + echo "sapphire types can only be based on opal spec" + exit 1 + fi + package_name=@unique-nft/sapphire-mainnet-types + repo_branch=sapphire-mainnet + repo_tag=$repo_branch +fi + +package_version=${spec_version:0:3}.$(echo ${spec_version:3:3} | sed 's/^0*//'). +last_patch=NEVER +for tag in $(git ls-remote -t --refs $GIT_REPO | cut -f 2 | sort -r); do + tag_prefix=refs/tags/$repo_tag-v$package_version + if [[ $tag == $tag_prefix* ]]; then + last_patch=${tag#$tag_prefix} + break; + fi +done +echo "Package version: ${package_version}X, name: $package_name" +echo "Last published: $package_version$last_patch" + +if test "$last_patch" = "NEVER"; then + new_package_version=${package_version}0 +else + new_package_version=${package_version}$((last_patch+1)) +fi +package_version=${package_version}$last_patch +echo "New package version: $new_package_version" + +pjsapi_ver=^$(cat $DIR/../package.json | jq -r '.dependencies."@polkadot/api"' | sed -e "s/^\^//") +tsnode_ver=^$(cat $DIR/../package.json | jq -r '.devDependencies."ts-node"' | sed -e "s/^\^//") +ts_ver=^$(cat $DIR/../package.json | jq -r '.devDependencies."typescript"' | sed -e "s/^\^//") + +gen=$(mktemp -d) +pushd $gen +git clone $GIT_REPO -b $repo_branch --depth 1 . +if test "$last_patch" != "NEVER"; then + git reset --hard $repo_tag-v$package_version +fi +git rm -r "*" +popd + +# Using old package_version here, becaue we first check if +# there is any difference between generated and already uplaoded types +cat $TEMPLATE/package.json \ +| jq '.private = false' - \ +| jq '.name = "'$package_name'"' - \ +| jq '.version = "'$package_version'"' - \ +| jq '.peerDependencies."@polkadot/api" = "'$pjsapi_ver'"' - \ +| jq '.peerDependencies."@polkadot/types" = "'$pjsapi_ver'"' - \ +| jq '.devDependencies."@polkadot/api" = "'$pjsapi_ver'"' - \ +| jq '.devDependencies."@polkadot/types" = "'$pjsapi_ver'"' - \ +| jq '.devDependencies."ts-node" = "'$tsnode_ver'"' - \ +| jq '.devDependencies."typescript" = "'$ts_ver'"' - \ +> $gen/package.json +for file in .gitignore .npmignore README.md tsconfig.json; do + cp $TEMPLATE/$file $gen/ +done +package_name_replacement=$(printf '%s\n' "$package_name" | sed -e 's/[\/&]/\\&/g') +sed -i 's/PKGNAME/'$package_name_replacement'/' $gen/README.md + +rsync -ar --exclude .gitignore src/interfaces/ $gen +for file in $gen/augment-* $gen/**/types.ts $gen/registry.ts; do + sed -i '1s;^;//@ts-nocheck\n;' $file +done + +pushd $gen +git add . +popd + +pushd $gen +if git diff --quiet HEAD && test ! "$force"; then + echo "no changes detected" + exit 0 +fi +popd + +mv $gen/package.json $gen/package.old.json +cat $gen/package.old.json \ +| jq '.version = "'$new_package_version'"' - \ +> $gen/package.json +rm $gen/package.old.json +pushd $gen +git add package.json +popd + +echo "package.json contents:" +cat $gen/package.json +echo "overall diff:" +pushd $gen +git status +git diff HEAD || true +popd + +# This check is only active if running in interactive terminal +if [ -t 0 ]; then + read -p "Is everything ok at $gen [y/n]? " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Aborting!" + exit 1 + fi +fi + +pushd $gen +yarn +yarn prepublish +git commit -m "chore: upgrade types to v$new_package_version" +git tag --force $repo_tag-v$new_package_version +if test "$push" = 1; then + git push --tags --force -u origin HEAD +else + echo "--push not given, origin repo left intact" + echo "To publish manually, go to $gen, and run \"git push --tags --force -u origin HEAD\"" +fi +popd --- /dev/null +++ b/tests/scripts/types_template/.gitignore @@ -0,0 +1,5 @@ +*.js +*.map +*.d.ts +/node_modules +metadata.json --- /dev/null +++ b/tests/scripts/types_template/.npmignore @@ -0,0 +1 @@ +/src --- /dev/null +++ b/tests/scripts/types_template/README.md @@ -0,0 +1,31 @@ +# PKGNAME + +Unique network api types + +Do not edit by hand, those types are generated automatically, and definitions are located in chain repo + +## Using types + +Install library: + +```bash +yarn add --dev PKGNAME +``` + +Replace polkadot.js types with our chain types adding corresponding path override to the tsconfig `compilerOptions.paths` section: + +```json +// in tsconfig.json +{ + "compilerOptions": { + "paths": { + "@polkadot/types/lookup": ["node_modules/PKGNAME/types-lookup"] + } + } +} +``` + +Since polkadot v7 api augmentations not loaded by default, in every file, where you need to access `api.tx`, `api.query`, `api.rpc`, etc; you should explicitly import corresponding augmentation before any other `polkadot.js` related import: +``` +import 'PKGNAME/augment-api'; +``` --- /dev/null +++ b/tests/scripts/types_template/package.json @@ -0,0 +1,22 @@ +{ + "name": "TODO", + "private": true, + "version": "TODO", + "main": "index.js", + "repository": "git@github.com:UniqueNetwork/unique-types-js.git", + "homepage": "https://unique.network/", + "license": "MIT", + "scripts": { + "prepublish": "tsc -d" + }, + "peerDependencies": { + "@polkadot/api": "TODO", + "@polkadot/types": "TODO" + }, + "devDependencies": { + "@polkadot/api": "TODO", + "@polkadot/types": "TODO", + "ts-node": "TODO", + "typescript": "TODO" + } +} --- /dev/null +++ b/tests/scripts/types_template/tsconfig.json @@ -0,0 +1,28 @@ +{ + "exclude": [ + "node_modules", + "node_modules/**/*", + "../node_modules/**/*", + "**/node_modules/**/*" + ], + "compilerOptions": { + "target": "ES2020", + "moduleResolution": "node", + "esModuleInterop": true, + "resolveJsonModule": true, + "module": "commonjs", + "sourceMap": true, + "outDir": ".", + "rootDir": ".", + "strict": true, + "paths": { + }, + "skipLibCheck": true, + }, + "include": [ + "**/*", + ], + "lib": [ + "es2017" + ], +} --- a/tests/scripts/wait_for_first_block.sh +++ b/tests/scripts/wait_for_first_block.sh @@ -1,15 +1,11 @@ #!/usr/bin/env bash -function do_rpc { - curl -s --header "Content-Type: application/json" -XPOST --data "{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"$1\",\"params\":[$2]}" $RPC_URL -} +DIR=$(dirname "$0") + +. $DIR/functions.sh function is_started { - block_hash_rpc=$(do_rpc chain_getFinalizedHead) - echo Rpc response = $block_hash_rpc - block_hash=$(echo $block_hash_rpc | jq -r .result) - echo Head = $block_hash - block_id_hex=$(do_rpc chain_getHeader "\"$block_hash\"" | jq -r .result.number) + block_id_hex=$(do_rpc chain_getHeader | jq -r .result.number) block_id=$((${block_id_hex})) echo Id = $block_id if (( $block_id > 1 )); then --- /dev/null +++ b/tests/src/apiConsts.test.ts @@ -0,0 +1,120 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {ApiPromise} from '@polkadot/api'; +import {ApiBase} from '@polkadot/api/base'; +import {usingPlaygrounds, itSub, expect} from './util'; + + +const MAX_COLLECTION_DESCRIPTION_LENGTH = 256n; +const MAX_COLLECTION_NAME_LENGTH = 64n; +const COLLECTION_ADMINS_LIMIT = 5n; +const MAX_COLLECTION_PROPERTIES_SIZE = 40960n; +const MAX_TOKEN_PREFIX_LENGTH = 16n; +const MAX_PROPERTY_KEY_LENGTH = 256n; +const MAX_PROPERTY_VALUE_LENGTH = 32768n; +const MAX_PROPERTIES_PER_ITEM = 64n; +const MAX_TOKEN_PROPERTIES_SIZE = 32768n; +const NESTING_BUDGET = 5n; + +const DEFAULT_COLLETCTION_LIMIT = { + accountTokenOwnershipLimit: '1,000,000', + sponsoredDataSize: '2,048', + sponsoredDataRateLimit: 'SponsoringDisabled', + tokenLimit: '4,294,967,295', + sponsorTransferTimeout: '5', + sponsorApproveTimeout: '5', + ownerCanTransfer: false, + ownerCanDestroy: true, + transfersEnabled: true, +}; + +const EVM_COLLECTION_HELPERS_ADDRESS = '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f'; +const HELPERS_CONTRACT_ADDRESS = '0x842899ECF380553E8a4de75bF534cdf6fBF64049'; + +describe('integration test: API UNIQUE consts', () => { + let api: ApiPromise; + + before(async () => { + await usingPlaygrounds(async (helper) => { + api = await helper.getApi(); + }); + }); + + itSub('DEFAULT_NFT_COLLECTION_LIMITS', () => { + expect(api.consts.unique.nftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); + }); + + itSub('DEFAULT_RFT_COLLECTION_LIMITS', () => { + expect(api.consts.unique.rftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); + }); + + itSub('DEFAULT_FT_COLLECTION_LIMITS', () => { + expect(api.consts.unique.ftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); + }); + + itSub('MAX_COLLECTION_NAME_LENGTH', () => { + checkConst(api.consts.unique.maxCollectionNameLength, MAX_COLLECTION_NAME_LENGTH); + }); + + itSub('MAX_COLLECTION_DESCRIPTION_LENGTH', () => { + checkConst(api.consts.unique.maxCollectionDescriptionLength, MAX_COLLECTION_DESCRIPTION_LENGTH); + }); + + itSub('MAX_COLLECTION_PROPERTIES_SIZE', () => { + checkConst(api.consts.unique.maxCollectionPropertiesSize, MAX_COLLECTION_PROPERTIES_SIZE); + }); + + itSub('MAX_TOKEN_PREFIX_LENGTH', () => { + checkConst(api.consts.unique.maxTokenPrefixLength, MAX_TOKEN_PREFIX_LENGTH); + }); + + itSub('MAX_PROPERTY_KEY_LENGTH', () => { + checkConst(api.consts.unique.maxPropertyKeyLength, MAX_PROPERTY_KEY_LENGTH); + }); + + itSub('MAX_PROPERTY_VALUE_LENGTH', () => { + checkConst(api.consts.unique.maxPropertyValueLength, MAX_PROPERTY_VALUE_LENGTH); + }); + + itSub('MAX_PROPERTIES_PER_ITEM', () => { + checkConst(api.consts.unique.maxPropertiesPerItem, MAX_PROPERTIES_PER_ITEM); + }); + + itSub('NESTING_BUDGET', () => { + checkConst(api.consts.unique.nestingBudget, NESTING_BUDGET); + }); + + itSub('MAX_TOKEN_PROPERTIES_SIZE', () => { + checkConst(api.consts.unique.maxTokenPropertiesSize, MAX_TOKEN_PROPERTIES_SIZE); + }); + + itSub('COLLECTION_ADMINS_LIMIT', () => { + checkConst(api.consts.unique.collectionAdminsLimit, COLLECTION_ADMINS_LIMIT); + }); + + itSub('HELPERS_CONTRACT_ADDRESS', () => { + expect(api.consts.evmContractHelpers.contractAddress.toString().toLowerCase()).to.be.equal(HELPERS_CONTRACT_ADDRESS.toLowerCase()); + }); + + itSub('EVM_COLLECTION_HELPERS_ADDRESS', () => { + expect(api.consts.common.contractAddress.toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS.toLowerCase()); + }); +}); + +function checkConst(constValue: any, expectedValue: T) { + expect(constValue.toBigInt()).equal(expectedValue); +} \ No newline at end of file --- a/tests/src/burnItem.test.ts +++ b/tests/src/burnItem.test.ts @@ -140,6 +140,31 @@ await expect(token.burn(bob)).to.be.rejectedWith('common.NoPermission'); }); + itSub.ifWithPallets('RFT: cannot burn non-owned token pieces', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice); + const aliceToken = await collection.mintToken(alice, 10n, {Substrate: alice.address}); + const bobToken = await collection.mintToken(alice, 10n, {Substrate: bob.address}); + + // 1. Cannot burn non-owned token: + await expect(bobToken.burn(alice, 0n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(bobToken.burn(alice, 5n)).to.be.rejectedWith('common.TokenValueTooLow'); + // 2. Cannot burn non-existing token: + await expect(helper.rft.burnToken(alice, 99999, 10)).to.be.rejectedWith('common.CollectionNotFound'); + await expect(helper.rft.burnToken(alice, collection.collectionId, 99999)).to.be.rejectedWith('common.TokenValueTooLow'); + // 3. Can burn zero amount of owned tokens (EIP-20) + await aliceToken.burn(alice, 0n); + + // 4. Storage is not corrupted: + expect(await aliceToken.getTop10Owners()).to.deep.eq([{Substrate: alice.address}]); + expect(await bobToken.getTop10Owners()).to.deep.eq([{Substrate: bob.address}]); + + // 4.1 Tokens can be transfered: + await aliceToken.transfer(alice, {Substrate: bob.address}, 10n); + await bobToken.transfer(bob, {Substrate: alice.address}, 10n); + expect(await aliceToken.getTop10Owners()).to.deep.eq([{Substrate: bob.address}]); + expect(await bobToken.getTop10Owners()).to.deep.eq([{Substrate: alice.address}]); + }); + itSub('Transfer a burned token', async ({helper}) => { const collection = await helper.nft.mintCollection(alice); const token = await collection.mintToken(alice); @@ -155,4 +180,48 @@ await expect(collection.burnTokens(alice, 11n)).to.be.rejectedWith('common.TokenValueTooLow'); expect(await collection.getBalance({Substrate: alice.address})).to.eq(10n); }); + + itSub('Zero burn NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Coll', description: 'Desc', tokenPrefix: 'T'}); + const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address}); + const tokenBob = await collection.mintToken(alice, {Substrate: bob.address}); + + // 1. Zero burn of own tokens allowed: + await helper.executeExtrinsic(alice, 'api.tx.unique.burnItem', [collection.collectionId, tokenAlice.tokenId, 0]); + // 2. Zero burn of non-owned tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.burnItem', [collection.collectionId, tokenBob.tokenId, 0])).to.be.rejectedWith('common.NoPermission'); + // 3. Zero burn of non-existing tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.burnItem', [collection.collectionId, 9999, 0])).to.be.rejectedWith('common.TokenNotFound'); + expect(await tokenAlice.doesExist()).to.be.true; + expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: alice.address}); + expect(await tokenBob.getOwner()).to.deep.eq({Substrate: bob.address}); + // 4. Storage is not corrupted: + await tokenAlice.transfer(alice, {Substrate: bob.address}); + await tokenBob.transfer(bob, {Substrate: alice.address}); + expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: bob.address}); + expect(await tokenBob.getOwner()).to.deep.eq({Substrate: alice.address}); + }); + + itSub('zero burnFrom NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Zero', description: 'Zero transfer', tokenPrefix: 'TF'}); + const notApprovedNft = await collection.mintToken(alice, {Substrate: bob.address}); + const approvedNft = await collection.mintToken(alice, {Substrate: bob.address}); + await approvedNft.approve(bob, {Substrate: alice.address}); + + // 1. Zero burnFrom of non-existing tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.burnFrom', [collection.collectionId, {Substrate: bob.address}, 9999, 0])).to.be.rejectedWith('common.ApprovedValueTooLow'); + // 2. Zero burnFrom of not approved tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.burnFrom', [collection.collectionId, {Substrate: bob.address}, notApprovedNft.tokenId, 0])).to.be.rejectedWith('common.ApprovedValueTooLow'); + // 3. Zero burnFrom of approved tokens allowed: + await helper.executeExtrinsic(alice, 'api.tx.unique.burnFrom', [collection.collectionId, {Substrate: bob.address}, approvedNft.tokenId, 0]); + + // 4.1 approvedNft still approved: + expect(await approvedNft.isApproved({Substrate: alice.address})).to.be.true; + // 4.2 bob is still the owner: + expect(await approvedNft.getOwner()).to.deep.eq({Substrate: bob.address}); + expect(await notApprovedNft.getOwner()).to.deep.eq({Substrate: bob.address}); + // 4.3 Alice can burn approved nft: + await approvedNft.burnFrom(alice, {Substrate: bob.address}); + expect(await approvedNft.doesExist()).to.be.false; + }); }); --- a/tests/src/eth/abi/collectionHelpers.json +++ b/tests/src/eth/abi/collectionHelpers.json @@ -32,6 +32,15 @@ "type": "event" }, { + "inputs": [ + { "internalType": "uint32", "name": "collectionId", "type": "uint32" } + ], + "name": "collectionAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "collectionCreationFee", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], @@ -40,6 +49,19 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "collectionAddress", + "type": "address" + } + ], + "name": "collectionId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "uint8", "name": "decimals", "type": "uint8" }, { "internalType": "string", "name": "description", "type": "string" }, --- a/tests/src/eth/abi/fungible.json +++ b/tests/src/eth/abi/fungible.json @@ -95,9 +95,17 @@ }, { "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } + { + "components": [ + { "internalType": "address", "name": "eth", "type": "address" }, + { "internalType": "uint256", "name": "sub", "type": "uint256" } + ], + "internalType": "struct EthCrossAccount", + "name": "user", + "type": "tuple" + } ], - "name": "allowed", + "name": "allowlistedCross", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" @@ -193,6 +201,13 @@ }, { "inputs": [], + "name": "collectionHelperAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], "name": "collectionOwner", "outputs": [ { --- a/tests/src/eth/abi/nonFungible.json +++ b/tests/src/eth/abi/nonFungible.json @@ -116,9 +116,17 @@ }, { "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } + { + "components": [ + { "internalType": "address", "name": "eth", "type": "address" }, + { "internalType": "uint256", "name": "sub", "type": "uint256" } + ], + "internalType": "struct EthCrossAccount", + "name": "user", + "type": "tuple" + } ], - "name": "allowed", + "name": "allowlistedCross", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" @@ -223,6 +231,13 @@ }, { "inputs": [], + "name": "collectionHelperAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], "name": "collectionOwner", "outputs": [ { @@ -440,6 +455,26 @@ { "inputs": [ { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "string[]", "name": "keys", "type": "string[]" } + ], + "name": "properties", + "outputs": [ + { + "components": [ + { "internalType": "string", "name": "key", "type": "string" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct Property[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, { "internalType": "string", "name": "key", "type": "string" } ], "name": "property", @@ -662,26 +697,6 @@ ], "name": "tokenOfOwnerByIndex", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { "internalType": "string[]", "name": "keys", "type": "string[]" } - ], - "name": "tokenProperties", - "outputs": [ - { - "components": [ - { "internalType": "string", "name": "key", "type": "string" }, - { "internalType": "bytes", "name": "value", "type": "bytes" } - ], - "internalType": "struct Property[]", - "name": "", - "type": "tuple[]" - } - ], "stateMutability": "view", "type": "function" }, --- a/tests/src/eth/abi/reFungible.json +++ b/tests/src/eth/abi/reFungible.json @@ -116,9 +116,17 @@ }, { "inputs": [ - { "internalType": "address", "name": "user", "type": "address" } + { + "components": [ + { "internalType": "address", "name": "eth", "type": "address" }, + { "internalType": "uint256", "name": "sub", "type": "uint256" } + ], + "internalType": "struct EthCrossAccount", + "name": "user", + "type": "tuple" + } ], - "name": "allowed", + "name": "allowlistedCross", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" @@ -205,6 +213,13 @@ }, { "inputs": [], + "name": "collectionHelperAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], "name": "collectionOwner", "outputs": [ { @@ -422,6 +437,26 @@ { "inputs": [ { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "string[]", "name": "keys", "type": "string[]" } + ], + "name": "properties", + "outputs": [ + { + "components": [ + { "internalType": "string", "name": "key", "type": "string" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct Property[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, { "internalType": "string", "name": "key", "type": "string" } ], "name": "property", @@ -653,26 +688,6 @@ ], "name": "tokenOfOwnerByIndex", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { "internalType": "string[]", "name": "keys", "type": "string[]" } - ], - "name": "tokenProperties", - "outputs": [ - { - "components": [ - { "internalType": "string", "name": "key", "type": "string" }, - { "internalType": "bytes", "name": "value", "type": "bytes" } - ], - "internalType": "struct Property[]", - "name": "", - "type": "tuple[]" - } - ], "stateMutability": "view", "type": "function" }, --- a/tests/src/eth/allowlist.test.ts +++ b/tests/src/eth/allowlist.test.ts @@ -78,32 +78,61 @@ itEth('Collection allowlist can be added and removed by [eth] address', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const user = helper.eth.createAccount(); - + const crossUser = helper.ethCrossAccount.fromAddress(user); + const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.false; await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner}); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.true; await collectionEvm.methods.removeFromCollectionAllowList(user).send({from: owner}); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.false; }); itEth('Collection allowlist can be added and removed by [cross] address', async ({helper}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - const user = donor; + const owner = (await helper.eth.createAccountWithBalance(donor)).toLowerCase(); + const [userSub] = await helper.arrange.createAccounts([10n], donor); + const userEth = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - const userCross = helper.ethCrossAccount.fromKeyringPair(user); + const userCrossSub = helper.ethCrossAccount.fromKeyringPair(userSub); + const userCrossEth = helper.ethCrossAccount.fromAddress(userEth); + const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner); + + // Can addToCollectionAllowListCross: + expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.false; + await collectionEvm.methods.addToCollectionAllowListCross(userCrossSub).send({from: owner}); + await collectionEvm.methods.addToCollectionAllowListCross(userCrossEth).send({from: owner}); + await collectionEvm.methods.addToCollectionAllowListCross(ownerCrossEth).send({from: owner}); + expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.true; + expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.true; + expect(await collectionEvm.methods.allowlistedCross(userCrossSub).call({from: owner})).to.be.true; + expect(await collectionEvm.methods.allowlistedCross(userCrossEth).call({from: owner})).to.be.true; + + await collectionEvm.methods.mint(userEth).send(); // token #1 + await collectionEvm.methods.mint(userEth).send(); // token #2 + await collectionEvm.methods.setCollectionAccess(1).send(); - expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false; - await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner}); - expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true; + // allowlisted account can transfer and transferCross: + await collectionEvm.methods.transfer(owner, 1).send({from: userEth}); + await collectionEvm.methods.transferCross(userCrossSub, 2).send({from: userEth}); + expect(await helper.nft.getTokenOwner(collectionId, 1)).to.deep.eq({Ethereum: owner}); + expect(await helper.nft.getTokenOwner(collectionId, 2)).to.deep.eq({Substrate: userSub.address}); - await collectionEvm.methods.removeFromCollectionAllowListCross(userCross).send({from: owner}); - expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false; + // can removeFromCollectionAllowListCross: + await collectionEvm.methods.removeFromCollectionAllowListCross(userCrossSub).send({from: owner}); + await collectionEvm.methods.removeFromCollectionAllowListCross(userCrossEth).send({from: owner}); + expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.false; + expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(userCrossSub).call({from: owner})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(userCrossEth).call({from: owner})).to.be.false; + + // cannot transfer anymore + await collectionEvm.methods.mint(userEth).send(); + await expect(collectionEvm.methods.transfer(owner, 2).send({from: userEth})).to.be.rejectedWith(/Transaction has been reverted/); }); // Soft-deprecated @@ -111,17 +140,18 @@ const owner = await helper.eth.createAccountWithBalance(donor); const notOwner = await helper.eth.createAccountWithBalance(donor); const user = helper.eth.createAccount(); + const crossUser = helper.ethCrossAccount.fromAddress(user); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.false; await expect(collectionEvm.methods.addToCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission'); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.false; await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner}); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.true; await expect(collectionEvm.methods.removeFromCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission'); - expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true; + expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.true; }); itEth('Collection allowlist can not be add and remove [cross] address by not owner', async ({helper}) => { --- a/tests/src/eth/api/CollectionHelpers.sol +++ b/tests/src/eth/api/CollectionHelpers.sol @@ -19,7 +19,7 @@ } /// @title Contract, which allows users to operate with collections -/// @dev the ERC-165 identifier for this interface is 0x7dea03b1 +/// @dev the ERC-165 identifier for this interface is 0xe65011aa interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { /// Create an NFT collection /// @param name Name of the collection @@ -78,4 +78,18 @@ /// @dev EVM selector for this function is: 0xd23a7ab1, /// or in textual repr: collectionCreationFee() function collectionCreationFee() external view returns (uint256); + + /// Returns address of a collection. + /// @param collectionId - CollectionId of the collection + /// @return eth mirror address of the collection + /// @dev EVM selector for this function is: 0x2e716683, + /// or in textual repr: collectionAddress(uint32) + function collectionAddress(uint32 collectionId) external view returns (address); + + /// Returns collectionId of a collection. + /// @param collectionAddress - Eth address of the collection + /// @return collectionId of the collection + /// @dev EVM selector for this function is: 0xb5cb7498, + /// or in textual repr: collectionId(address) + function collectionId(address collectionAddress) external view returns (uint32); } --- a/tests/src/eth/api/UniqueFungible.sol +++ b/tests/src/eth/api/UniqueFungible.sol @@ -13,7 +13,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca interface Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -177,9 +177,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) external view returns (bool); + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) external view returns (bool); // /// Add the user to the allowed list. // /// @@ -354,7 +354,7 @@ event Approval(address indexed owner, address indexed spender, uint256 value); } -/// @dev the ERC-165 identifier for this interface is 0x942e8b22 +/// @dev the ERC-165 identifier for this interface is 0x8cb847c4 interface ERC20 is Dummy, ERC165, ERC20Events { /// @dev EVM selector for this function is: 0x06fdde03, /// or in textual repr: name() @@ -395,6 +395,11 @@ /// @dev EVM selector for this function is: 0xdd62ed3e, /// or in textual repr: allowance(address,address) function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() external view returns (address); } interface UniqueFungible is Dummy, ERC165, ERC20, ERC20Mintable, ERC20UniqueExtensions, Collection {} --- a/tests/src/eth/api/UniqueNFT.sol +++ b/tests/src/eth/api/UniqueNFT.sol @@ -80,7 +80,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca interface Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -244,9 +244,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) external view returns (bool); + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) external view returns (bool); // /// Add the user to the allowed list. // /// @@ -446,7 +446,7 @@ } /// @title Unique extensions for ERC721. -/// @dev the ERC-165 identifier for this interface is 0xb8f094a0 +/// @dev the ERC-165 identifier for this interface is 0xb74c26b7 interface ERC721UniqueExtensions is Dummy, ERC165 { /// @notice A descriptive name for a collection of NFTs in this contract /// @dev EVM selector for this function is: 0x06fdde03, @@ -475,9 +475,9 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - /// @dev EVM selector for this function is: 0xefc26c69, - /// or in textual repr: tokenProperties(uint256,string[]) - function tokenProperties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory); + /// @dev EVM selector for this function is: 0xe07ede7e, + /// or in textual repr: properties(uint256,string[]) + function properties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory); /// @notice Set or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. @@ -605,7 +605,7 @@ /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// @dev the ERC-165 identifier for this interface is 0x80ac58cd +/// @dev the ERC-165 identifier for this interface is 0x983a942b interface ERC721 is Dummy, ERC165, ERC721Events { /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this @@ -685,6 +685,11 @@ /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) external view returns (address); + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() external view returns (address); } interface UniqueNFT is --- a/tests/src/eth/api/UniqueRefungible.sol +++ b/tests/src/eth/api/UniqueRefungible.sol @@ -80,7 +80,7 @@ } /// @title A contract that allows you to work with collections. -/// @dev the ERC-165 identifier for this interface is 0x8b91d192 +/// @dev the ERC-165 identifier for this interface is 0xcc1d80ca interface Collection is Dummy, ERC165 { // /// Set collection property. // /// @@ -244,9 +244,9 @@ /// Checks that user allowed to operate with collection. /// /// @param user User address to check. - /// @dev EVM selector for this function is: 0xd63a8e11, - /// or in textual repr: allowed(address) - function allowed(address user) external view returns (bool); + /// @dev EVM selector for this function is: 0x91b6df49, + /// or in textual repr: allowlistedCross((address,uint256)) + function allowlistedCross(EthCrossAccount memory user) external view returns (bool); // /// Add the user to the allowed list. // /// @@ -444,7 +444,7 @@ } /// @title Unique extensions for ERC721. -/// @dev the ERC-165 identifier for this interface is 0x1d4b64d6 +/// @dev the ERC-165 identifier for this interface is 0x12f7d6c1 interface ERC721UniqueExtensions is Dummy, ERC165 { /// @notice A descriptive name for a collection of NFTs in this contract /// @dev EVM selector for this function is: 0x06fdde03, @@ -473,9 +473,9 @@ /// @param tokenId Id for the token. /// @param keys Properties keys. Empty keys for all propertyes. /// @return Vector of properties key/value pairs. - /// @dev EVM selector for this function is: 0xefc26c69, - /// or in textual repr: tokenProperties(uint256,string[]) - function tokenProperties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory); + /// @dev EVM selector for this function is: 0xe07ede7e, + /// or in textual repr: properties(uint256,string[]) + function properties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory); /// @notice Transfer ownership of an RFT /// @dev Throws unless `msg.sender` is the current owner. Throws if `to` @@ -604,7 +604,7 @@ /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// @dev the ERC-165 identifier for this interface is 0x58800161 +/// @dev the ERC-165 identifier for this interface is 0x4016cd87 interface ERC721 is Dummy, ERC165, ERC721Events { /// @notice Count all RFTs assigned to an owner /// @dev RFTs assigned to the zero address are considered invalid, and this @@ -682,6 +682,11 @@ /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) external view returns (address); + + /// @notice Returns collection helper contract address + /// @dev EVM selector for this function is: 0x1896cce6, + /// or in textual repr: collectionHelperAddress() + function collectionHelperAddress() external view returns (address); } interface UniqueRefungible is --- a/tests/src/eth/base.test.ts +++ b/tests/src/eth/base.test.ts @@ -117,7 +117,7 @@ }); itEth('ERC721UniqueExtensions support', async ({helper}) => { - await checkInterface(helper, '0xb8f094a0', true, true); + await checkInterface(helper, '0xb74c26b7', true, true); }); itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => { --- a/tests/src/eth/collectionAdmin.test.ts +++ b/tests/src/eth/collectionAdmin.test.ts @@ -39,80 +39,98 @@ }); }); - // Soft-deprecated - itEth('Add admin by owner', async ({helper}) => { + itEth('can add account admin by owner', async ({helper, privateKey}) => { + // arrange const owner = await helper.eth.createAccountWithBalance(donor); + const adminSub = await privateKey('//admin2'); + const adminEth = helper.eth.createAccount().toLowerCase(); + + const adminDeprecated = helper.eth.createAccount().toLowerCase(); + const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); + const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); + const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - const newAdmin = helper.eth.createAccount(); + // Soft-deprecated: can addCollectionAdmin + await collectionEvm.methods.addCollectionAdmin(adminDeprecated).send(); + // Can addCollectionAdminCross for substrate and ethereum address + await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); + await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); - await collectionEvm.methods.addCollectionAdmin(newAdmin).send(); - const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]); - expect(adminList[0].asEthereum.toString().toLocaleLowerCase()) - .to.be.eq(newAdmin.toLocaleLowerCase()); + // 1. Expect api.rpc.unique.adminlist returns admins: + const adminListRpc = await helper.collection.getAdmins(collectionId); + expect(adminListRpc).to.has.length(3); + expect(adminListRpc).to.be.deep.contain.members([{Substrate: adminSub.address}, {Ethereum: adminEth}, {Ethereum: adminDeprecated}]); + + // 2. Expect methods.collectionAdmins == api.rpc.unique.adminlist + let adminListEth = await collectionEvm.methods.collectionAdmins().call(); + adminListEth = adminListEth.map((element: IEthCrossAccountId) => { + return helper.address.convertCrossAccountFromEthCrossAccount(element); + }); + expect(adminListRpc).to.be.like(adminListEth); }); - itEth('Add cross account admin by owner', async ({helper, privateKey}) => { + itEth('cross account admin can mint', async ({helper}) => { + // arrange: create collection and accounts const owner = await helper.eth.createAccountWithBalance(donor); - - const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', 'a', 'b', 'uri'); + const adminEth = (await helper.eth.createAccountWithBalance(donor)).toLowerCase(); + const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); + const [adminSub] = await helper.arrange.createAccounts([100n], donor); + const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + + // cannot mint while not admin + await expect(collectionEvm.methods.mint(owner).send({from: adminEth})).to.be.rejected; + await expect(helper.nft.mintToken(adminSub, {collectionId, owner: {Ethereum: owner}})).to.be.rejectedWith(/common.PublicMintingNotAllowed/); - const newAdmin = await privateKey('//Bob'); - const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin); - await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send(); + // admin (sub and eth) can mint token: + await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); + await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); + await collectionEvm.methods.mint(owner).send({from: adminEth}); + await helper.nft.mintToken(adminSub, {collectionId, owner: {Ethereum: owner}}); - const adminList = await helper.collection.getAdmins(collectionId); - expect(adminList).to.be.like([{Substrate: newAdmin.address}]); + expect(await helper.collection.getLastTokenId(collectionId)).to.eq(2); }); - itEth('Check adminlist', async ({helper, privateKey}) => { + itEth('cannot add invalid cross account admin', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - - const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const [admin] = await helper.arrange.createAccounts([100n, 100n], donor); - const admin1 = helper.eth.createAccount(); - const admin2 = await privateKey('admin'); - const admin2Cross = helper.ethCrossAccount.fromKeyringPair(admin2); - - // Soft-deprecated - await collectionEvm.methods.addCollectionAdmin(admin1).send(); - await collectionEvm.methods.addCollectionAdminCross(admin2Cross).send(); + const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - const adminListRpc = await helper.collection.getAdmins(collectionId); - let adminListEth = await collectionEvm.methods.collectionAdmins().call(); - adminListEth = adminListEth.map((element: IEthCrossAccountId) => { - return helper.address.convertCrossAccountFromEthCrossAcoount(element); - }); - expect(adminListRpc).to.be.like(adminListEth); + const adminCross = { + eth: helper.address.substrateToEth(admin.address), + sub: admin.addressRaw, + }; + await expect(collectionEvm.methods.addCollectionAdminCross(adminCross).send()).to.be.rejected; }); - // Soft-deprecated - itEth('Verify owner or admin', async ({helper}) => { + itEth('can verify owner with methods.isOwnerOrAdmin[Cross]', async ({helper, privateKey}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const newAdmin = helper.eth.createAccount(); + const adminDeprecated = helper.eth.createAccount(); + const admin1Cross = helper.ethCrossAccount.fromKeyringPair(await privateKey('admin')); + const admin2Cross = helper.ethCrossAccount.fromAddress(helper.address.substrateToEth((await privateKey('admin3')).address)); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.false; - await collectionEvm.methods.addCollectionAdmin(newAdmin).send(); - expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true; - }); + // Soft-deprecated: + expect(await collectionEvm.methods.isOwnerOrAdmin(adminDeprecated).call()).to.be.false; + expect(await collectionEvm.methods.isOwnerOrAdminCross(admin1Cross).call()).to.be.false; + expect(await collectionEvm.methods.isOwnerOrAdminCross(admin2Cross).call()).to.be.false; - itEth('Verify owner or admin cross', async ({helper, privateKey}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); + await collectionEvm.methods.addCollectionAdmin(adminDeprecated).send(); + await collectionEvm.methods.addCollectionAdminCross(admin1Cross).send(); + await collectionEvm.methods.addCollectionAdminCross(admin2Cross).send(); - const newAdmin = await privateKey('admin'); - const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - - expect(await collectionEvm.methods.isOwnerOrAdminCross(newAdminCross).call()).to.be.false; - await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send(); - expect(await collectionEvm.methods.isOwnerOrAdminCross(newAdminCross).call()).to.be.true; + // Soft-deprecated: isOwnerOrAdmin returns true + expect(await collectionEvm.methods.isOwnerOrAdmin(adminDeprecated).call()).to.be.true; + // Expect isOwnerOrAdminCross return true + expect(await collectionEvm.methods.isOwnerOrAdminCross(admin1Cross).call()).to.be.true; + expect(await collectionEvm.methods.isOwnerOrAdminCross(admin2Cross).call()).to.be.true; }); // Soft-deprecated @@ -154,12 +172,11 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const [admin] = await helper.arrange.createAccounts([10n], donor); + const [admin, notAdmin] = await helper.arrange.createAccounts([10n, 10n], donor); const adminCross = helper.ethCrossAccount.fromKeyringPair(admin); const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await collectionEvm.methods.addCollectionAdminCross(adminCross).send(); - const [notAdmin] = await helper.arrange.createAccounts([10n], donor); const notAdminCross = helper.ethCrossAccount.fromKeyringPair(notAdmin); await expect(collectionEvm.methods.addCollectionAdminCross(notAdminCross).call({from: adminCross.eth})) .to.be.rejectedWith('NoPermission'); @@ -222,19 +239,29 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const [newAdmin] = await helper.arrange.createAccounts([10n], donor); - const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin); + const [adminSub] = await helper.arrange.createAccounts([10n], donor); + const adminEth = (await helper.eth.createAccountWithBalance(donor)).toLowerCase(); + const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); + const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send(); + await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); + await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); + { - const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]); - expect(adminList[0].asSubstrate.toString().toLocaleLowerCase()) - .to.be.eq(newAdmin.address.toLocaleLowerCase()); + const adminList = await helper.collection.getAdmins(collectionId); + expect(adminList).to.deep.include({Substrate: adminSub.address}); + expect(adminList).to.deep.include({Ethereum: adminEth}); } - await collectionEvm.methods.removeCollectionAdminCross(newAdminCross).send(); - const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]); + await collectionEvm.methods.removeCollectionAdminCross(adminCrossSub).send(); + await collectionEvm.methods.removeCollectionAdminCross(adminCrossEth).send(); + const adminList = await helper.collection.getAdmins(collectionId); expect(adminList.length).to.be.eq(0); + + // Non admin cannot mint: + await expect(helper.nft.mintToken(adminSub, {collectionId, owner: {Substrate: adminSub.address}})).to.be.rejectedWith(/common.PublicMintingNotAllowed/); + await expect(collectionEvm.methods.mint(adminEth).send({from: adminEth})).to.be.rejected; }); // Soft-deprecated @@ -378,16 +405,27 @@ itEth('Change owner [cross]', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const [newOwner] = await helper.arrange.createAccounts([10n], donor); - const newOwnerCross = helper.ethCrossAccount.fromKeyringPair(newOwner); - const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const ownerEth = await helper.eth.createAccountWithBalance(donor); + const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth); + const [ownerSub] = await helper.arrange.createAccounts([10n], donor); + const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub); - expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.false; + const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - await collectionEvm.methods.changeCollectionOwnerCross(newOwnerCross).send(); + expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.false; - expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.true; + // Can set ethereum owner: + await collectionEvm.methods.changeCollectionOwnerCross(ownerCrossEth).send({from: owner}); + expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossEth).call()).to.be.true; + expect(await helper.collection.getData(collectionId)) + .to.have.property('normalizedOwner').that.is.eq(helper.address.ethToSubstrate(ownerEth)); + + // Can set Substrate owner: + await collectionEvm.methods.changeCollectionOwnerCross(ownerCrossSub).send({from: ownerEth}); + expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.true; + expect(await helper.collection.getData(collectionId)) + .to.have.property('normalizedOwner').that.is.eq(helper.address.normalizeSubstrate(ownerSub.address)); }); itEth.skip('change owner call fee', async ({helper}) => { --- /dev/null +++ b/tests/src/eth/collectionHelperAddress.test.ts @@ -0,0 +1,72 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {itEth, usingEthPlaygrounds, expect} from './util'; +import {IKeyringPair} from '@polkadot/types/types'; +import {Pallets} from '../util'; + +const EVM_COLLECTION_HELPERS_ADDRESS = '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f'; + +describe('[eth]CollectionHelperAddress test: ERC20/ERC721 ', () => { + let donor: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = await privateKey({filename: __filename}); + }); + }); + + itEth('NFT', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + + const {collectionAddress: nftCollectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC'); + const nftCollection = helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner); + + expect((await nftCollection.methods.collectionHelperAddress().call()) + .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); + }); + + itEth.ifWithPallets('RFT ', [Pallets.ReFungible], async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + + const {collectionAddress: rftCollectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC'); + + const rftCollection = helper.ethNativeContract.collection(rftCollectionAddress, 'rft', owner); + expect((await rftCollection.methods.collectionHelperAddress().call()) + .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); + }); + + itEth('FT', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', 18, 'absolutely anything', 'ROC'); + const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + + expect((await collection.methods.collectionHelperAddress().call()) + .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); + }); + + itEth('[collectionHelpers] convert collectionId into address', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collectionId = 7; + const collectionAddress = helper.ethAddress.fromCollectionId(collectionId); + const helperContract = helper.ethNativeContract.collectionHelpers(owner); + + expect(await helperContract.methods.collectionAddress(collectionId).call()).to.be.equal(collectionAddress); + expect(parseInt(await helperContract.methods.collectionId(collectionAddress).call())).to.be.equal(collectionId); + }); + +}); --- a/tests/src/eth/contractSponsoring.test.ts +++ b/tests/src/eth/contractSponsoring.test.ts @@ -372,7 +372,7 @@ const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address); expect(originalFlipperBalance).to.be.not.equal('0'); - await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/); + await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/Returned error: insufficient funds for gas \* price \+ value/); expect(await flipper.methods.getValue().call()).to.be.false; // Balance should be taken from flipper instead of caller --- a/tests/src/eth/createFTCollection.test.ts +++ b/tests/src/eth/createFTCollection.test.ts @@ -144,7 +144,7 @@ itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); + const {collectionAddress, collectionId} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); const result = await collectionHelper.methods @@ -166,6 +166,7 @@ expect(await collectionHelper.methods .isCollectionExist(collectionAddress) .call()).to.be.false; + expect(await helper.collection.getData(collectionId)).to.be.null; }); }); @@ -214,12 +215,15 @@ } }); - itEth('(!negative test!) Create collection (no funds)', async ({helper}) => { + itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - await expect(collectionHelper.methods - .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW') - .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); + const expects = [0n, 1n, 30n].map(async value => { + await expect(collectionHelper.methods + .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW') + .call({value: Number(value * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); + }); + await Promise.all(expects); }); // Soft-deprecated --- a/tests/src/eth/createNFTCollection.test.ts +++ b/tests/src/eth/createNFTCollection.test.ts @@ -308,7 +308,7 @@ itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); + const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); @@ -331,5 +331,6 @@ expect(await collectionHelper.methods .isCollectionExist(collectionAddress) .call()).to.be.false; + expect(await helper.collection.getData(collectionId)).to.be.null; }); }); \ No newline at end of file --- a/tests/src/eth/createRFTCollection.test.ts +++ b/tests/src/eth/createRFTCollection.test.ts @@ -340,7 +340,7 @@ itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); + const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); await expect(collectionHelper.methods @@ -349,6 +349,7 @@ expect(await collectionHelper.methods .isCollectionExist(collectionAddress) - .call()).to.be.false; + .call()).to.be.false; + expect(await helper.collection.getData(collectionId)).to.be.null; }); }); --- a/tests/src/eth/destroyCollection.test.ts +++ b/tests/src/eth/destroyCollection.test.ts @@ -15,62 +15,48 @@ // along with Unique Network. If not, see . import {IKeyringPair} from '@polkadot/types/types'; -import {Pallets, requirePalletsOrSkip} from '../util'; +import {Pallets} from '../util'; import {expect, itEth, usingEthPlaygrounds} from './util'; - -describe('Destroy Collection from EVM', () => { +describe('Destroy Collection from EVM', function() { let donor: IKeyringPair; + const testCases = [ + {method: 'createRFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF'], requiredPallets: [Pallets.ReFungible]}, + {method: 'createNFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF'], requiredPallets: [Pallets.NFT]}, + {method: 'createFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF', 18], requiredPallets: [Pallets.Fungible]}, + ]; before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { - requirePalletsOrSkip(this, helper, [Pallets.ReFungible, Pallets.NFT]); + await usingEthPlaygrounds(async (_, privateKey) => { donor = await privateKey({filename: __filename}); }); }); - - itEth('(!negative test!) RFT', async ({helper}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - const signer = await helper.eth.createAccountWithBalance(donor); - - const unexistedCollection = helper.ethAddress.fromCollectionId(1000000); - - const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); - const collectionHelper = helper.ethNativeContract.collectionHelpers(signer); - - await expect(collectionHelper.methods - .destroyCollection(collectionAddress) - .send({from: signer})).to.be.rejected; - - await expect(collectionHelper.methods - .destroyCollection(unexistedCollection) - .send({from: signer})).to.be.rejected; - - expect(await collectionHelper.methods - .isCollectionExist(unexistedCollection) - .call()).to.be.false; - }); - - itEth('(!negative test!) NFT', async ({helper}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - const signer = await helper.eth.createAccountWithBalance(donor); - - const unexistedCollection = helper.ethAddress.fromCollectionId(1000000); - - const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); - const collectionHelper = helper.ethNativeContract.collectionHelpers(signer); - - await expect(collectionHelper.methods - .destroyCollection(collectionAddress) - .send({from: signer})).to.be.rejected; - - await expect(collectionHelper.methods - .destroyCollection(unexistedCollection) - .send({from: signer})).to.be.rejected; - - expect(await collectionHelper.methods - .isCollectionExist(unexistedCollection) - .call()).to.be.false; - }); + testCases.map((testCase) => + itEth.ifWithPallets(`Cannot burn non-owned or non-existing collection ${testCase.method}`, testCase.requiredPallets, async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const signer = await helper.eth.createAccountWithBalance(donor); + + const unexistedCollection = helper.ethAddress.fromCollectionId(1000000); + + const collectionHelpers = helper.ethNativeContract.collectionHelpers(signer); + const {collectionAddress} = await helper.eth.createCollecion(testCase.method, owner, ...testCase.params as [string, string, string, number?]); + + // cannot burn collec + await expect(collectionHelpers.methods + .destroyCollection(collectionAddress) + .send({from: signer})).to.be.rejected; + + await expect(collectionHelpers.methods + .destroyCollection(unexistedCollection) + .send({from: signer})).to.be.rejected; + + expect(await collectionHelpers.methods + .isCollectionExist(unexistedCollection) + .call()).to.be.false; + + expect(await collectionHelpers.methods + .isCollectionExist(collectionAddress) + .call()).to.be.true; + })); }); --- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -232,57 +232,70 @@ }); itEth('Can perform transferCross()', async ({helper}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - const receiver = await helper.eth.createAccountWithBalance(donor); - const to = helper.ethCrossAccount.fromAddress(receiver); - const toSubstrate = helper.ethCrossAccount.fromKeyringPair(donor); + const sender = await helper.eth.createAccountWithBalance(donor); + const receiverEth = await helper.eth.createAccountWithBalance(donor); + const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); + const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(donor); const collection = await helper.ft.mintCollection(alice); - await collection.mint(alice, 200n, {Ethereum: owner}); + await collection.mint(alice, 200n, {Ethereum: sender}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender); { - const result = await contract.methods.transferCross(to, 50).send({from: owner}); - + // Can transferCross to ethereum address: + const result = await collectionEvm.methods.transferCross(receiverCrossEth, 50).send({from: sender}); + // Check events: const event = result.events.Transfer; expect(event.address).to.be.equal(collectionAddress); - expect(event.returnValues.from).to.be.equal(owner); - expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.from).to.be.equal(sender); + expect(event.returnValues.to).to.be.equal(receiverEth); expect(event.returnValues.value).to.be.equal('50'); - } - - { - const balance = await contract.methods.balanceOf(owner).call(); - expect(+balance).to.equal(150); - } - - { - const balance = await contract.methods.balanceOf(receiver).call(); - expect(+balance).to.equal(50); + // Sender's balance decreased: + const ownerBalance = await collectionEvm.methods.balanceOf(sender).call(); + expect(+ownerBalance).to.equal(150); + // Receiver's balance increased: + const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); + expect(+receiverBalance).to.equal(50); } { - const result = await contract.methods.transferCross(toSubstrate, 50).send({from: owner}); - + // Can transferCross to substrate address: + const result = await collectionEvm.methods.transferCross(receiverCrossSub, 50).send({from: sender}); + // Check events: const event = result.events.Transfer; expect(event.address).to.be.equal(collectionAddress); - expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.from).to.be.equal(sender); expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(donor.address)); expect(event.returnValues.value).to.be.equal('50'); - } - - { - const balance = await collection.getBalance({Ethereum: owner}); - expect(balance).to.equal(100n); - } - - { + // Sender's balance decreased: + const senderBalance = await collection.getBalance({Ethereum: sender}); + expect(senderBalance).to.equal(100n); + // Receiver's balance increased: const balance = await collection.getBalance({Substrate: donor.address}); expect(balance).to.equal(50n); } - }); + + ['transfer', 'transferCross'].map(testCase => itEth(`Cannot ${testCase} incorrect amount`, async ({helper}) => { + const sender = await helper.eth.createAccountWithBalance(donor); + const receiverEth = await helper.eth.createAccountWithBalance(donor); + const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); + const BALANCE = 200n; + const BALANCE_TO_TRANSFER = BALANCE + 100n; + + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, BALANCE, {Ethereum: sender}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender); + + // 1. Cannot transfer more than have + const receiver = testCase === 'transfer' ? receiverEth : receiverCrossEth; + await expect(collectionEvm.methods[testCase](receiver, BALANCE_TO_TRANSFER).send({from: sender})).to.be.rejected; + // 2. Zero transfer allowed (EIP-20): + await collectionEvm.methods[testCase](receiver, 0n).send({from: sender}); + })); + itEth('Can perform transfer()', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); @@ -314,7 +327,7 @@ } }); - itEth('Can perform transferFromCross()', async ({helper, privateKey}) => { + itEth('Can perform transferFromCross()', async ({helper}) => { const sender = await helper.eth.createAccountWithBalance(donor, 100n); const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0); @@ -508,7 +521,7 @@ expect(event.returnValues.value).to.be.equal('51'); }); - itEth('Events emitted for transferFromCross()', async ({helper, privateKey}) => { + itEth('Events emitted for transferFromCross()', async ({helper}) => { const sender = await helper.eth.createAccountWithBalance(donor, 100n); const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -17,7 +17,6 @@ import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util'; import {IKeyringPair} from '@polkadot/types/types'; import {Contract} from 'web3-eth-contract'; -import exp from 'constants'; describe('NFT: Information getting', () => { @@ -252,58 +251,124 @@ itEth('Can perform burnFromCross()', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); + const ownerSub = bob; + const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub); + const ownerEth = await helper.eth.createAccountWithBalance(donor, 100n); + const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth); - const owner = bob; - const spender = await helper.eth.createAccountWithBalance(donor, 100n); + const burnerEth = await helper.eth.createAccountWithBalance(donor, 100n); + const burnerCrossEth = helper.ethCrossAccount.fromAddress(burnerEth); - const token = await collection.mintToken(minter, {Substrate: owner.address}); + const token1 = await collection.mintToken(minter, {Substrate: ownerSub.address}); + const token2 = await collection.mintToken(minter, {Ethereum: ownerEth}); - const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft'); - { - await token.approve(owner, {Ethereum: spender}); - const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner); - const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender}); - const events = result.events.Transfer; + // Approve tokens from substrate and ethereum: + await token1.approve(ownerSub, {Ethereum: burnerEth}); + await collectionEvm.methods.approveCross(burnerCrossEth, token2.tokenId).send({from: ownerEth}); - expect(events).to.be.like({ - address, + // can burnFromCross: + const result1 = await collectionEvm.methods.burnFromCross(ownerCrossSub, token1.tokenId).send({from: burnerEth}); + const result2 = await collectionEvm.methods.burnFromCross(ownerCrossEth, token2.tokenId).send({from: burnerEth}); + const events1 = result1.events.Transfer; + const events2 = result2.events.Transfer; + + // Check events for burnFromCross (substrate and ethereum): + [ + [events1, token1, helper.address.substrateToEth(ownerSub.address)], + [events2, token2, ownerEth], + ].map(burnData => { + expect(burnData[0]).to.be.like({ + address: collectionAddress, event: 'Transfer', returnValues: { - from: helper.address.substrateToEth(owner.address), + from: burnData[2], to: '0x0000000000000000000000000000000000000000', - tokenId: token.tokenId.toString(), + tokenId: burnData[1].tokenId.toString(), }, }); - } + }); + + expect(await token1.doesExist()).to.be.false; + expect(await token2.doesExist()).to.be.false; }); itEth('Can perform approveCross()', async ({helper}) => { + // arrange: create accounts + const owner = await helper.eth.createAccountWithBalance(donor, 100n); + const ownerCross = helper.ethCrossAccount.fromAddress(owner); + const receiverSub = charlie; + const recieverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub); + const receiverEth = await helper.eth.createAccountWithBalance(donor, 100n); + const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); + + // arrange: create collection and tokens: const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); + const token1 = await collection.mintToken(minter, {Ethereum: owner}); + const token2 = await collection.mintToken(minter, {Ethereum: owner}); + + const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + + // Can approveCross substrate and ethereum address: + const resultSub = await collectionEvm.methods.approveCross(recieverCrossSub, token1.tokenId).send({from: owner}); + const resultEth = await collectionEvm.methods.approveCross(receiverCrossEth, token2.tokenId).send({from: owner}); + const eventSub = resultSub.events.Approval; + const eventEth = resultEth.events.Approval; + expect(eventSub).to.be.like({ + address: helper.ethAddress.fromCollectionId(collection.collectionId), + event: 'Approval', + returnValues: { + owner, + approved: helper.address.substrateToEth(receiverSub.address), + tokenId: token1.tokenId.toString(), + }, + }); + expect(eventEth).to.be.like({ + address: helper.ethAddress.fromCollectionId(collection.collectionId), + event: 'Approval', + returnValues: { + owner, + approved: receiverEth, + tokenId: token2.tokenId.toString(), + }, + }); + + // Substrate address can transferFrom approved tokens: + await helper.nft.transferTokenFrom(receiverSub, collection.collectionId, token1.tokenId, {Ethereum: owner}, {Substrate: receiverSub.address}); + expect(await helper.nft.getTokenOwner(collection.collectionId, token1.tokenId)).to.deep.eq({Substrate: receiverSub.address}); + // Ethereum address can transferFromCross approved tokens: + await collectionEvm.methods.transferFromCross(ownerCross, receiverCrossEth, token2.tokenId).send({from: receiverEth}); + expect(await helper.nft.getTokenOwner(collection.collectionId, token2.tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()}); + }); + itEth('Can reaffirm approved address', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor, 100n); - const receiver = charlie; + const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner); + const [receiver1, receiver2] = await helper.arrange.createAccounts([100n, 100n], donor); + const receiver1Cross = helper.ethCrossAccount.fromKeyringPair(receiver1); + const receiver2Cross = helper.ethCrossAccount.fromKeyringPair(receiver2); + const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); + const token1 = await collection.mintToken(minter, {Ethereum: owner}); + const token2 = await collection.mintToken(minter, {Ethereum: owner}); + const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); - const token = await collection.mintToken(minter, {Ethereum: owner}); + // Can approve and reaffirm approved address: + await collectionEvm.methods.approveCross(receiver1Cross, token1.tokenId).send({from: owner}); + await collectionEvm.methods.approveCross(receiver2Cross, token1.tokenId).send({from: owner}); - const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + // receiver1 cannot transferFrom: + await expect(helper.nft.transferTokenFrom(receiver1, collection.collectionId, token1.tokenId, {Ethereum: owner}, {Substrate: receiver1.address})).to.be.rejected; + // receiver2 can transferFrom: + await helper.nft.transferTokenFrom(receiver2, collection.collectionId, token1.tokenId, {Ethereum: owner}, {Substrate: receiver2.address}); - { - const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); - const result = await contract.methods.approveCross(recieverCross, token.tokenId).send({from: owner}); - const event = result.events.Approval; - expect(event).to.be.like({ - address: helper.ethAddress.fromCollectionId(collection.collectionId), - event: 'Approval', - returnValues: { - owner, - approved: helper.address.substrateToEth(receiver.address), - tokenId: token.tokenId.toString(), - }, - }); - } + // can set approved address to self address to remove approval: + await collectionEvm.methods.approveCross(receiver1Cross, token2.tokenId).send({from: owner}); + await collectionEvm.methods.approveCross(ownerCrossEth, token2.tokenId).send({from: owner}); + + // receiver1 cannot transfer token anymore: + await expect(helper.nft.transferTokenFrom(receiver1, collection.collectionId, token2.tokenId, {Ethereum: owner}, {Substrate: receiver1.address})).to.be.rejected; }); itEth('Can perform transferFrom()', async ({helper}) => { @@ -340,13 +405,11 @@ } }); - itEth('Can perform transferFromCross()', async ({helper, privateKey}) => { - const minter = await privateKey('//Alice'); + itEth('Can perform transferFromCross()', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); - const owner = await privateKey('//Bob'); + const [owner, receiver] = await helper.arrange.createAccounts([100n, 100n], donor); const spender = await helper.eth.createAccountWithBalance(donor); - const receiver = await privateKey('//Charlie'); const token = await collection.mintToken(minter, {Substrate: owner.address}); @@ -408,56 +471,72 @@ itEth('Can perform transferCross()', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {}); const owner = await helper.eth.createAccountWithBalance(donor); - const receiver = await helper.eth.createAccountWithBalance(donor); - const to = helper.ethCrossAccount.fromAddress(receiver); - const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter); + const receiverEth = await helper.eth.createAccountWithBalance(donor); + const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); + const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter); const {tokenId} = await collection.mintToken(minter, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { - const result = await contract.methods.transferCross(to, tokenId).send({from: owner}); - + // Can transferCross to ethereum address: + const result = await collectionEvm.methods.transferCross(receiverCrossEth, tokenId).send({from: owner}); + // Check events: const event = result.events.Transfer; expect(event.address).to.be.equal(collectionAddress); expect(event.returnValues.from).to.be.equal(owner); - expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.to).to.be.equal(receiverEth); expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); - } - - { - const balance = await contract.methods.balanceOf(owner).call(); - expect(+balance).to.equal(0); - } - - { - const balance = await contract.methods.balanceOf(receiver).call(); - expect(+balance).to.equal(1); + + // owner has balance = 0: + const ownerBalance = await collectionEvm.methods.balanceOf(owner).call(); + expect(+ownerBalance).to.equal(0); + // receiver owns token: + const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); + expect(+receiverBalance).to.equal(1); + expect(await helper.nft.getTokenOwner(collection.collectionId, tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()}); } { - const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver}); - - + // Can transferCross to substrate address: + const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, tokenId).send({from: receiverEth}); + // Check events: const event = substrateResult.events.Transfer; expect(event.address).to.be.equal(collectionAddress); - expect(event.returnValues.from).to.be.equal(receiver); + expect(event.returnValues.from).to.be.equal(receiverEth); expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address)); expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); + + // owner has balance = 0: + const ownerBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); + expect(+ownerBalance).to.equal(0); + // receiver owns token: + const receiverBalance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address}); + expect(receiverBalance).to.contain(tokenId); } + }); + + ['transfer', 'transferCross'].map(testCase => itEth(`Cannot ${testCase} non-owned token`, async ({helper}) => { + const sender = await helper.eth.createAccountWithBalance(donor); + const tokenOwner = await helper.eth.createAccountWithBalance(donor); + const receiverSub = minter; + const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter); - { - const balance = await contract.methods.balanceOf(receiver).call(); - expect(+balance).to.equal(0); - } + const collection = await helper.nft.mintCollection(minter, {}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', sender); - { - const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address}); - expect(balance).to.be.contain(tokenId); - } - }); + await collection.mintToken(minter, {Ethereum: sender}); + const nonSendersToken = await collection.mintToken(minter, {Ethereum: tokenOwner}); + + // Cannot transferCross someone else's token: + const receiver = testCase === 'transfer' ? helper.address.substrateToEth(receiverSub.address) : receiverCrossSub; + await expect(collectionEvm.methods[testCase](receiver, nonSendersToken.tokenId).send({from: sender})).to.be.rejected; + // Cannot transfer token if it does not exist: + await expect(collectionEvm.methods[testCase](receiver, 999999).send({from: sender})).to.be.rejected; + })); }); describe('NFT: Fees', () => { @@ -501,7 +580,7 @@ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itEth('Can perform transferFromCross()', async ({helper, privateKey}) => { + itEth('Can perform transferFromCross()', async ({helper}) => { const collectionMinter = alice; const owner = bob; const receiver = charlie; --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -363,57 +363,75 @@ }); itEth('Can perform transferCross()', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const receiver = await helper.eth.createAccountWithBalance(donor); - const to = helper.ethCrossAccount.fromAddress(receiver); - const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter); + const sender = await helper.eth.createAccountWithBalance(donor); + const receiverEth = await helper.eth.createAccountWithBalance(donor); + const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); + const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter); + const collection = await helper.rft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender); - const {tokenId} = await collection.mintToken(minter, 1n, {Ethereum: caller}); + const token = await collection.mintToken(minter, 50n, {Ethereum: sender}); { - const result = await contract.methods.transferCross(to, tokenId).send({from: caller}); - + // Can transferCross to ethereum address: + const result = await collectionEvm.methods.transferCross(receiverCrossEth, token.tokenId).send({from: sender}); + // Check events: const event = result.events.Transfer; expect(event.address).to.equal(collectionAddress); - expect(event.returnValues.from).to.equal(caller); - expect(event.returnValues.to).to.equal(receiver); - expect(event.returnValues.tokenId).to.equal(tokenId.toString()); - } - - { - const balance = await contract.methods.balanceOf(caller).call(); - expect(+balance).to.equal(0); + expect(event.returnValues.from).to.equal(sender); + expect(event.returnValues.to).to.equal(receiverEth); + expect(event.returnValues.tokenId).to.equal(token.tokenId.toString()); + // Sender's balance decreased: + const senderBalance = await collectionEvm.methods.balanceOf(sender).call(); + expect(+senderBalance).to.equal(0); + expect(await token.getBalance({Ethereum: sender})).to.eq(0n); + // Receiver's balance increased: + const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); + expect(+receiverBalance).to.equal(1); + expect(await token.getBalance({Ethereum: receiverEth})).to.eq(50n); } - - { - const balance = await contract.methods.balanceOf(receiver).call(); - expect(+balance).to.equal(1); - } { - const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver}); - - + // Can transferCross to substrate address: + const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, token.tokenId).send({from: receiverEth}); + // Check events: const event = substrateResult.events.Transfer; expect(event.address).to.be.equal(collectionAddress); - expect(event.returnValues.from).to.be.equal(receiver); + expect(event.returnValues.from).to.be.equal(receiverEth); expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address)); - expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); + expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`); + // Sender's balance decreased: + const senderBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); + expect(+senderBalance).to.equal(0); + expect(await token.getBalance({Ethereum: receiverEth})).to.eq(0n); + // Receiver's balance increased: + const receiverBalance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address}); + expect(receiverBalance).to.contain(token.tokenId); + expect(await token.getBalance({Substrate: minter.address})).to.eq(50n); } + }); + + ['transfer', 'transferCross'].map(testCase => itEth(`Cannot ${testCase} non-owned token`, async ({helper}) => { + const sender = await helper.eth.createAccountWithBalance(donor); + const tokenOwner = await helper.eth.createAccountWithBalance(donor); + const receiverSub = minter; + const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter); - { - const balance = await contract.methods.balanceOf(receiver).call(); - expect(+balance).to.equal(0); - } + const collection = await helper.rft.mintCollection(minter, {}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender); + + await collection.mintToken(minter, 50n, {Ethereum: sender}); + const nonSendersToken = await collection.mintToken(minter, 50n, {Ethereum: tokenOwner}); - { - const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address}); - expect(balance).to.be.contain(tokenId); - } - }); + // Cannot transferCross someone else's token: + const receiver = testCase === 'transfer' ? helper.address.substrateToEth(receiverSub.address) : receiverCrossSub; + await expect(collectionEvm.methods[testCase](receiver, nonSendersToken.tokenId).send({from: sender})).to.be.rejected; + // Cannot transfer token if it does not exist: + await expect(collectionEvm.methods[testCase](receiver, 999999).send({from: sender})).to.be.rejected; + })); itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); --- a/tests/src/eth/reFungibleToken.test.ts +++ b/tests/src/eth/reFungibleToken.test.ts @@ -227,6 +227,46 @@ } }); + [ + 'transfer', + // 'transferCross', // TODO + ].map(testCase => + itEth(`Cannot ${testCase}() non-owned token`, async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice); + const rftOwner = await collection.mintToken(alice, 10n, {Ethereum: owner}); + const rftReceiver = await collection.mintToken(alice, 10n, {Ethereum: receiver}); + const tokenIdNonExist = 9999999; + + const tokenAddress1 = helper.ethAddress.fromTokenId(collection.collectionId, rftOwner.tokenId); + const tokenAddress2 = helper.ethAddress.fromTokenId(collection.collectionId, rftReceiver.tokenId); + const tokenAddressNonExist = helper.ethAddress.fromTokenId(collection.collectionId, tokenIdNonExist); + const tokenEvmOwner = helper.ethNativeContract.rftToken(tokenAddress1, owner); + const tokenEvmReceiver = helper.ethNativeContract.rftToken(tokenAddress2, owner); + const tokenEvmNonExist = helper.ethNativeContract.rftToken(tokenAddressNonExist, owner); + + // 1. Can transfer zero amount (EIP-20): + await tokenEvmOwner.methods[testCase](receiver, 0).send({from: owner}); + // 2. Cannot transfer non-owned token: + await expect(tokenEvmReceiver.methods[testCase](owner, 0).send({from: owner})).to.be.rejected; + await expect(tokenEvmReceiver.methods[testCase](owner, 5).send({from: owner})).to.be.rejected; + // 3. Cannot transfer non-existing token: + await expect(tokenEvmNonExist.methods[testCase](owner, 0).send({from: owner})).to.be.rejected; + await expect(tokenEvmNonExist.methods[testCase](owner, 5).send({from: owner})).to.be.rejected; + + // 4. Storage is not corrupted: + expect(await rftOwner.getTop10Owners()).to.deep.eq([{Ethereum: owner.toLowerCase()}]); + expect(await rftReceiver.getTop10Owners()).to.deep.eq([{Ethereum: receiver.toLowerCase()}]); + expect(await helper.rft.getTokenTop10Owners(collection.collectionId, tokenIdNonExist)).to.deep.eq([]); // TODO + + // 4.1 Tokens can be transferred: + await tokenEvmOwner.methods[testCase](receiver, 10).send({from: owner}); + await tokenEvmReceiver.methods[testCase](owner, 10).send({from: receiver}); + expect(await rftOwner.getTop10Owners()).to.deep.eq([{Ethereum: receiver.toLowerCase()}]); + expect(await rftReceiver.getTop10Owners()).to.deep.eq([{Ethereum: owner.toLowerCase()}]); + })); + itEth('Can perform repartition()', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const receiver = await helper.eth.createAccountWithBalance(donor); --- a/tests/src/eth/tokenProperties.test.ts +++ b/tests/src/eth/tokenProperties.test.ts @@ -120,17 +120,17 @@ const address = helper.ethAddress.fromCollectionId(collection.collectionId); const contract = helper.ethNativeContract.collection(address, mode, caller); - expect(await contract.methods.tokenProperties(token.tokenId, []).call()).to.be.deep.equal([]); + expect(await contract.methods.properties(token.tokenId, []).call()).to.be.deep.equal([]); await contract.methods.setProperties(token.tokenId, properties).send({from: caller}); const values = await token.getProperties(properties.map(p => p.key)); expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; })); - expect(await contract.methods.tokenProperties(token.tokenId, []).call()).to.be.like(properties + expect(await contract.methods.properties(token.tokenId, []).call()).to.be.like(properties .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); })); - expect(await contract.methods.tokenProperties(token.tokenId, [properties[0].key]).call()) + expect(await contract.methods.properties(token.tokenId, [properties[0].key]).call()) .to.be.like([helper.ethProperty.property(properties[0].key, properties[0].value.toString())]); } --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -103,12 +103,12 @@ contractHelpers(caller: string): Contract { const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS}); + return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS}); } collectionHelpers(caller: string) { const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS}); + return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS}); } collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false): Contract { @@ -186,11 +186,12 @@ return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]); } - async createCollecion(functionName: string, signer: string, name: string, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { + async createCollecion(functionName: 'createNFTCollection' | 'createRFTCollection' | 'createFTCollection', signer: string, name: string, description: string, tokenPrefix: string, decimals?: number): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice(); const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); - const result = await collectionHelper.methods[functionName](name, description, tokenPrefix).send({value: Number(collectionCreationPrice)}); + const functionParams = functionName === 'createFTCollection' ? [name, decimals, description, tokenPrefix] : [name, description, tokenPrefix]; + const result = await collectionHelper.methods[functionName](...functionParams).send({value: Number(collectionCreationPrice)}); const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress); @@ -217,17 +218,8 @@ return this.createCollecion('createRFTCollection', signer, name, description, tokenPrefix); } - async createFungibleCollection(signer: string, name: string, decimals: number, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> { - const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice(); - const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); - - const result = await collectionHelper.methods.createFTCollection(name, decimals, description, tokenPrefix).send({value: Number(collectionCreationPrice)}); - const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); - const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress); - - const events = this.helper.eth.normalizeEvents(result.events); - - return {collectionId, collectionAddress, events}; + createFungibleCollection(signer: string, name: string, decimals: number, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> { + return this.createCollecion('createFTCollection', signer, name, description, tokenPrefix, decimals); } async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { --- a/tests/src/fungible.test.ts +++ b/tests/src/fungible.test.ts @@ -15,7 +15,7 @@ // along with Unique Network. If not, see . import {IKeyringPair} from '@polkadot/types/types'; -import {itSub, usingPlaygrounds, expect} from './util'; +import {itSub, usingPlaygrounds, expect, requirePalletsOrSkip, Pallets} from './util'; const U128_MAX = (1n << 128n) - 1n; @@ -145,3 +145,42 @@ expect(await collection.getBalance(ethAcc)).to.be.equal(10n); }); }); + +describe('Fungible negative tests', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + let bob: IKeyringPair; + let charlie: IKeyringPair; + + before(async function() { + await usingPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.Fungible]); + + donor = await privateKey({filename: __filename}); + [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor); + }); + }); + + itSub('Cannot transfer incorrect amount of tokens', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const nonExistingCollection = helper.ft.getCollectionObject(99999); + await collection.mint(alice, 10n, {Substrate: bob.address}); + + // 1. Alice cannot transfer more than 0 tokens if balance low: + await expect(collection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(collection.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow'); + + // 2. Alice cannot transfer non-existing token: + await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.CollectionNotFound'); + await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.CollectionNotFound'); + + // 3. Zero transfer allowed (EIP-20): + await collection.transfer(bob, {Substrate: charlie.address}, 0n); + // 3.1 even if the balance = 0 + await collection.transfer(alice, {Substrate: charlie.address}, 0n); + + expect(await collection.getBalance({Substrate: alice.address})).to.eq(0n); + expect(await collection.getBalance({Substrate: bob.address})).to.eq(10n); + expect(await collection.getBalance({Substrate: charlie.address})).to.eq(0n); + }); +}); --- a/tests/src/interfaces/augment-api-consts.ts +++ b/tests/src/interfaces/augment-api-consts.ts @@ -8,8 +8,8 @@ import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types'; import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { Codec } from '@polkadot/types-codec/types'; -import type { Perbill, Permill, Weight } from '@polkadot/types/interfaces/runtime'; -import type { FrameSupportPalletId, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, XcmV1MultiLocation } from '@polkadot/types/lookup'; +import type { H160, Perbill, Permill, Weight } from '@polkadot/types/interfaces/runtime'; +import type { FrameSupportPalletId, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsCollectionLimits, XcmV1MultiLocation } from '@polkadot/types/lookup'; export type __AugmentedConst = AugmentedConst; @@ -70,6 +70,10 @@ **/ collectionCreationPrice: u128 & AugmentedConst; /** + * Address under which the CollectionHelper contract would be available. + **/ + contractAddress: H160 & AugmentedConst; + /** * Generic const **/ [key: string]: Codec; @@ -82,6 +86,16 @@ **/ [key: string]: Codec; }; + evmContractHelpers: { + /** + * Address, under which magic contract will be available + **/ + contractAddress: H160 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; inflation: { /** * Number of blocks that pass between treasury balance updates due to inflation @@ -94,13 +108,11 @@ }; scheduler: { /** - * The maximum weight that may be scheduled per block for any dispatchables of less - * priority than `schedule::HARD_DEADLINE`. + * The maximum weight that may be scheduled per block for any dispatchables. **/ maximumWeight: Weight & AugmentedConst; /** * The maximum number of scheduled calls in the queue for a single block. - * Not strictly enforced, but used for weight estimation. **/ maxScheduledPerBlock: u32 & AugmentedConst; /** @@ -233,6 +245,64 @@ **/ [key: string]: Codec; }; + unique: { + /** + * Maximum admins per collection. + **/ + collectionAdminsLimit: u32 & AugmentedConst; + /** + * Default FT collection limit. + **/ + ftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst; + /** + * Maximal length of a collection description. + **/ + maxCollectionDescriptionLength: u32 & AugmentedConst; + /** + * Maximal length of a collection name. + **/ + maxCollectionNameLength: u32 & AugmentedConst; + /** + * Maximum size for all collection properties. + **/ + maxCollectionPropertiesSize: u32 & AugmentedConst; + /** + * A maximum number of token properties. + **/ + maxPropertiesPerItem: u32 & AugmentedConst; + /** + * Maximal length of a property key. + **/ + maxPropertyKeyLength: u32 & AugmentedConst; + /** + * Maximal length of a property value. + **/ + maxPropertyValueLength: u32 & AugmentedConst; + /** + * Maximal length of a token prefix. + **/ + maxTokenPrefixLength: u32 & AugmentedConst; + /** + * Maximum size of all token properties. + **/ + maxTokenPropertiesSize: u32 & AugmentedConst; + /** + * A maximum number of levels of depth in the token nesting tree. + **/ + nestingBudget: u32 & AugmentedConst; + /** + * Default NFT collection limit. + **/ + nftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst; + /** + * Default RFT collection limit. + **/ + rftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; vesting: { /** * The minimum amount transferred to call `vested_transfer`. --- a/tests/src/interfaces/augment-api-errors.ts +++ b/tests/src/interfaces/augment-api-errors.ts @@ -265,6 +265,14 @@ **/ FeeOverflow: AugmentedError; /** + * Gas limit is too high. + **/ + GasLimitTooHigh: AugmentedError; + /** + * Gas limit is too low. + **/ + GasLimitTooLow: AugmentedError; + /** * Gas price is too low. **/ GasPriceTooLow: AugmentedError; @@ -277,6 +285,14 @@ **/ PaymentOverflow: AugmentedError; /** + * EVM reentrancy + **/ + Reentrancy: AugmentedError; + /** + * Undefined error. + **/ + Undefined: AugmentedError; + /** * Withdraw fee failed **/ WithdrawFailed: AugmentedError; @@ -321,6 +337,10 @@ **/ AccountNotEmpty: AugmentedError; /** + * Failed to decode event bytes + **/ + BadEvent: AugmentedError; + /** * Generic error **/ [key: string]: AugmentedError; @@ -644,22 +664,38 @@ }; scheduler: { /** + * There is no place for a new task in the agenda + **/ + AgendaIsExhausted: AugmentedError; + /** * Failed to schedule a call **/ FailedToSchedule: AugmentedError; /** + * Attempt to use a non-named function on a named task. + **/ + Named: AugmentedError; + /** * Cannot find the scheduled call. **/ NotFound: AugmentedError; /** - * Reschedule failed because it does not change scheduled time. + * Scheduled call preimage is not found + **/ + PreimageNotFound: AugmentedError; + /** + * Scheduled call is corrupted **/ - RescheduleNoChange: AugmentedError; + ScheduledCallCorrupted: AugmentedError; /** * Given target block number is in the past. **/ TargetBlockNumberInPast: AugmentedError; /** + * Scheduled call is too big + **/ + TooBigScheduledCall: AugmentedError; + /** * Generic error **/ [key: string]: AugmentedError; --- a/tests/src/interfaces/augment-api-events.ts +++ b/tests/src/interfaces/augment-api-events.ts @@ -6,10 +6,10 @@ import '@polkadot/api-base/types/events'; import type { ApiTypes, AugmentedEvent } from '@polkadot/api-base/types'; -import type { Bytes, Null, Option, Result, U256, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec'; +import type { Bytes, Null, Option, Result, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H160, H256, Weight } from '@polkadot/types/interfaces/runtime'; -import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportDispatchDispatchInfo, FrameSupportScheduleLookupError, FrameSupportTokensMiscBalanceStatus, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; +import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportDispatchDispatchInfo, FrameSupportTokensMiscBalanceStatus, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; export type __AugmentedEvent = AugmentedEvent; @@ -204,9 +204,9 @@ }; ethereum: { /** - * An ethereum transaction was successfully executed. [from, to/contract_address, transaction_hash, exit_reason] + * An ethereum transaction was successfully executed. **/ - Executed: AugmentedEvent; + Executed: AugmentedEvent; /** * Generic event **/ @@ -214,33 +214,25 @@ }; evm: { /** - * A deposit has been made at a given address. \[sender, address, value\] - **/ - BalanceDeposit: AugmentedEvent; - /** - * A withdrawal has been made from a given address. \[sender, address, value\] - **/ - BalanceWithdraw: AugmentedEvent; - /** - * A contract has been created at given \[address\]. + * A contract has been created at given address. **/ - Created: AugmentedEvent; + Created: AugmentedEvent; /** - * A \[contract\] was attempted to be created, but the execution failed. + * A contract was attempted to be created, but the execution failed. **/ - CreatedFailed: AugmentedEvent; + CreatedFailed: AugmentedEvent; /** - * A \[contract\] has been executed successfully with states applied. + * A contract has been executed successfully with states applied. **/ - Executed: AugmentedEvent; + Executed: AugmentedEvent; /** - * A \[contract\] has been executed with errors. States are reverted with only gas fees applied. + * A contract has been executed with errors. States are reverted with only gas fees applied. **/ - ExecutedFailed: AugmentedEvent; + ExecutedFailed: AugmentedEvent; /** * Ethereum events from contracts. **/ - Log: AugmentedEvent; + Log: AugmentedEvent; /** * Generic event **/ @@ -264,6 +256,16 @@ **/ [key: string]: AugmentedEvent; }; + evmMigration: { + /** + * This event is used in benchmarking and can be used for tests + **/ + TestEvent: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; foreignAssets: { /** * The asset registered. @@ -479,7 +481,7 @@ /** * The call for the provided hash was not found so the task has been aborted. **/ - CallLookupFailed: AugmentedEvent, id: Option, error: FrameSupportScheduleLookupError], { task: ITuple<[u32, u32]>, id: Option, error: FrameSupportScheduleLookupError }>; + CallUnavailable: AugmentedEvent, id: Option], { task: ITuple<[u32, u32]>, id: Option }>; /** * Canceled some task. **/ @@ -489,9 +491,13 @@ **/ Dispatched: AugmentedEvent, id: Option, result: Result], { task: ITuple<[u32, u32]>, id: Option, result: Result }>; /** + * The given task can never be executed since it is overweight. + **/ + PermanentlyOverweight: AugmentedEvent, id: Option], { task: ITuple<[u32, u32]>, id: Option }>; + /** * Scheduled task's priority has changed **/ - PriorityChanged: AugmentedEvent; + PriorityChanged: AugmentedEvent, priority: u8], { task: ITuple<[u32, u32]>, priority: u8 }>; /** * Scheduled some task. **/ @@ -560,6 +566,7 @@ [key: string]: AugmentedEvent; }; testUtils: { + BatchCompleted: AugmentedEvent; ShouldRollback: AugmentedEvent; ValueIsSet: AugmentedEvent; /** --- a/tests/src/interfaces/augment-api-query.ts +++ b/tests/src/interfaces/augment-api-query.ts @@ -9,7 +9,7 @@ import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H160, H256, Weight } from '@polkadot/types/interfaces/runtime'; -import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup'; +import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerV2BlockAgenda, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup'; import type { Observable } from '@polkadot/types/types'; export type __AugmentedQuery = AugmentedQuery unknown>; @@ -681,9 +681,14 @@ /** * Items to be executed, indexed by the block number that they should be executed on. **/ - agenda: AugmentedQuery Observable>>, [u32]> & QueryableStorageEntry; + agenda: AugmentedQuery Observable, [u32]> & QueryableStorageEntry; /** - * Lookup from identity to the block number and index of the task. + * It contains the block number from which we should service tasks. + * It's used for delaying the servicing of future blocks' agendas if we had overweight tasks. + **/ + incompleteSince: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * Lookup from a name to the block number and index of the task. **/ lookup: AugmentedQuery Observable>>, [U8aFixed]> & QueryableStorageEntry; /** --- a/tests/src/interfaces/augment-api-tx.ts +++ b/tests/src/interfaces/augment-api-tx.ts @@ -9,7 +9,7 @@ import type { Bytes, Compact, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, IMethod, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, Call, H160, H256, MultiAddress, Perbill, Permill, Weight } from '@polkadot/types/interfaces/runtime'; -import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumTransactionTransactionV2, FrameSupportScheduleMaybeHashed, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsPartEquippableList, RmrkTraitsPartPartType, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; +import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumLog, EthereumTransactionTransactionV2, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsPartEquippableList, RmrkTraitsPartPartType, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; export type __AugmentedSubmittable = AugmentedSubmittable<() => unknown>; export type __SubmittableExtrinsic = SubmittableExtrinsic; @@ -295,6 +295,14 @@ **/ finish: AugmentedSubmittable<(address: H160 | string | Uint8Array, code: Bytes | string | Uint8Array) => SubmittableExtrinsic, [H160, Bytes]>; /** + * Create ethereum events attached to the fake transaction + **/ + insertEthLogs: AugmentedSubmittable<(logs: Vec | (EthereumLog | { address?: any; topics?: any; data?: any } | string | Uint8Array)[]) => SubmittableExtrinsic, [Vec]>; + /** + * Create substrate events + **/ + insertEvents: AugmentedSubmittable<(events: Vec | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic, [Vec]>; + /** * Insert items into contract storage, this method can be called * multiple times **/ @@ -831,22 +839,56 @@ }; scheduler: { /** + * Cancel an anonymously scheduled task. + * + * The `T::OriginPrivilegeCmp` decides whether the given origin is allowed to cancel the task or not. + **/ + cancel: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, index: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, u32]>; + /** * Cancel a named scheduled task. + * + * The `T::OriginPrivilegeCmp` decides whether the given origin is allowed to cancel the task or not. **/ cancelNamed: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array) => SubmittableExtrinsic, [U8aFixed]>; + /** + * Change a named task's priority. + * + * Only the `T::PrioritySetOrigin` is allowed to change the task's priority. + **/ changeNamedPriority: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [U8aFixed, u8]>; /** + * Anonymously schedule a task. + * + * Only `T::ScheduleOrigin` is allowed to schedule a task. + * Only `T::PrioritySetOrigin` is allowed to set the task's priority. + **/ + schedule: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: Call | IMethod | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, Option, Call]>; + /** + * Anonymously schedule a task after a delay. + * + * # + * Same as [`schedule`]. + * # + **/ + scheduleAfter: AugmentedSubmittable<(after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: Call | IMethod | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, Option, Call]>; + /** * Schedule a named task. + * + * Only `T::ScheduleOrigin` is allowed to schedule a task. + * Only `T::PrioritySetOrigin` is allowed to set the task's priority. **/ - scheduleNamed: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array, when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [U8aFixed, u32, Option>, Option, FrameSupportScheduleMaybeHashed]>; + scheduleNamed: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array, when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: Call | IMethod | string | Uint8Array) => SubmittableExtrinsic, [U8aFixed, u32, Option>, Option, Call]>; /** * Schedule a named task after a delay. * + * Only `T::ScheduleOrigin` is allowed to schedule a task. + * Only `T::PrioritySetOrigin` is allowed to set the task's priority. + * * # * Same as [`schedule_named`](Self::schedule_named). * # **/ - scheduleNamedAfter: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array, after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [U8aFixed, u32, Option>, Option, FrameSupportScheduleMaybeHashed]>; + scheduleNamedAfter: AugmentedSubmittable<(id: U8aFixed | string | Uint8Array, after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | Uint8Array | ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array], priority: Option | null | Uint8Array | u8 | AnyNumber, call: Call | IMethod | string | Uint8Array) => SubmittableExtrinsic, [U8aFixed, u32, Option>, Option, Call]>; /** * Generic tx **/ @@ -986,6 +1028,7 @@ [key: string]: SubmittableExtrinsicFunction; }; testUtils: { + batchAll: AugmentedSubmittable<(calls: Vec | (Call | IMethod | string | Uint8Array)[]) => SubmittableExtrinsic, [Vec]>; enable: AugmentedSubmittable<() => SubmittableExtrinsic, []>; incTestValue: AugmentedSubmittable<() => SubmittableExtrinsic, []>; justTakeFee: AugmentedSubmittable<() => SubmittableExtrinsic, []>; --- a/tests/src/interfaces/augment-types.ts +++ b/tests/src/interfaces/augment-types.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default'; +import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default'; import type { Data, StorageKey } from '@polkadot/types'; import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec'; import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets'; @@ -526,8 +526,6 @@ FrameSupportDispatchPerDispatchClassWeightsPerClass: FrameSupportDispatchPerDispatchClassWeightsPerClass; FrameSupportDispatchRawOrigin: FrameSupportDispatchRawOrigin; FrameSupportPalletId: FrameSupportPalletId; - FrameSupportScheduleLookupError: FrameSupportScheduleLookupError; - FrameSupportScheduleMaybeHashed: FrameSupportScheduleMaybeHashed; FrameSupportTokensMiscBalanceStatus: FrameSupportTokensMiscBalanceStatus; FrameSystemAccountInfo: FrameSystemAccountInfo; FrameSystemCall: FrameSystemCall; @@ -854,6 +852,7 @@ PalletEvmEvent: PalletEvmEvent; PalletEvmMigrationCall: PalletEvmMigrationCall; PalletEvmMigrationError: PalletEvmMigrationError; + PalletEvmMigrationEvent: PalletEvmMigrationEvent; PalletForeignAssetsAssetIds: PalletForeignAssetsAssetIds; PalletForeignAssetsModuleAssetMetadata: PalletForeignAssetsModuleAssetMetadata; PalletForeignAssetsModuleCall: PalletForeignAssetsModuleCall; @@ -902,10 +901,12 @@ PalletUniqueCall: PalletUniqueCall; PalletUniqueError: PalletUniqueError; PalletUniqueRawEvent: PalletUniqueRawEvent; - PalletUniqueSchedulerCall: PalletUniqueSchedulerCall; - PalletUniqueSchedulerError: PalletUniqueSchedulerError; - PalletUniqueSchedulerEvent: PalletUniqueSchedulerEvent; - PalletUniqueSchedulerScheduledV3: PalletUniqueSchedulerScheduledV3; + PalletUniqueSchedulerV2BlockAgenda: PalletUniqueSchedulerV2BlockAgenda; + PalletUniqueSchedulerV2Call: PalletUniqueSchedulerV2Call; + PalletUniqueSchedulerV2Error: PalletUniqueSchedulerV2Error; + PalletUniqueSchedulerV2Event: PalletUniqueSchedulerV2Event; + PalletUniqueSchedulerV2Scheduled: PalletUniqueSchedulerV2Scheduled; + PalletUniqueSchedulerV2ScheduledCall: PalletUniqueSchedulerV2ScheduledCall; PalletVersion: PalletVersion; PalletXcmCall: PalletXcmCall; PalletXcmError: PalletXcmError; --- a/tests/src/interfaces/default/types.ts +++ b/tests/src/interfaces/default/types.ts @@ -556,22 +556,6 @@ /** @name FrameSupportPalletId */ export interface FrameSupportPalletId extends U8aFixed {} -/** @name FrameSupportScheduleLookupError */ -export interface FrameSupportScheduleLookupError extends Enum { - readonly isUnknown: boolean; - readonly isBadFormat: boolean; - readonly type: 'Unknown' | 'BadFormat'; -} - -/** @name FrameSupportScheduleMaybeHashed */ -export interface FrameSupportScheduleMaybeHashed extends Enum { - readonly isValue: boolean; - readonly asValue: Call; - readonly isHash: boolean; - readonly asHash: H256; - readonly type: 'Value' | 'Hash'; -} - /** @name FrameSupportTokensMiscBalanceStatus */ export interface FrameSupportTokensMiscBalanceStatus extends Enum { readonly isFree: boolean; @@ -1347,7 +1331,12 @@ /** @name PalletEthereumEvent */ export interface PalletEthereumEvent extends Enum { readonly isExecuted: boolean; - readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>; + readonly asExecuted: { + readonly from: H160; + readonly to: H160; + readonly transactionHash: H256; + readonly exitReason: EvmCoreErrorExitReason; + } & Struct; readonly type: 'Executed'; } @@ -1457,26 +1446,36 @@ readonly isWithdrawFailed: boolean; readonly isGasPriceTooLow: boolean; readonly isInvalidNonce: boolean; - readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce'; + readonly isGasLimitTooLow: boolean; + readonly isGasLimitTooHigh: boolean; + readonly isUndefined: boolean; + readonly isReentrancy: boolean; + readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy'; } /** @name PalletEvmEvent */ export interface PalletEvmEvent extends Enum { readonly isLog: boolean; - readonly asLog: EthereumLog; + readonly asLog: { + readonly log: EthereumLog; + } & Struct; readonly isCreated: boolean; - readonly asCreated: H160; + readonly asCreated: { + readonly address: H160; + } & Struct; readonly isCreatedFailed: boolean; - readonly asCreatedFailed: H160; + readonly asCreatedFailed: { + readonly address: H160; + } & Struct; readonly isExecuted: boolean; - readonly asExecuted: H160; + readonly asExecuted: { + readonly address: H160; + } & Struct; readonly isExecutedFailed: boolean; - readonly asExecutedFailed: H160; - readonly isBalanceDeposit: boolean; - readonly asBalanceDeposit: ITuple<[AccountId32, H160, U256]>; - readonly isBalanceWithdraw: boolean; - readonly asBalanceWithdraw: ITuple<[AccountId32, H160, U256]>; - readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw'; + readonly asExecutedFailed: { + readonly address: H160; + } & Struct; + readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed'; } /** @name PalletEvmMigrationCall */ @@ -1495,16 +1494,31 @@ readonly address: H160; readonly code: Bytes; } & Struct; - readonly type: 'Begin' | 'SetData' | 'Finish'; + readonly isInsertEthLogs: boolean; + readonly asInsertEthLogs: { + readonly logs: Vec; + } & Struct; + readonly isInsertEvents: boolean; + readonly asInsertEvents: { + readonly events: Vec; + } & Struct; + readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents'; } /** @name PalletEvmMigrationError */ export interface PalletEvmMigrationError extends Enum { readonly isAccountNotEmpty: boolean; readonly isAccountIsNotMigrating: boolean; - readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating'; + readonly isBadEvent: boolean; + readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating' | 'BadEvent'; } +/** @name PalletEvmMigrationEvent */ +export interface PalletEvmMigrationEvent extends Enum { + readonly isTestEvent: boolean; + readonly type: 'TestEvent'; +} + /** @name PalletForeignAssetsAssetIds */ export interface PalletForeignAssetsAssetIds extends Enum { readonly isForeignAssetId: boolean; @@ -2004,7 +2018,11 @@ readonly maxTestValue: u32; } & Struct; readonly isJustTakeFee: boolean; - readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'SelfCancelingInc' | 'JustTakeFee'; + readonly isBatchAll: boolean; + readonly asBatchAll: { + readonly calls: Vec; + } & Struct; + readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'SelfCancelingInc' | 'JustTakeFee' | 'BatchAll'; } /** @name PalletTestUtilsError */ @@ -2018,7 +2036,8 @@ export interface PalletTestUtilsEvent extends Enum { readonly isValueIsSet: boolean; readonly isShouldRollback: boolean; - readonly type: 'ValueIsSet' | 'ShouldRollback'; + readonly isBatchCompleted: boolean; + readonly type: 'ValueIsSet' | 'ShouldRollback' | 'BatchCompleted'; } /** @name PalletTimestampCall */ @@ -2327,47 +2346,76 @@ readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet'; } -/** @name PalletUniqueSchedulerCall */ -export interface PalletUniqueSchedulerCall extends Enum { +/** @name PalletUniqueSchedulerV2BlockAgenda */ +export interface PalletUniqueSchedulerV2BlockAgenda extends Struct { + readonly agenda: Vec>; + readonly freePlaces: u32; +} + +/** @name PalletUniqueSchedulerV2Call */ +export interface PalletUniqueSchedulerV2Call extends Enum { + readonly isSchedule: boolean; + readonly asSchedule: { + readonly when: u32; + readonly maybePeriodic: Option>; + readonly priority: Option; + readonly call: Call; + } & Struct; + readonly isCancel: boolean; + readonly asCancel: { + readonly when: u32; + readonly index: u32; + } & Struct; readonly isScheduleNamed: boolean; readonly asScheduleNamed: { readonly id: U8aFixed; readonly when: u32; readonly maybePeriodic: Option>; readonly priority: Option; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: Call; } & Struct; readonly isCancelNamed: boolean; readonly asCancelNamed: { readonly id: U8aFixed; } & Struct; + readonly isScheduleAfter: boolean; + readonly asScheduleAfter: { + readonly after: u32; + readonly maybePeriodic: Option>; + readonly priority: Option; + readonly call: Call; + } & Struct; readonly isScheduleNamedAfter: boolean; readonly asScheduleNamedAfter: { readonly id: U8aFixed; readonly after: u32; readonly maybePeriodic: Option>; readonly priority: Option; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: Call; } & Struct; readonly isChangeNamedPriority: boolean; readonly asChangeNamedPriority: { readonly id: U8aFixed; readonly priority: u8; } & Struct; - readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter' | 'ChangeNamedPriority'; + readonly type: 'Schedule' | 'Cancel' | 'ScheduleNamed' | 'CancelNamed' | 'ScheduleAfter' | 'ScheduleNamedAfter' | 'ChangeNamedPriority'; } -/** @name PalletUniqueSchedulerError */ -export interface PalletUniqueSchedulerError extends Enum { +/** @name PalletUniqueSchedulerV2Error */ +export interface PalletUniqueSchedulerV2Error extends Enum { readonly isFailedToSchedule: boolean; + readonly isAgendaIsExhausted: boolean; + readonly isScheduledCallCorrupted: boolean; + readonly isPreimageNotFound: boolean; + readonly isTooBigScheduledCall: boolean; readonly isNotFound: boolean; readonly isTargetBlockNumberInPast: boolean; - readonly isRescheduleNoChange: boolean; - readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange'; + readonly isNamed: boolean; + readonly type: 'FailedToSchedule' | 'AgendaIsExhausted' | 'ScheduledCallCorrupted' | 'PreimageNotFound' | 'TooBigScheduledCall' | 'NotFound' | 'TargetBlockNumberInPast' | 'Named'; } -/** @name PalletUniqueSchedulerEvent */ -export interface PalletUniqueSchedulerEvent extends Enum { +/** @name PalletUniqueSchedulerV2Event */ +export interface PalletUniqueSchedulerV2Event extends Enum { readonly isScheduled: boolean; readonly asScheduled: { readonly when: u32; @@ -2378,36 +2426,51 @@ readonly when: u32; readonly index: u32; } & Struct; + readonly isDispatched: boolean; + readonly asDispatched: { + readonly task: ITuple<[u32, u32]>; + readonly id: Option; + readonly result: Result; + } & Struct; readonly isPriorityChanged: boolean; readonly asPriorityChanged: { - readonly when: u32; - readonly index: u32; + readonly task: ITuple<[u32, u32]>; readonly priority: u8; } & Struct; - readonly isDispatched: boolean; - readonly asDispatched: { + readonly isCallUnavailable: boolean; + readonly asCallUnavailable: { readonly task: ITuple<[u32, u32]>; readonly id: Option; - readonly result: Result; } & Struct; - readonly isCallLookupFailed: boolean; - readonly asCallLookupFailed: { + readonly isPermanentlyOverweight: boolean; + readonly asPermanentlyOverweight: { readonly task: ITuple<[u32, u32]>; readonly id: Option; - readonly error: FrameSupportScheduleLookupError; } & Struct; - readonly type: 'Scheduled' | 'Canceled' | 'PriorityChanged' | 'Dispatched' | 'CallLookupFailed'; + readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'PriorityChanged' | 'CallUnavailable' | 'PermanentlyOverweight'; } -/** @name PalletUniqueSchedulerScheduledV3 */ -export interface PalletUniqueSchedulerScheduledV3 extends Struct { +/** @name PalletUniqueSchedulerV2Scheduled */ +export interface PalletUniqueSchedulerV2Scheduled extends Struct { readonly maybeId: Option; readonly priority: u8; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: PalletUniqueSchedulerV2ScheduledCall; readonly maybePeriodic: Option>; readonly origin: OpalRuntimeOriginCaller; } +/** @name PalletUniqueSchedulerV2ScheduledCall */ +export interface PalletUniqueSchedulerV2ScheduledCall extends Enum { + readonly isInline: boolean; + readonly asInline: Bytes; + readonly isPreimageLookup: boolean; + readonly asPreimageLookup: { + readonly hash_: H256; + readonly unboundedLen: u32; + } & Struct; + readonly type: 'Inline' | 'PreimageLookup'; +} + /** @name PalletXcmCall */ export interface PalletXcmCall extends Enum { readonly isSend: boolean; --- a/tests/src/interfaces/lookup.ts +++ b/tests/src/interfaces/lookup.ts @@ -1004,9 +1004,9 @@ } }, /** - * Lookup93: pallet_unique_scheduler::pallet::Event + * Lookup93: pallet_unique_scheduler_v2::pallet::Event **/ - PalletUniqueSchedulerEvent: { + PalletUniqueSchedulerV2Event: { _enum: { Scheduled: { when: 'u32', @@ -1016,31 +1016,27 @@ when: 'u32', index: 'u32', }, + Dispatched: { + task: '(u32,u32)', + id: 'Option<[u8;32]>', + result: 'Result', + }, PriorityChanged: { - when: 'u32', - index: 'u32', + task: '(u32,u32)', priority: 'u8', }, - Dispatched: { + CallUnavailable: { task: '(u32,u32)', - id: 'Option<[u8;16]>', - result: 'Result', + id: 'Option<[u8;32]>', }, - CallLookupFailed: { + PermanentlyOverweight: { task: '(u32,u32)', - id: 'Option<[u8;16]>', - error: 'FrameSupportScheduleLookupError' + id: 'Option<[u8;32]>' } } }, /** - * Lookup96: frame_support::traits::schedule::LookupError - **/ - FrameSupportScheduleLookupError: { - _enum: ['Unknown', 'BadFormat'] - }, - /** - * Lookup97: pallet_common::pallet::Event + * Lookup96: pallet_common::pallet::Event **/ PalletCommonEvent: { _enum: { @@ -1058,7 +1054,7 @@ } }, /** - * Lookup100: pallet_structure::pallet::Event + * Lookup99: pallet_structure::pallet::Event **/ PalletStructureEvent: { _enum: { @@ -1066,7 +1062,7 @@ } }, /** - * Lookup101: pallet_rmrk_core::pallet::Event + * Lookup100: pallet_rmrk_core::pallet::Event **/ PalletRmrkCoreEvent: { _enum: { @@ -1143,7 +1139,7 @@ } }, /** - * Lookup102: rmrk_traits::nft::AccountIdOrCollectionNftTuple + * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple **/ RmrkTraitsNftAccountIdOrCollectionNftTuple: { _enum: { @@ -1152,7 +1148,7 @@ } }, /** - * Lookup107: pallet_rmrk_equip::pallet::Event + * Lookup106: pallet_rmrk_equip::pallet::Event **/ PalletRmrkEquipEvent: { _enum: { @@ -1167,7 +1163,7 @@ } }, /** - * Lookup108: pallet_app_promotion::pallet::Event + * Lookup107: pallet_app_promotion::pallet::Event **/ PalletAppPromotionEvent: { _enum: { @@ -1178,7 +1174,7 @@ } }, /** - * Lookup109: pallet_foreign_assets::module::Event + * Lookup108: pallet_foreign_assets::module::Event **/ PalletForeignAssetsModuleEvent: { _enum: { @@ -1203,7 +1199,7 @@ } }, /** - * Lookup110: pallet_foreign_assets::module::AssetMetadata + * Lookup109: pallet_foreign_assets::module::AssetMetadata **/ PalletForeignAssetsModuleAssetMetadata: { name: 'Bytes', @@ -1212,21 +1208,29 @@ minimalBalance: 'u128' }, /** - * Lookup111: pallet_evm::pallet::Event + * Lookup110: pallet_evm::pallet::Event **/ PalletEvmEvent: { _enum: { - Log: 'EthereumLog', - Created: 'H160', - CreatedFailed: 'H160', - Executed: 'H160', - ExecutedFailed: 'H160', - BalanceDeposit: '(AccountId32,H160,U256)', - BalanceWithdraw: '(AccountId32,H160,U256)' + Log: { + log: 'EthereumLog', + }, + Created: { + address: 'H160', + }, + CreatedFailed: { + address: 'H160', + }, + Executed: { + address: 'H160', + }, + ExecutedFailed: { + address: 'H160' + } } }, /** - * Lookup112: ethereum::log::Log + * Lookup111: ethereum::log::Log **/ EthereumLog: { address: 'H160', @@ -1234,15 +1238,20 @@ data: 'Bytes' }, /** - * Lookup116: pallet_ethereum::pallet::Event + * Lookup113: pallet_ethereum::pallet::Event **/ PalletEthereumEvent: { _enum: { - Executed: '(H160,H160,H256,EvmCoreErrorExitReason)' + Executed: { + from: 'H160', + to: 'H160', + transactionHash: 'H256', + exitReason: 'EvmCoreErrorExitReason' + } } }, /** - * Lookup117: evm_core::error::ExitReason + * Lookup114: evm_core::error::ExitReason **/ EvmCoreErrorExitReason: { _enum: { @@ -1253,13 +1262,13 @@ } }, /** - * Lookup118: evm_core::error::ExitSucceed + * Lookup115: evm_core::error::ExitSucceed **/ EvmCoreErrorExitSucceed: { _enum: ['Stopped', 'Returned', 'Suicided'] }, /** - * Lookup119: evm_core::error::ExitError + * Lookup116: evm_core::error::ExitError **/ EvmCoreErrorExitError: { _enum: { @@ -1281,13 +1290,13 @@ } }, /** - * Lookup122: evm_core::error::ExitRevert + * Lookup119: evm_core::error::ExitRevert **/ EvmCoreErrorExitRevert: { _enum: ['Reverted'] }, /** - * Lookup123: evm_core::error::ExitFatal + * Lookup120: evm_core::error::ExitFatal **/ EvmCoreErrorExitFatal: { _enum: { @@ -1298,7 +1307,7 @@ } }, /** - * Lookup124: pallet_evm_contract_helpers::pallet::Event + * Lookup121: pallet_evm_contract_helpers::pallet::Event **/ PalletEvmContractHelpersEvent: { _enum: { @@ -1308,19 +1317,25 @@ } }, /** - * Lookup125: pallet_maintenance::pallet::Event + * Lookup122: pallet_evm_migration::pallet::Event + **/ + PalletEvmMigrationEvent: { + _enum: ['TestEvent'] + }, + /** + * Lookup123: pallet_maintenance::pallet::Event **/ PalletMaintenanceEvent: { _enum: ['MaintenanceEnabled', 'MaintenanceDisabled'] }, /** - * Lookup126: pallet_test_utils::pallet::Event + * Lookup124: pallet_test_utils::pallet::Event **/ PalletTestUtilsEvent: { - _enum: ['ValueIsSet', 'ShouldRollback'] + _enum: ['ValueIsSet', 'ShouldRollback', 'BatchCompleted'] }, /** - * Lookup127: frame_system::Phase + * Lookup125: frame_system::Phase **/ FrameSystemPhase: { _enum: { @@ -1330,14 +1345,14 @@ } }, /** - * Lookup129: frame_system::LastRuntimeUpgradeInfo + * Lookup127: frame_system::LastRuntimeUpgradeInfo **/ FrameSystemLastRuntimeUpgradeInfo: { specVersion: 'Compact', specName: 'Text' }, /** - * Lookup130: frame_system::pallet::Call + * Lookup128: frame_system::pallet::Call **/ FrameSystemCall: { _enum: { @@ -1375,7 +1390,7 @@ } }, /** - * Lookup135: frame_system::limits::BlockWeights + * Lookup133: frame_system::limits::BlockWeights **/ FrameSystemLimitsBlockWeights: { baseBlock: 'Weight', @@ -1383,7 +1398,7 @@ perClass: 'FrameSupportDispatchPerDispatchClassWeightsPerClass' }, /** - * Lookup136: frame_support::dispatch::PerDispatchClass + * Lookup134: frame_support::dispatch::PerDispatchClass **/ FrameSupportDispatchPerDispatchClassWeightsPerClass: { normal: 'FrameSystemLimitsWeightsPerClass', @@ -1391,7 +1406,7 @@ mandatory: 'FrameSystemLimitsWeightsPerClass' }, /** - * Lookup137: frame_system::limits::WeightsPerClass + * Lookup135: frame_system::limits::WeightsPerClass **/ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: 'Weight', @@ -1400,13 +1415,13 @@ reserved: 'Option' }, /** - * Lookup139: frame_system::limits::BlockLength + * Lookup137: frame_system::limits::BlockLength **/ FrameSystemLimitsBlockLength: { max: 'FrameSupportDispatchPerDispatchClassU32' }, /** - * Lookup140: frame_support::dispatch::PerDispatchClass + * Lookup138: frame_support::dispatch::PerDispatchClass **/ FrameSupportDispatchPerDispatchClassU32: { normal: 'u32', @@ -1414,14 +1429,14 @@ mandatory: 'u32' }, /** - * Lookup141: sp_weights::RuntimeDbWeight + * Lookup139: sp_weights::RuntimeDbWeight **/ SpWeightsRuntimeDbWeight: { read: 'u64', write: 'u64' }, /** - * Lookup142: sp_version::RuntimeVersion + * Lookup140: sp_version::RuntimeVersion **/ SpVersionRuntimeVersion: { specName: 'Text', @@ -1434,13 +1449,13 @@ stateVersion: 'u8' }, /** - * Lookup147: frame_system::pallet::Error + * Lookup145: frame_system::pallet::Error **/ FrameSystemError: { _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered'] }, /** - * Lookup148: polkadot_primitives::v2::PersistedValidationData + * Lookup146: polkadot_primitives::v2::PersistedValidationData **/ PolkadotPrimitivesV2PersistedValidationData: { parentHead: 'Bytes', @@ -1449,19 +1464,19 @@ maxPovSize: 'u32' }, /** - * Lookup151: polkadot_primitives::v2::UpgradeRestriction + * Lookup149: polkadot_primitives::v2::UpgradeRestriction **/ PolkadotPrimitivesV2UpgradeRestriction: { _enum: ['Present'] }, /** - * Lookup152: sp_trie::storage_proof::StorageProof + * Lookup150: sp_trie::storage_proof::StorageProof **/ SpTrieStorageProof: { trieNodes: 'BTreeSet' }, /** - * Lookup154: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot + * Lookup152: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot **/ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: 'H256', @@ -1470,7 +1485,7 @@ egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>' }, /** - * Lookup157: polkadot_primitives::v2::AbridgedHrmpChannel + * Lookup155: polkadot_primitives::v2::AbridgedHrmpChannel **/ PolkadotPrimitivesV2AbridgedHrmpChannel: { maxCapacity: 'u32', @@ -1481,7 +1496,7 @@ mqcHead: 'Option' }, /** - * Lookup158: polkadot_primitives::v2::AbridgedHostConfiguration + * Lookup156: polkadot_primitives::v2::AbridgedHostConfiguration **/ PolkadotPrimitivesV2AbridgedHostConfiguration: { maxCodeSize: 'u32', @@ -1495,14 +1510,14 @@ validationUpgradeDelay: 'u32' }, /** - * Lookup164: polkadot_core_primitives::OutboundHrmpMessage + * Lookup162: polkadot_core_primitives::OutboundHrmpMessage **/ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: 'u32', data: 'Bytes' }, /** - * Lookup165: cumulus_pallet_parachain_system::pallet::Call + * Lookup163: cumulus_pallet_parachain_system::pallet::Call **/ CumulusPalletParachainSystemCall: { _enum: { @@ -1521,7 +1536,7 @@ } }, /** - * Lookup166: cumulus_primitives_parachain_inherent::ParachainInherentData + * Lookup164: cumulus_primitives_parachain_inherent::ParachainInherentData **/ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: 'PolkadotPrimitivesV2PersistedValidationData', @@ -1530,27 +1545,27 @@ horizontalMessages: 'BTreeMap>' }, /** - * Lookup168: polkadot_core_primitives::InboundDownwardMessage + * Lookup166: polkadot_core_primitives::InboundDownwardMessage **/ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: 'u32', msg: 'Bytes' }, /** - * Lookup171: polkadot_core_primitives::InboundHrmpMessage + * Lookup169: polkadot_core_primitives::InboundHrmpMessage **/ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: 'u32', data: 'Bytes' }, /** - * Lookup174: cumulus_pallet_parachain_system::pallet::Error + * Lookup172: cumulus_pallet_parachain_system::pallet::Error **/ CumulusPalletParachainSystemError: { _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized'] }, /** - * Lookup176: pallet_balances::BalanceLock + * Lookup174: pallet_balances::BalanceLock **/ PalletBalancesBalanceLock: { id: '[u8;8]', @@ -1558,26 +1573,26 @@ reasons: 'PalletBalancesReasons' }, /** - * Lookup177: pallet_balances::Reasons + * Lookup175: pallet_balances::Reasons **/ PalletBalancesReasons: { _enum: ['Fee', 'Misc', 'All'] }, /** - * Lookup180: pallet_balances::ReserveData + * Lookup178: pallet_balances::ReserveData **/ PalletBalancesReserveData: { id: '[u8;16]', amount: 'u128' }, /** - * Lookup182: pallet_balances::Releases + * Lookup180: pallet_balances::Releases **/ PalletBalancesReleases: { _enum: ['V1_0_0', 'V2_0_0'] }, /** - * Lookup183: pallet_balances::pallet::Call + * Lookup181: pallet_balances::pallet::Call **/ PalletBalancesCall: { _enum: { @@ -1610,13 +1625,13 @@ } }, /** - * Lookup186: pallet_balances::pallet::Error + * Lookup184: pallet_balances::pallet::Error **/ PalletBalancesError: { _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves'] }, /** - * Lookup188: pallet_timestamp::pallet::Call + * Lookup186: pallet_timestamp::pallet::Call **/ PalletTimestampCall: { _enum: { @@ -1626,13 +1641,13 @@ } }, /** - * Lookup190: pallet_transaction_payment::Releases + * Lookup188: pallet_transaction_payment::Releases **/ PalletTransactionPaymentReleases: { _enum: ['V1Ancient', 'V2'] }, /** - * Lookup191: pallet_treasury::Proposal + * Lookup189: pallet_treasury::Proposal **/ PalletTreasuryProposal: { proposer: 'AccountId32', @@ -1641,7 +1656,7 @@ bond: 'u128' }, /** - * Lookup194: pallet_treasury::pallet::Call + * Lookup192: pallet_treasury::pallet::Call **/ PalletTreasuryCall: { _enum: { @@ -1665,17 +1680,17 @@ } }, /** - * Lookup197: frame_support::PalletId + * Lookup195: frame_support::PalletId **/ FrameSupportPalletId: '[u8;8]', /** - * Lookup198: pallet_treasury::pallet::Error + * Lookup196: pallet_treasury::pallet::Error **/ PalletTreasuryError: { _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved'] }, /** - * Lookup199: pallet_sudo::pallet::Call + * Lookup197: pallet_sudo::pallet::Call **/ PalletSudoCall: { _enum: { @@ -1699,7 +1714,7 @@ } }, /** - * Lookup201: orml_vesting::module::Call + * Lookup199: orml_vesting::module::Call **/ OrmlVestingModuleCall: { _enum: { @@ -1718,7 +1733,7 @@ } }, /** - * Lookup203: orml_xtokens::module::Call + * Lookup201: orml_xtokens::module::Call **/ OrmlXtokensModuleCall: { _enum: { @@ -1761,7 +1776,7 @@ } }, /** - * Lookup204: xcm::VersionedMultiAsset + * Lookup202: xcm::VersionedMultiAsset **/ XcmVersionedMultiAsset: { _enum: { @@ -1770,7 +1785,7 @@ } }, /** - * Lookup207: orml_tokens::module::Call + * Lookup205: orml_tokens::module::Call **/ OrmlTokensModuleCall: { _enum: { @@ -1804,7 +1819,7 @@ } }, /** - * Lookup208: cumulus_pallet_xcmp_queue::pallet::Call + * Lookup206: cumulus_pallet_xcmp_queue::pallet::Call **/ CumulusPalletXcmpQueueCall: { _enum: { @@ -1853,7 +1868,7 @@ } }, /** - * Lookup209: pallet_xcm::pallet::Call + * Lookup207: pallet_xcm::pallet::Call **/ PalletXcmCall: { _enum: { @@ -1907,7 +1922,7 @@ } }, /** - * Lookup210: xcm::VersionedXcm + * Lookup208: xcm::VersionedXcm **/ XcmVersionedXcm: { _enum: { @@ -1917,7 +1932,7 @@ } }, /** - * Lookup211: xcm::v0::Xcm + * Lookup209: xcm::v0::Xcm **/ XcmV0Xcm: { _enum: { @@ -1971,7 +1986,7 @@ } }, /** - * Lookup213: xcm::v0::order::Order + * Lookup211: xcm::v0::order::Order **/ XcmV0Order: { _enum: { @@ -2014,7 +2029,7 @@ } }, /** - * Lookup215: xcm::v0::Response + * Lookup213: xcm::v0::Response **/ XcmV0Response: { _enum: { @@ -2022,7 +2037,7 @@ } }, /** - * Lookup216: xcm::v1::Xcm + * Lookup214: xcm::v1::Xcm **/ XcmV1Xcm: { _enum: { @@ -2081,7 +2096,7 @@ } }, /** - * Lookup218: xcm::v1::order::Order + * Lookup216: xcm::v1::order::Order **/ XcmV1Order: { _enum: { @@ -2126,7 +2141,7 @@ } }, /** - * Lookup220: xcm::v1::Response + * Lookup218: xcm::v1::Response **/ XcmV1Response: { _enum: { @@ -2135,11 +2150,11 @@ } }, /** - * Lookup234: cumulus_pallet_xcm::pallet::Call + * Lookup232: cumulus_pallet_xcm::pallet::Call **/ CumulusPalletXcmCall: 'Null', /** - * Lookup235: cumulus_pallet_dmp_queue::pallet::Call + * Lookup233: cumulus_pallet_dmp_queue::pallet::Call **/ CumulusPalletDmpQueueCall: { _enum: { @@ -2150,7 +2165,7 @@ } }, /** - * Lookup236: pallet_inflation::pallet::Call + * Lookup234: pallet_inflation::pallet::Call **/ PalletInflationCall: { _enum: { @@ -2160,7 +2175,7 @@ } }, /** - * Lookup237: pallet_unique::Call + * Lookup235: pallet_unique::Call **/ PalletUniqueCall: { _enum: { @@ -2292,7 +2307,7 @@ } }, /** - * Lookup242: up_data_structs::CollectionMode + * Lookup240: up_data_structs::CollectionMode **/ UpDataStructsCollectionMode: { _enum: { @@ -2302,7 +2317,7 @@ } }, /** - * Lookup243: up_data_structs::CreateCollectionData + * Lookup241: up_data_structs::CreateCollectionData **/ UpDataStructsCreateCollectionData: { mode: 'UpDataStructsCollectionMode', @@ -2317,13 +2332,13 @@ properties: 'Vec' }, /** - * Lookup245: up_data_structs::AccessMode + * Lookup243: up_data_structs::AccessMode **/ UpDataStructsAccessMode: { _enum: ['Normal', 'AllowList'] }, /** - * Lookup247: up_data_structs::CollectionLimits + * Lookup245: up_data_structs::CollectionLimits **/ UpDataStructsCollectionLimits: { accountTokenOwnershipLimit: 'Option', @@ -2337,7 +2352,7 @@ transfersEnabled: 'Option' }, /** - * Lookup249: up_data_structs::SponsoringRateLimit + * Lookup247: up_data_structs::SponsoringRateLimit **/ UpDataStructsSponsoringRateLimit: { _enum: { @@ -2346,7 +2361,7 @@ } }, /** - * Lookup252: up_data_structs::CollectionPermissions + * Lookup250: up_data_structs::CollectionPermissions **/ UpDataStructsCollectionPermissions: { access: 'Option', @@ -2354,7 +2369,7 @@ nesting: 'Option' }, /** - * Lookup254: up_data_structs::NestingPermissions + * Lookup252: up_data_structs::NestingPermissions **/ UpDataStructsNestingPermissions: { tokenOwner: 'bool', @@ -2362,18 +2377,18 @@ restricted: 'Option' }, /** - * Lookup256: up_data_structs::OwnerRestrictedSet + * Lookup254: up_data_structs::OwnerRestrictedSet **/ UpDataStructsOwnerRestrictedSet: 'BTreeSet', /** - * Lookup261: up_data_structs::PropertyKeyPermission + * Lookup259: up_data_structs::PropertyKeyPermission **/ UpDataStructsPropertyKeyPermission: { key: 'Bytes', permission: 'UpDataStructsPropertyPermission' }, /** - * Lookup262: up_data_structs::PropertyPermission + * Lookup260: up_data_structs::PropertyPermission **/ UpDataStructsPropertyPermission: { mutable: 'bool', @@ -2381,14 +2396,14 @@ tokenOwner: 'bool' }, /** - * Lookup265: up_data_structs::Property + * Lookup263: up_data_structs::Property **/ UpDataStructsProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup268: up_data_structs::CreateItemData + * Lookup266: up_data_structs::CreateItemData **/ UpDataStructsCreateItemData: { _enum: { @@ -2398,26 +2413,26 @@ } }, /** - * Lookup269: up_data_structs::CreateNftData + * Lookup267: up_data_structs::CreateNftData **/ UpDataStructsCreateNftData: { properties: 'Vec' }, /** - * Lookup270: up_data_structs::CreateFungibleData + * Lookup268: up_data_structs::CreateFungibleData **/ UpDataStructsCreateFungibleData: { value: 'u128' }, /** - * Lookup271: up_data_structs::CreateReFungibleData + * Lookup269: up_data_structs::CreateReFungibleData **/ UpDataStructsCreateReFungibleData: { pieces: 'u128', properties: 'Vec' }, /** - * Lookup274: up_data_structs::CreateItemExData> + * Lookup272: up_data_structs::CreateItemExData> **/ UpDataStructsCreateItemExData: { _enum: { @@ -2428,14 +2443,14 @@ } }, /** - * Lookup276: up_data_structs::CreateNftExData> + * Lookup274: up_data_structs::CreateNftExData> **/ UpDataStructsCreateNftExData: { properties: 'Vec', owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup283: up_data_structs::CreateRefungibleExSingleOwner> + * Lookup281: up_data_structs::CreateRefungibleExSingleOwner> **/ UpDataStructsCreateRefungibleExSingleOwner: { user: 'PalletEvmAccountBasicCrossAccountIdRepr', @@ -2443,51 +2458,58 @@ properties: 'Vec' }, /** - * Lookup285: up_data_structs::CreateRefungibleExMultipleOwners> + * Lookup283: up_data_structs::CreateRefungibleExMultipleOwners> **/ UpDataStructsCreateRefungibleExMultipleOwners: { users: 'BTreeMap', properties: 'Vec' }, /** - * Lookup286: pallet_unique_scheduler::pallet::Call + * Lookup284: pallet_unique_scheduler_v2::pallet::Call **/ - PalletUniqueSchedulerCall: { + PalletUniqueSchedulerV2Call: { _enum: { + schedule: { + when: 'u32', + maybePeriodic: 'Option<(u32,u32)>', + priority: 'Option', + call: 'Call', + }, + cancel: { + when: 'u32', + index: 'u32', + }, schedule_named: { - id: '[u8;16]', + id: '[u8;32]', when: 'u32', maybePeriodic: 'Option<(u32,u32)>', priority: 'Option', - call: 'FrameSupportScheduleMaybeHashed', + call: 'Call', }, cancel_named: { - id: '[u8;16]', + id: '[u8;32]', }, + schedule_after: { + after: 'u32', + maybePeriodic: 'Option<(u32,u32)>', + priority: 'Option', + call: 'Call', + }, schedule_named_after: { - id: '[u8;16]', + id: '[u8;32]', after: 'u32', maybePeriodic: 'Option<(u32,u32)>', priority: 'Option', - call: 'FrameSupportScheduleMaybeHashed', + call: 'Call', }, change_named_priority: { - id: '[u8;16]', + id: '[u8;32]', priority: 'u8' } } }, /** - * Lookup289: frame_support::traits::schedule::MaybeHashed - **/ - FrameSupportScheduleMaybeHashed: { - _enum: { - Value: 'Call', - Hash: 'H256' - } - }, - /** - * Lookup290: pallet_configuration::pallet::Call + * Lookup287: pallet_configuration::pallet::Call **/ PalletConfigurationCall: { _enum: { @@ -2500,15 +2522,15 @@ } }, /** - * Lookup292: pallet_template_transaction_payment::Call + * Lookup289: pallet_template_transaction_payment::Call **/ PalletTemplateTransactionPaymentCall: 'Null', /** - * Lookup293: pallet_structure::pallet::Call + * Lookup290: pallet_structure::pallet::Call **/ PalletStructureCall: 'Null', /** - * Lookup294: pallet_rmrk_core::pallet::Call + * Lookup291: pallet_rmrk_core::pallet::Call **/ PalletRmrkCoreCall: { _enum: { @@ -2599,7 +2621,7 @@ } }, /** - * Lookup300: rmrk_traits::resource::ResourceTypes, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup297: rmrk_traits::resource::ResourceTypes, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceTypes: { _enum: { @@ -2609,7 +2631,7 @@ } }, /** - * Lookup302: rmrk_traits::resource::BasicResource> + * Lookup299: rmrk_traits::resource::BasicResource> **/ RmrkTraitsResourceBasicResource: { src: 'Option', @@ -2618,7 +2640,7 @@ thumb: 'Option' }, /** - * Lookup304: rmrk_traits::resource::ComposableResource, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup301: rmrk_traits::resource::ComposableResource, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceComposableResource: { parts: 'Vec', @@ -2629,7 +2651,7 @@ thumb: 'Option' }, /** - * Lookup305: rmrk_traits::resource::SlotResource> + * Lookup302: rmrk_traits::resource::SlotResource> **/ RmrkTraitsResourceSlotResource: { base: 'u32', @@ -2640,7 +2662,7 @@ thumb: 'Option' }, /** - * Lookup308: pallet_rmrk_equip::pallet::Call + * Lookup305: pallet_rmrk_equip::pallet::Call **/ PalletRmrkEquipCall: { _enum: { @@ -2661,7 +2683,7 @@ } }, /** - * Lookup311: rmrk_traits::part::PartType, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup308: rmrk_traits::part::PartType, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartPartType: { _enum: { @@ -2670,7 +2692,7 @@ } }, /** - * Lookup313: rmrk_traits::part::FixedPart> + * Lookup310: rmrk_traits::part::FixedPart> **/ RmrkTraitsPartFixedPart: { id: 'u32', @@ -2678,7 +2700,7 @@ src: 'Bytes' }, /** - * Lookup314: rmrk_traits::part::SlotPart, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup311: rmrk_traits::part::SlotPart, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartSlotPart: { id: 'u32', @@ -2687,7 +2709,7 @@ z: 'u32' }, /** - * Lookup315: rmrk_traits::part::EquippableList> + * Lookup312: rmrk_traits::part::EquippableList> **/ RmrkTraitsPartEquippableList: { _enum: { @@ -2697,7 +2719,7 @@ } }, /** - * Lookup317: rmrk_traits::theme::Theme, sp_core::bounded::bounded_vec::BoundedVec>, S>> + * Lookup314: rmrk_traits::theme::Theme, sp_core::bounded::bounded_vec::BoundedVec>, S>> **/ RmrkTraitsTheme: { name: 'Bytes', @@ -2705,14 +2727,14 @@ inherit: 'bool' }, /** - * Lookup319: rmrk_traits::theme::ThemeProperty> + * Lookup316: rmrk_traits::theme::ThemeProperty> **/ RmrkTraitsThemeThemeProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup321: pallet_app_promotion::pallet::Call + * Lookup318: pallet_app_promotion::pallet::Call **/ PalletAppPromotionCall: { _enum: { @@ -2741,7 +2763,7 @@ } }, /** - * Lookup322: pallet_foreign_assets::module::Call + * Lookup319: pallet_foreign_assets::module::Call **/ PalletForeignAssetsModuleCall: { _enum: { @@ -2758,7 +2780,7 @@ } }, /** - * Lookup323: pallet_evm::pallet::Call + * Lookup320: pallet_evm::pallet::Call **/ PalletEvmCall: { _enum: { @@ -2801,7 +2823,7 @@ } }, /** - * Lookup327: pallet_ethereum::pallet::Call + * Lookup326: pallet_ethereum::pallet::Call **/ PalletEthereumCall: { _enum: { @@ -2811,7 +2833,7 @@ } }, /** - * Lookup328: ethereum::transaction::TransactionV2 + * Lookup327: ethereum::transaction::TransactionV2 **/ EthereumTransactionTransactionV2: { _enum: { @@ -2821,7 +2843,7 @@ } }, /** - * Lookup329: ethereum::transaction::LegacyTransaction + * Lookup328: ethereum::transaction::LegacyTransaction **/ EthereumTransactionLegacyTransaction: { nonce: 'U256', @@ -2833,7 +2855,7 @@ signature: 'EthereumTransactionTransactionSignature' }, /** - * Lookup330: ethereum::transaction::TransactionAction + * Lookup329: ethereum::transaction::TransactionAction **/ EthereumTransactionTransactionAction: { _enum: { @@ -2842,7 +2864,7 @@ } }, /** - * Lookup331: ethereum::transaction::TransactionSignature + * Lookup330: ethereum::transaction::TransactionSignature **/ EthereumTransactionTransactionSignature: { v: 'u64', @@ -2850,7 +2872,7 @@ s: 'H256' }, /** - * Lookup333: ethereum::transaction::EIP2930Transaction + * Lookup332: ethereum::transaction::EIP2930Transaction **/ EthereumTransactionEip2930Transaction: { chainId: 'u64', @@ -2866,14 +2888,14 @@ s: 'H256' }, /** - * Lookup335: ethereum::transaction::AccessListItem + * Lookup334: ethereum::transaction::AccessListItem **/ EthereumTransactionAccessListItem: { address: 'H160', storageKeys: 'Vec' }, /** - * Lookup336: ethereum::transaction::EIP1559Transaction + * Lookup335: ethereum::transaction::EIP1559Transaction **/ EthereumTransactionEip1559Transaction: { chainId: 'u64', @@ -2890,7 +2912,7 @@ s: 'H256' }, /** - * Lookup337: pallet_evm_migration::pallet::Call + * Lookup336: pallet_evm_migration::pallet::Call **/ PalletEvmMigrationCall: { _enum: { @@ -2903,7 +2925,13 @@ }, finish: { address: 'H160', - code: 'Bytes' + code: 'Bytes', + }, + insert_eth_logs: { + logs: 'Vec', + }, + insert_events: { + events: 'Vec' } } }, @@ -2927,39 +2955,42 @@ }, inc_test_value: 'Null', self_canceling_inc: { - id: '[u8;16]', + id: '[u8;32]', maxTestValue: 'u32', }, - just_take_fee: 'Null' + just_take_fee: 'Null', + batch_all: { + calls: 'Vec' + } } }, /** - * Lookup342: pallet_sudo::pallet::Error + * Lookup343: pallet_sudo::pallet::Error **/ PalletSudoError: { _enum: ['RequireSudo'] }, /** - * Lookup344: orml_vesting::module::Error + * Lookup345: orml_vesting::module::Error **/ OrmlVestingModuleError: { _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded'] }, /** - * Lookup345: orml_xtokens::module::Error + * Lookup346: orml_xtokens::module::Error **/ OrmlXtokensModuleError: { _enum: ['AssetHasNoReserve', 'NotCrossChainTransfer', 'InvalidDest', 'NotCrossChainTransferableCurrency', 'UnweighableMessage', 'XcmExecutionFailed', 'CannotReanchor', 'InvalidAncestry', 'InvalidAsset', 'DestinationNotInvertible', 'BadVersion', 'DistinctReserveForAssetAndFee', 'ZeroFee', 'ZeroAmount', 'TooManyAssetsBeingSent', 'AssetIndexNonExistent', 'FeeNotEnough', 'NotSupportedMultiLocation', 'MinXcmFeeNotDefined'] }, /** - * Lookup348: orml_tokens::BalanceLock + * Lookup349: orml_tokens::BalanceLock **/ OrmlTokensBalanceLock: { id: '[u8;8]', amount: 'u128' }, /** - * Lookup350: orml_tokens::AccountData + * Lookup351: orml_tokens::AccountData **/ OrmlTokensAccountData: { free: 'u128', @@ -2967,20 +2998,20 @@ frozen: 'u128' }, /** - * Lookup352: orml_tokens::ReserveData + * Lookup353: orml_tokens::ReserveData **/ OrmlTokensReserveData: { id: 'Null', amount: 'u128' }, /** - * Lookup354: orml_tokens::module::Error + * Lookup355: orml_tokens::module::Error **/ OrmlTokensModuleError: { _enum: ['BalanceTooLow', 'AmountIntoBalanceFailed', 'LiquidityRestrictions', 'MaxLocksExceeded', 'KeepAlive', 'ExistentialDeposit', 'DeadAccount', 'TooManyReserves'] }, /** - * Lookup356: cumulus_pallet_xcmp_queue::InboundChannelDetails + * Lookup357: cumulus_pallet_xcmp_queue::InboundChannelDetails **/ CumulusPalletXcmpQueueInboundChannelDetails: { sender: 'u32', @@ -2988,19 +3019,19 @@ messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>' }, /** - * Lookup357: cumulus_pallet_xcmp_queue::InboundState + * Lookup358: cumulus_pallet_xcmp_queue::InboundState **/ CumulusPalletXcmpQueueInboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup360: polkadot_parachain::primitives::XcmpMessageFormat + * Lookup361: polkadot_parachain::primitives::XcmpMessageFormat **/ PolkadotParachainPrimitivesXcmpMessageFormat: { _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals'] }, /** - * Lookup363: cumulus_pallet_xcmp_queue::OutboundChannelDetails + * Lookup364: cumulus_pallet_xcmp_queue::OutboundChannelDetails **/ CumulusPalletXcmpQueueOutboundChannelDetails: { recipient: 'u32', @@ -3010,13 +3041,13 @@ lastIndex: 'u16' }, /** - * Lookup364: cumulus_pallet_xcmp_queue::OutboundState + * Lookup365: cumulus_pallet_xcmp_queue::OutboundState **/ CumulusPalletXcmpQueueOutboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup366: cumulus_pallet_xcmp_queue::QueueConfigData + * Lookup367: cumulus_pallet_xcmp_queue::QueueConfigData **/ CumulusPalletXcmpQueueQueueConfigData: { suspendThreshold: 'u32', @@ -3027,29 +3058,29 @@ xcmpMaxIndividualWeight: 'Weight' }, /** - * Lookup368: cumulus_pallet_xcmp_queue::pallet::Error + * Lookup369: cumulus_pallet_xcmp_queue::pallet::Error **/ CumulusPalletXcmpQueueError: { _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit'] }, /** - * Lookup369: pallet_xcm::pallet::Error + * Lookup370: pallet_xcm::pallet::Error **/ PalletXcmError: { _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed'] }, /** - * Lookup370: cumulus_pallet_xcm::pallet::Error + * Lookup371: cumulus_pallet_xcm::pallet::Error **/ CumulusPalletXcmError: 'Null', /** - * Lookup371: cumulus_pallet_dmp_queue::ConfigData + * Lookup372: cumulus_pallet_dmp_queue::ConfigData **/ CumulusPalletDmpQueueConfigData: { maxIndividual: 'Weight' }, /** - * Lookup372: cumulus_pallet_dmp_queue::PageIndexData + * Lookup373: cumulus_pallet_dmp_queue::PageIndexData **/ CumulusPalletDmpQueuePageIndexData: { beginUsed: 'u32', @@ -3057,30 +3088,52 @@ overweightCount: 'u64' }, /** - * Lookup375: cumulus_pallet_dmp_queue::pallet::Error + * Lookup376: cumulus_pallet_dmp_queue::pallet::Error **/ CumulusPalletDmpQueueError: { _enum: ['Unknown', 'OverLimit'] }, /** - * Lookup379: pallet_unique::Error + * Lookup380: pallet_unique::Error **/ PalletUniqueError: { _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection'] }, /** - * Lookup382: pallet_unique_scheduler::ScheduledV3, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> + * Lookup381: pallet_unique_scheduler_v2::BlockAgenda + **/ + PalletUniqueSchedulerV2BlockAgenda: { + agenda: 'Vec>', + freePlaces: 'u32' + }, + /** + * Lookup384: pallet_unique_scheduler_v2::Scheduled, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> **/ - PalletUniqueSchedulerScheduledV3: { - maybeId: 'Option<[u8;16]>', + PalletUniqueSchedulerV2Scheduled: { + maybeId: 'Option<[u8;32]>', priority: 'u8', - call: 'FrameSupportScheduleMaybeHashed', + call: 'PalletUniqueSchedulerV2ScheduledCall', maybePeriodic: 'Option<(u32,u32)>', origin: 'OpalRuntimeOriginCaller' }, /** - * Lookup383: opal_runtime::OriginCaller + * Lookup385: pallet_unique_scheduler_v2::ScheduledCall **/ + PalletUniqueSchedulerV2ScheduledCall: { + _enum: { + Inline: 'Bytes', + PreimageLookup: { + _alias: { + hash_: 'hash', + }, + hash_: 'H256', + unboundedLen: 'u32' + } + } + }, + /** + * Lookup387: opal_runtime::OriginCaller + **/ OpalRuntimeOriginCaller: { _enum: { system: 'FrameSupportDispatchRawOrigin', @@ -3188,7 +3241,7 @@ } }, /** - * Lookup384: frame_support::dispatch::RawOrigin + * Lookup388: frame_support::dispatch::RawOrigin **/ FrameSupportDispatchRawOrigin: { _enum: { @@ -3198,7 +3251,7 @@ } }, /** - * Lookup385: pallet_xcm::pallet::Origin + * Lookup389: pallet_xcm::pallet::Origin **/ PalletXcmOrigin: { _enum: { @@ -3207,7 +3260,7 @@ } }, /** - * Lookup386: cumulus_pallet_xcm::pallet::Origin + * Lookup390: cumulus_pallet_xcm::pallet::Origin **/ CumulusPalletXcmOrigin: { _enum: { @@ -3216,7 +3269,7 @@ } }, /** - * Lookup387: pallet_ethereum::RawOrigin + * Lookup391: pallet_ethereum::RawOrigin **/ PalletEthereumRawOrigin: { _enum: { @@ -3224,17 +3277,17 @@ } }, /** - * Lookup388: sp_core::Void + * Lookup392: sp_core::Void **/ SpCoreVoid: 'Null', /** - * Lookup389: pallet_unique_scheduler::pallet::Error + * Lookup394: pallet_unique_scheduler_v2::pallet::Error **/ - PalletUniqueSchedulerError: { - _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange'] + PalletUniqueSchedulerV2Error: { + _enum: ['FailedToSchedule', 'AgendaIsExhausted', 'ScheduledCallCorrupted', 'PreimageNotFound', 'TooBigScheduledCall', 'NotFound', 'TargetBlockNumberInPast', 'Named'] }, /** - * Lookup390: up_data_structs::Collection + * Lookup395: up_data_structs::Collection **/ UpDataStructsCollection: { owner: 'AccountId32', @@ -3248,7 +3301,7 @@ flags: '[u8;1]' }, /** - * Lookup391: up_data_structs::SponsorshipState + * Lookup396: up_data_structs::SponsorshipState **/ UpDataStructsSponsorshipStateAccountId32: { _enum: { @@ -3258,7 +3311,7 @@ } }, /** - * Lookup393: up_data_structs::Properties + * Lookup398: up_data_structs::Properties **/ UpDataStructsProperties: { map: 'UpDataStructsPropertiesMapBoundedVec', @@ -3266,15 +3319,15 @@ spaceLimit: 'u32' }, /** - * Lookup394: up_data_structs::PropertiesMap> + * Lookup399: up_data_structs::PropertiesMap> **/ UpDataStructsPropertiesMapBoundedVec: 'BTreeMap', /** - * Lookup399: up_data_structs::PropertiesMap + * Lookup404: up_data_structs::PropertiesMap **/ UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap', /** - * Lookup406: up_data_structs::CollectionStats + * Lookup411: up_data_structs::CollectionStats **/ UpDataStructsCollectionStats: { created: 'u32', @@ -3282,18 +3335,18 @@ alive: 'u32' }, /** - * Lookup407: up_data_structs::TokenChild + * Lookup412: up_data_structs::TokenChild **/ UpDataStructsTokenChild: { token: 'u32', collection: 'u32' }, /** - * Lookup408: PhantomType::up_data_structs + * Lookup413: PhantomType::up_data_structs **/ PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]', /** - * Lookup410: up_data_structs::TokenData> + * Lookup415: up_data_structs::TokenData> **/ UpDataStructsTokenData: { properties: 'Vec', @@ -3301,7 +3354,7 @@ pieces: 'u128' }, /** - * Lookup412: up_data_structs::RpcCollection + * Lookup417: up_data_structs::RpcCollection **/ UpDataStructsRpcCollection: { owner: 'AccountId32', @@ -3318,14 +3371,14 @@ flags: 'UpDataStructsRpcCollectionFlags' }, /** - * Lookup413: up_data_structs::RpcCollectionFlags + * Lookup418: up_data_structs::RpcCollectionFlags **/ UpDataStructsRpcCollectionFlags: { foreign: 'bool', erc721metadata: 'bool' }, /** - * Lookup414: rmrk_traits::collection::CollectionInfo, sp_core::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> + * Lookup419: rmrk_traits::collection::CollectionInfo, sp_core::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> **/ RmrkTraitsCollectionCollectionInfo: { issuer: 'AccountId32', @@ -3335,7 +3388,7 @@ nftsCount: 'u32' }, /** - * Lookup415: rmrk_traits::nft::NftInfo> + * Lookup420: rmrk_traits::nft::NftInfo> **/ RmrkTraitsNftNftInfo: { owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple', @@ -3345,14 +3398,14 @@ pending: 'bool' }, /** - * Lookup417: rmrk_traits::nft::RoyaltyInfo + * Lookup422: rmrk_traits::nft::RoyaltyInfo **/ RmrkTraitsNftRoyaltyInfo: { recipient: 'AccountId32', amount: 'Permill' }, /** - * Lookup418: rmrk_traits::resource::ResourceInfo, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup423: rmrk_traits::resource::ResourceInfo, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceInfo: { id: 'u32', @@ -3361,14 +3414,14 @@ pendingRemoval: 'bool' }, /** - * Lookup419: rmrk_traits::property::PropertyInfo, sp_core::bounded::bounded_vec::BoundedVec> + * Lookup424: rmrk_traits::property::PropertyInfo, sp_core::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPropertyPropertyInfo: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup420: rmrk_traits::base::BaseInfo> + * Lookup425: rmrk_traits::base::BaseInfo> **/ RmrkTraitsBaseBaseInfo: { issuer: 'AccountId32', @@ -3376,92 +3429,92 @@ symbol: 'Bytes' }, /** - * Lookup421: rmrk_traits::nft::NftChild + * Lookup426: rmrk_traits::nft::NftChild **/ RmrkTraitsNftNftChild: { collectionId: 'u32', nftId: 'u32' }, /** - * Lookup423: pallet_common::pallet::Error + * Lookup428: pallet_common::pallet::Error **/ PalletCommonError: { _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal'] }, /** - * Lookup425: pallet_fungible::pallet::Error + * Lookup430: pallet_fungible::pallet::Error **/ PalletFungibleError: { _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup426: pallet_refungible::ItemData + * Lookup431: pallet_refungible::ItemData **/ PalletRefungibleItemData: { constData: 'Bytes' }, /** - * Lookup431: pallet_refungible::pallet::Error + * Lookup436: pallet_refungible::pallet::Error **/ PalletRefungibleError: { _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup432: pallet_nonfungible::ItemData> + * Lookup437: pallet_nonfungible::ItemData> **/ PalletNonfungibleItemData: { owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup434: up_data_structs::PropertyScope + * Lookup439: up_data_structs::PropertyScope **/ UpDataStructsPropertyScope: { _enum: ['None', 'Rmrk'] }, /** - * Lookup436: pallet_nonfungible::pallet::Error + * Lookup441: pallet_nonfungible::pallet::Error **/ PalletNonfungibleError: { _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren'] }, /** - * Lookup437: pallet_structure::pallet::Error + * Lookup442: pallet_structure::pallet::Error **/ PalletStructureError: { _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound'] }, /** - * Lookup438: pallet_rmrk_core::pallet::Error + * Lookup443: pallet_rmrk_core::pallet::Error **/ PalletRmrkCoreError: { _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId'] }, /** - * Lookup440: pallet_rmrk_equip::pallet::Error + * Lookup445: pallet_rmrk_equip::pallet::Error **/ PalletRmrkEquipError: { _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart'] }, /** - * Lookup446: pallet_app_promotion::pallet::Error + * Lookup451: pallet_app_promotion::pallet::Error **/ PalletAppPromotionError: { _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation'] }, /** - * Lookup447: pallet_foreign_assets::module::Error + * Lookup452: pallet_foreign_assets::module::Error **/ PalletForeignAssetsModuleError: { _enum: ['BadLocation', 'MultiLocationExisted', 'AssetIdNotExists', 'AssetIdExisted'] }, /** - * Lookup450: pallet_evm::pallet::Error + * Lookup454: pallet_evm::pallet::Error **/ PalletEvmError: { - _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce'] + _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce', 'GasLimitTooLow', 'GasLimitTooHigh', 'Undefined', 'Reentrancy'] }, /** - * Lookup453: fp_rpc::TransactionStatus + * Lookup457: fp_rpc::TransactionStatus **/ FpRpcTransactionStatus: { transactionHash: 'H256', @@ -3473,11 +3526,11 @@ logsBloom: 'EthbloomBloom' }, /** - * Lookup455: ethbloom::Bloom + * Lookup459: ethbloom::Bloom **/ EthbloomBloom: '[u8;256]', /** - * Lookup457: ethereum::receipt::ReceiptV3 + * Lookup461: ethereum::receipt::ReceiptV3 **/ EthereumReceiptReceiptV3: { _enum: { @@ -3487,7 +3540,7 @@ } }, /** - * Lookup458: ethereum::receipt::EIP658ReceiptData + * Lookup462: ethereum::receipt::EIP658ReceiptData **/ EthereumReceiptEip658ReceiptData: { statusCode: 'u8', @@ -3496,7 +3549,7 @@ logs: 'Vec' }, /** - * Lookup459: ethereum::block::Block + * Lookup463: ethereum::block::Block **/ EthereumBlock: { header: 'EthereumHeader', @@ -3504,7 +3557,7 @@ ommers: 'Vec' }, /** - * Lookup460: ethereum::header::Header + * Lookup464: ethereum::header::Header **/ EthereumHeader: { parentHash: 'H256', @@ -3524,23 +3577,23 @@ nonce: 'EthereumTypesHashH64' }, /** - * Lookup461: ethereum_types::hash::H64 + * Lookup465: ethereum_types::hash::H64 **/ EthereumTypesHashH64: '[u8;8]', /** - * Lookup466: pallet_ethereum::pallet::Error + * Lookup470: pallet_ethereum::pallet::Error **/ PalletEthereumError: { _enum: ['InvalidSignature', 'PreLogExists'] }, /** - * Lookup467: pallet_evm_coder_substrate::pallet::Error + * Lookup471: pallet_evm_coder_substrate::pallet::Error **/ PalletEvmCoderSubstrateError: { _enum: ['OutOfGas', 'OutOfFund'] }, /** - * Lookup468: up_data_structs::SponsorshipState> + * Lookup472: up_data_structs::SponsorshipState> **/ UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: { _enum: { @@ -3550,35 +3603,35 @@ } }, /** - * Lookup469: pallet_evm_contract_helpers::SponsoringModeT + * Lookup473: pallet_evm_contract_helpers::SponsoringModeT **/ PalletEvmContractHelpersSponsoringModeT: { _enum: ['Disabled', 'Allowlisted', 'Generous'] }, /** - * Lookup475: pallet_evm_contract_helpers::pallet::Error + * Lookup479: pallet_evm_contract_helpers::pallet::Error **/ PalletEvmContractHelpersError: { _enum: ['NoPermission', 'NoPendingSponsor', 'TooManyMethodsHaveSponsoredLimit'] }, /** - * Lookup476: pallet_evm_migration::pallet::Error + * Lookup480: pallet_evm_migration::pallet::Error **/ PalletEvmMigrationError: { - _enum: ['AccountNotEmpty', 'AccountIsNotMigrating'] + _enum: ['AccountNotEmpty', 'AccountIsNotMigrating', 'BadEvent'] }, /** - * Lookup477: pallet_maintenance::pallet::Error + * Lookup481: pallet_maintenance::pallet::Error **/ PalletMaintenanceError: 'Null', /** - * Lookup478: pallet_test_utils::pallet::Error + * Lookup482: pallet_test_utils::pallet::Error **/ PalletTestUtilsError: { _enum: ['TestPalletDisabled', 'TriggerRollback'] }, /** - * Lookup480: sp_runtime::MultiSignature + * Lookup484: sp_runtime::MultiSignature **/ SpRuntimeMultiSignature: { _enum: { @@ -3588,51 +3641,51 @@ } }, /** - * Lookup481: sp_core::ed25519::Signature + * Lookup485: sp_core::ed25519::Signature **/ SpCoreEd25519Signature: '[u8;64]', /** - * Lookup483: sp_core::sr25519::Signature + * Lookup487: sp_core::sr25519::Signature **/ SpCoreSr25519Signature: '[u8;64]', /** - * Lookup484: sp_core::ecdsa::Signature + * Lookup488: sp_core::ecdsa::Signature **/ SpCoreEcdsaSignature: '[u8;65]', /** - * Lookup487: frame_system::extensions::check_spec_version::CheckSpecVersion + * Lookup491: frame_system::extensions::check_spec_version::CheckSpecVersion **/ FrameSystemExtensionsCheckSpecVersion: 'Null', /** - * Lookup488: frame_system::extensions::check_tx_version::CheckTxVersion + * Lookup492: frame_system::extensions::check_tx_version::CheckTxVersion **/ FrameSystemExtensionsCheckTxVersion: 'Null', /** - * Lookup489: frame_system::extensions::check_genesis::CheckGenesis + * Lookup493: frame_system::extensions::check_genesis::CheckGenesis **/ FrameSystemExtensionsCheckGenesis: 'Null', /** - * Lookup492: frame_system::extensions::check_nonce::CheckNonce + * Lookup496: frame_system::extensions::check_nonce::CheckNonce **/ FrameSystemExtensionsCheckNonce: 'Compact', /** - * Lookup493: frame_system::extensions::check_weight::CheckWeight + * Lookup497: frame_system::extensions::check_weight::CheckWeight **/ FrameSystemExtensionsCheckWeight: 'Null', /** - * Lookup494: opal_runtime::runtime_common::maintenance::CheckMaintenance + * Lookup498: opal_runtime::runtime_common::maintenance::CheckMaintenance **/ OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: 'Null', /** - * Lookup495: pallet_template_transaction_payment::ChargeTransactionPayment + * Lookup499: pallet_template_transaction_payment::ChargeTransactionPayment **/ PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact', /** - * Lookup496: opal_runtime::Runtime + * Lookup500: opal_runtime::Runtime **/ OpalRuntimeRuntime: 'Null', /** - * Lookup497: pallet_ethereum::FakeTransactionFinalizer + * Lookup501: pallet_ethereum::FakeTransactionFinalizer **/ PalletEthereumFakeTransactionFinalizer: 'Null' }; --- a/tests/src/interfaces/registry.ts +++ b/tests/src/interfaces/registry.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; +import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; declare module '@polkadot/types/types/registry' { interface InterfaceTypes { @@ -59,8 +59,6 @@ FrameSupportDispatchPerDispatchClassWeightsPerClass: FrameSupportDispatchPerDispatchClassWeightsPerClass; FrameSupportDispatchRawOrigin: FrameSupportDispatchRawOrigin; FrameSupportPalletId: FrameSupportPalletId; - FrameSupportScheduleLookupError: FrameSupportScheduleLookupError; - FrameSupportScheduleMaybeHashed: FrameSupportScheduleMaybeHashed; FrameSupportTokensMiscBalanceStatus: FrameSupportTokensMiscBalanceStatus; FrameSystemAccountInfo: FrameSystemAccountInfo; FrameSystemCall: FrameSystemCall; @@ -122,6 +120,7 @@ PalletEvmEvent: PalletEvmEvent; PalletEvmMigrationCall: PalletEvmMigrationCall; PalletEvmMigrationError: PalletEvmMigrationError; + PalletEvmMigrationEvent: PalletEvmMigrationEvent; PalletForeignAssetsAssetIds: PalletForeignAssetsAssetIds; PalletForeignAssetsModuleAssetMetadata: PalletForeignAssetsModuleAssetMetadata; PalletForeignAssetsModuleCall: PalletForeignAssetsModuleCall; @@ -164,10 +163,12 @@ PalletUniqueCall: PalletUniqueCall; PalletUniqueError: PalletUniqueError; PalletUniqueRawEvent: PalletUniqueRawEvent; - PalletUniqueSchedulerCall: PalletUniqueSchedulerCall; - PalletUniqueSchedulerError: PalletUniqueSchedulerError; - PalletUniqueSchedulerEvent: PalletUniqueSchedulerEvent; - PalletUniqueSchedulerScheduledV3: PalletUniqueSchedulerScheduledV3; + PalletUniqueSchedulerV2BlockAgenda: PalletUniqueSchedulerV2BlockAgenda; + PalletUniqueSchedulerV2Call: PalletUniqueSchedulerV2Call; + PalletUniqueSchedulerV2Error: PalletUniqueSchedulerV2Error; + PalletUniqueSchedulerV2Event: PalletUniqueSchedulerV2Event; + PalletUniqueSchedulerV2Scheduled: PalletUniqueSchedulerV2Scheduled; + PalletUniqueSchedulerV2ScheduledCall: PalletUniqueSchedulerV2ScheduledCall; PalletXcmCall: PalletXcmCall; PalletXcmError: PalletXcmError; PalletXcmEvent: PalletXcmEvent; --- a/tests/src/interfaces/types-lookup.ts +++ b/tests/src/interfaces/types-lookup.ts @@ -1132,8 +1132,8 @@ readonly type: 'Substrate' | 'Ethereum'; } - /** @name PalletUniqueSchedulerEvent (93) */ - interface PalletUniqueSchedulerEvent extends Enum { + /** @name PalletUniqueSchedulerV2Event (93) */ + interface PalletUniqueSchedulerV2Event extends Enum { readonly isScheduled: boolean; readonly asScheduled: { readonly when: u32; @@ -1144,35 +1144,31 @@ readonly when: u32; readonly index: u32; } & Struct; + readonly isDispatched: boolean; + readonly asDispatched: { + readonly task: ITuple<[u32, u32]>; + readonly id: Option; + readonly result: Result; + } & Struct; readonly isPriorityChanged: boolean; readonly asPriorityChanged: { - readonly when: u32; - readonly index: u32; + readonly task: ITuple<[u32, u32]>; readonly priority: u8; } & Struct; - readonly isDispatched: boolean; - readonly asDispatched: { + readonly isCallUnavailable: boolean; + readonly asCallUnavailable: { readonly task: ITuple<[u32, u32]>; readonly id: Option; - readonly result: Result; } & Struct; - readonly isCallLookupFailed: boolean; - readonly asCallLookupFailed: { + readonly isPermanentlyOverweight: boolean; + readonly asPermanentlyOverweight: { readonly task: ITuple<[u32, u32]>; readonly id: Option; - readonly error: FrameSupportScheduleLookupError; } & Struct; - readonly type: 'Scheduled' | 'Canceled' | 'PriorityChanged' | 'Dispatched' | 'CallLookupFailed'; + readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'PriorityChanged' | 'CallUnavailable' | 'PermanentlyOverweight'; } - /** @name FrameSupportScheduleLookupError (96) */ - interface FrameSupportScheduleLookupError extends Enum { - readonly isUnknown: boolean; - readonly isBadFormat: boolean; - readonly type: 'Unknown' | 'BadFormat'; - } - - /** @name PalletCommonEvent (97) */ + /** @name PalletCommonEvent (96) */ interface PalletCommonEvent extends Enum { readonly isCollectionCreated: boolean; readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>; @@ -1199,14 +1195,14 @@ readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet'; } - /** @name PalletStructureEvent (100) */ + /** @name PalletStructureEvent (99) */ interface PalletStructureEvent extends Enum { readonly isExecuted: boolean; readonly asExecuted: Result; readonly type: 'Executed'; } - /** @name PalletRmrkCoreEvent (101) */ + /** @name PalletRmrkCoreEvent (100) */ interface PalletRmrkCoreEvent extends Enum { readonly isCollectionCreated: boolean; readonly asCollectionCreated: { @@ -1296,7 +1292,7 @@ readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet'; } - /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (102) */ + /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (101) */ interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum { readonly isAccountId: boolean; readonly asAccountId: AccountId32; @@ -1305,7 +1301,7 @@ readonly type: 'AccountId' | 'CollectionAndNftTuple'; } - /** @name PalletRmrkEquipEvent (107) */ + /** @name PalletRmrkEquipEvent (106) */ interface PalletRmrkEquipEvent extends Enum { readonly isBaseCreated: boolean; readonly asBaseCreated: { @@ -1320,7 +1316,7 @@ readonly type: 'BaseCreated' | 'EquippablesUpdated'; } - /** @name PalletAppPromotionEvent (108) */ + /** @name PalletAppPromotionEvent (107) */ interface PalletAppPromotionEvent extends Enum { readonly isStakingRecalculation: boolean; readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>; @@ -1333,7 +1329,7 @@ readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin'; } - /** @name PalletForeignAssetsModuleEvent (109) */ + /** @name PalletForeignAssetsModuleEvent (108) */ interface PalletForeignAssetsModuleEvent extends Enum { readonly isForeignAssetRegistered: boolean; readonly asForeignAssetRegistered: { @@ -1360,7 +1356,7 @@ readonly type: 'ForeignAssetRegistered' | 'ForeignAssetUpdated' | 'AssetRegistered' | 'AssetUpdated'; } - /** @name PalletForeignAssetsModuleAssetMetadata (110) */ + /** @name PalletForeignAssetsModuleAssetMetadata (109) */ interface PalletForeignAssetsModuleAssetMetadata extends Struct { readonly name: Bytes; readonly symbol: Bytes; @@ -1368,40 +1364,51 @@ readonly minimalBalance: u128; } - /** @name PalletEvmEvent (111) */ + /** @name PalletEvmEvent (110) */ interface PalletEvmEvent extends Enum { readonly isLog: boolean; - readonly asLog: EthereumLog; + readonly asLog: { + readonly log: EthereumLog; + } & Struct; readonly isCreated: boolean; - readonly asCreated: H160; + readonly asCreated: { + readonly address: H160; + } & Struct; readonly isCreatedFailed: boolean; - readonly asCreatedFailed: H160; + readonly asCreatedFailed: { + readonly address: H160; + } & Struct; readonly isExecuted: boolean; - readonly asExecuted: H160; + readonly asExecuted: { + readonly address: H160; + } & Struct; readonly isExecutedFailed: boolean; - readonly asExecutedFailed: H160; - readonly isBalanceDeposit: boolean; - readonly asBalanceDeposit: ITuple<[AccountId32, H160, U256]>; - readonly isBalanceWithdraw: boolean; - readonly asBalanceWithdraw: ITuple<[AccountId32, H160, U256]>; - readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw'; + readonly asExecutedFailed: { + readonly address: H160; + } & Struct; + readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed'; } - /** @name EthereumLog (112) */ + /** @name EthereumLog (111) */ interface EthereumLog extends Struct { readonly address: H160; readonly topics: Vec; readonly data: Bytes; } - /** @name PalletEthereumEvent (116) */ + /** @name PalletEthereumEvent (113) */ interface PalletEthereumEvent extends Enum { readonly isExecuted: boolean; - readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>; + readonly asExecuted: { + readonly from: H160; + readonly to: H160; + readonly transactionHash: H256; + readonly exitReason: EvmCoreErrorExitReason; + } & Struct; readonly type: 'Executed'; } - /** @name EvmCoreErrorExitReason (117) */ + /** @name EvmCoreErrorExitReason (114) */ interface EvmCoreErrorExitReason extends Enum { readonly isSucceed: boolean; readonly asSucceed: EvmCoreErrorExitSucceed; @@ -1414,7 +1421,7 @@ readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal'; } - /** @name EvmCoreErrorExitSucceed (118) */ + /** @name EvmCoreErrorExitSucceed (115) */ interface EvmCoreErrorExitSucceed extends Enum { readonly isStopped: boolean; readonly isReturned: boolean; @@ -1422,7 +1429,7 @@ readonly type: 'Stopped' | 'Returned' | 'Suicided'; } - /** @name EvmCoreErrorExitError (119) */ + /** @name EvmCoreErrorExitError (116) */ interface EvmCoreErrorExitError extends Enum { readonly isStackUnderflow: boolean; readonly isStackOverflow: boolean; @@ -1443,13 +1450,13 @@ readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode'; } - /** @name EvmCoreErrorExitRevert (122) */ + /** @name EvmCoreErrorExitRevert (119) */ interface EvmCoreErrorExitRevert extends Enum { readonly isReverted: boolean; readonly type: 'Reverted'; } - /** @name EvmCoreErrorExitFatal (123) */ + /** @name EvmCoreErrorExitFatal (120) */ interface EvmCoreErrorExitFatal extends Enum { readonly isNotSupported: boolean; readonly isUnhandledInterrupt: boolean; @@ -1460,7 +1467,7 @@ readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other'; } - /** @name PalletEvmContractHelpersEvent (124) */ + /** @name PalletEvmContractHelpersEvent (121) */ interface PalletEvmContractHelpersEvent extends Enum { readonly isContractSponsorSet: boolean; readonly asContractSponsorSet: ITuple<[H160, AccountId32]>; @@ -1471,21 +1478,28 @@ readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved'; } - /** @name PalletMaintenanceEvent (125) */ + /** @name PalletEvmMigrationEvent (122) */ + interface PalletEvmMigrationEvent extends Enum { + readonly isTestEvent: boolean; + readonly type: 'TestEvent'; + } + + /** @name PalletMaintenanceEvent (123) */ interface PalletMaintenanceEvent extends Enum { readonly isMaintenanceEnabled: boolean; readonly isMaintenanceDisabled: boolean; readonly type: 'MaintenanceEnabled' | 'MaintenanceDisabled'; } - /** @name PalletTestUtilsEvent (126) */ + /** @name PalletTestUtilsEvent (124) */ interface PalletTestUtilsEvent extends Enum { readonly isValueIsSet: boolean; readonly isShouldRollback: boolean; - readonly type: 'ValueIsSet' | 'ShouldRollback'; + readonly isBatchCompleted: boolean; + readonly type: 'ValueIsSet' | 'ShouldRollback' | 'BatchCompleted'; } - /** @name FrameSystemPhase (127) */ + /** @name FrameSystemPhase (125) */ interface FrameSystemPhase extends Enum { readonly isApplyExtrinsic: boolean; readonly asApplyExtrinsic: u32; @@ -1494,13 +1508,13 @@ readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization'; } - /** @name FrameSystemLastRuntimeUpgradeInfo (129) */ + /** @name FrameSystemLastRuntimeUpgradeInfo (127) */ interface FrameSystemLastRuntimeUpgradeInfo extends Struct { readonly specVersion: Compact; readonly specName: Text; } - /** @name FrameSystemCall (130) */ + /** @name FrameSystemCall (128) */ interface FrameSystemCall extends Enum { readonly isFillBlock: boolean; readonly asFillBlock: { @@ -1542,21 +1556,21 @@ readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent'; } - /** @name FrameSystemLimitsBlockWeights (135) */ + /** @name FrameSystemLimitsBlockWeights (133) */ interface FrameSystemLimitsBlockWeights extends Struct { readonly baseBlock: Weight; readonly maxBlock: Weight; readonly perClass: FrameSupportDispatchPerDispatchClassWeightsPerClass; } - /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (136) */ + /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (134) */ interface FrameSupportDispatchPerDispatchClassWeightsPerClass extends Struct { readonly normal: FrameSystemLimitsWeightsPerClass; readonly operational: FrameSystemLimitsWeightsPerClass; readonly mandatory: FrameSystemLimitsWeightsPerClass; } - /** @name FrameSystemLimitsWeightsPerClass (137) */ + /** @name FrameSystemLimitsWeightsPerClass (135) */ interface FrameSystemLimitsWeightsPerClass extends Struct { readonly baseExtrinsic: Weight; readonly maxExtrinsic: Option; @@ -1564,25 +1578,25 @@ readonly reserved: Option; } - /** @name FrameSystemLimitsBlockLength (139) */ + /** @name FrameSystemLimitsBlockLength (137) */ interface FrameSystemLimitsBlockLength extends Struct { readonly max: FrameSupportDispatchPerDispatchClassU32; } - /** @name FrameSupportDispatchPerDispatchClassU32 (140) */ + /** @name FrameSupportDispatchPerDispatchClassU32 (138) */ interface FrameSupportDispatchPerDispatchClassU32 extends Struct { readonly normal: u32; readonly operational: u32; readonly mandatory: u32; } - /** @name SpWeightsRuntimeDbWeight (141) */ + /** @name SpWeightsRuntimeDbWeight (139) */ interface SpWeightsRuntimeDbWeight extends Struct { readonly read: u64; readonly write: u64; } - /** @name SpVersionRuntimeVersion (142) */ + /** @name SpVersionRuntimeVersion (140) */ interface SpVersionRuntimeVersion extends Struct { readonly specName: Text; readonly implName: Text; @@ -1594,7 +1608,7 @@ readonly stateVersion: u8; } - /** @name FrameSystemError (147) */ + /** @name FrameSystemError (145) */ interface FrameSystemError extends Enum { readonly isInvalidSpecName: boolean; readonly isSpecVersionNeedsToIncrease: boolean; @@ -1605,7 +1619,7 @@ readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered'; } - /** @name PolkadotPrimitivesV2PersistedValidationData (148) */ + /** @name PolkadotPrimitivesV2PersistedValidationData (146) */ interface PolkadotPrimitivesV2PersistedValidationData extends Struct { readonly parentHead: Bytes; readonly relayParentNumber: u32; @@ -1613,18 +1627,18 @@ readonly maxPovSize: u32; } - /** @name PolkadotPrimitivesV2UpgradeRestriction (151) */ + /** @name PolkadotPrimitivesV2UpgradeRestriction (149) */ interface PolkadotPrimitivesV2UpgradeRestriction extends Enum { readonly isPresent: boolean; readonly type: 'Present'; } - /** @name SpTrieStorageProof (152) */ + /** @name SpTrieStorageProof (150) */ interface SpTrieStorageProof extends Struct { readonly trieNodes: BTreeSet; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (154) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (152) */ interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct { readonly dmqMqcHead: H256; readonly relayDispatchQueueSize: ITuple<[u32, u32]>; @@ -1632,7 +1646,7 @@ readonly egressChannels: Vec>; } - /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (157) */ + /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (155) */ interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct { readonly maxCapacity: u32; readonly maxTotalSize: u32; @@ -1642,7 +1656,7 @@ readonly mqcHead: Option; } - /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (158) */ + /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (156) */ interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct { readonly maxCodeSize: u32; readonly maxHeadDataSize: u32; @@ -1655,13 +1669,13 @@ readonly validationUpgradeDelay: u32; } - /** @name PolkadotCorePrimitivesOutboundHrmpMessage (164) */ + /** @name PolkadotCorePrimitivesOutboundHrmpMessage (162) */ interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct { readonly recipient: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemCall (165) */ + /** @name CumulusPalletParachainSystemCall (163) */ interface CumulusPalletParachainSystemCall extends Enum { readonly isSetValidationData: boolean; readonly asSetValidationData: { @@ -1682,7 +1696,7 @@ readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade'; } - /** @name CumulusPrimitivesParachainInherentParachainInherentData (166) */ + /** @name CumulusPrimitivesParachainInherentParachainInherentData (164) */ interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct { readonly validationData: PolkadotPrimitivesV2PersistedValidationData; readonly relayChainState: SpTrieStorageProof; @@ -1690,19 +1704,19 @@ readonly horizontalMessages: BTreeMap>; } - /** @name PolkadotCorePrimitivesInboundDownwardMessage (168) */ + /** @name PolkadotCorePrimitivesInboundDownwardMessage (166) */ interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct { readonly sentAt: u32; readonly msg: Bytes; } - /** @name PolkadotCorePrimitivesInboundHrmpMessage (171) */ + /** @name PolkadotCorePrimitivesInboundHrmpMessage (169) */ interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct { readonly sentAt: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemError (174) */ + /** @name CumulusPalletParachainSystemError (172) */ interface CumulusPalletParachainSystemError extends Enum { readonly isOverlappingUpgrades: boolean; readonly isProhibitedByPolkadot: boolean; @@ -1715,14 +1729,14 @@ readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized'; } - /** @name PalletBalancesBalanceLock (176) */ + /** @name PalletBalancesBalanceLock (174) */ interface PalletBalancesBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; readonly reasons: PalletBalancesReasons; } - /** @name PalletBalancesReasons (177) */ + /** @name PalletBalancesReasons (175) */ interface PalletBalancesReasons extends Enum { readonly isFee: boolean; readonly isMisc: boolean; @@ -1730,20 +1744,20 @@ readonly type: 'Fee' | 'Misc' | 'All'; } - /** @name PalletBalancesReserveData (180) */ + /** @name PalletBalancesReserveData (178) */ interface PalletBalancesReserveData extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name PalletBalancesReleases (182) */ + /** @name PalletBalancesReleases (180) */ interface PalletBalancesReleases extends Enum { readonly isV100: boolean; readonly isV200: boolean; readonly type: 'V100' | 'V200'; } - /** @name PalletBalancesCall (183) */ + /** @name PalletBalancesCall (181) */ interface PalletBalancesCall extends Enum { readonly isTransfer: boolean; readonly asTransfer: { @@ -1780,7 +1794,7 @@ readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve'; } - /** @name PalletBalancesError (186) */ + /** @name PalletBalancesError (184) */ interface PalletBalancesError extends Enum { readonly isVestingBalance: boolean; readonly isLiquidityRestrictions: boolean; @@ -1793,7 +1807,7 @@ readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves'; } - /** @name PalletTimestampCall (188) */ + /** @name PalletTimestampCall (186) */ interface PalletTimestampCall extends Enum { readonly isSet: boolean; readonly asSet: { @@ -1802,14 +1816,14 @@ readonly type: 'Set'; } - /** @name PalletTransactionPaymentReleases (190) */ + /** @name PalletTransactionPaymentReleases (188) */ interface PalletTransactionPaymentReleases extends Enum { readonly isV1Ancient: boolean; readonly isV2: boolean; readonly type: 'V1Ancient' | 'V2'; } - /** @name PalletTreasuryProposal (191) */ + /** @name PalletTreasuryProposal (189) */ interface PalletTreasuryProposal extends Struct { readonly proposer: AccountId32; readonly value: u128; @@ -1817,7 +1831,7 @@ readonly bond: u128; } - /** @name PalletTreasuryCall (194) */ + /** @name PalletTreasuryCall (192) */ interface PalletTreasuryCall extends Enum { readonly isProposeSpend: boolean; readonly asProposeSpend: { @@ -1844,10 +1858,10 @@ readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval'; } - /** @name FrameSupportPalletId (197) */ + /** @name FrameSupportPalletId (195) */ interface FrameSupportPalletId extends U8aFixed {} - /** @name PalletTreasuryError (198) */ + /** @name PalletTreasuryError (196) */ interface PalletTreasuryError extends Enum { readonly isInsufficientProposersBalance: boolean; readonly isInvalidIndex: boolean; @@ -1857,7 +1871,7 @@ readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved'; } - /** @name PalletSudoCall (199) */ + /** @name PalletSudoCall (197) */ interface PalletSudoCall extends Enum { readonly isSudo: boolean; readonly asSudo: { @@ -1880,7 +1894,7 @@ readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs'; } - /** @name OrmlVestingModuleCall (201) */ + /** @name OrmlVestingModuleCall (199) */ interface OrmlVestingModuleCall extends Enum { readonly isClaim: boolean; readonly isVestedTransfer: boolean; @@ -1900,7 +1914,7 @@ readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor'; } - /** @name OrmlXtokensModuleCall (203) */ + /** @name OrmlXtokensModuleCall (201) */ interface OrmlXtokensModuleCall extends Enum { readonly isTransfer: boolean; readonly asTransfer: { @@ -1947,7 +1961,7 @@ readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets'; } - /** @name XcmVersionedMultiAsset (204) */ + /** @name XcmVersionedMultiAsset (202) */ interface XcmVersionedMultiAsset extends Enum { readonly isV0: boolean; readonly asV0: XcmV0MultiAsset; @@ -1956,7 +1970,7 @@ readonly type: 'V0' | 'V1'; } - /** @name OrmlTokensModuleCall (207) */ + /** @name OrmlTokensModuleCall (205) */ interface OrmlTokensModuleCall extends Enum { readonly isTransfer: boolean; readonly asTransfer: { @@ -1993,7 +2007,7 @@ readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance'; } - /** @name CumulusPalletXcmpQueueCall (208) */ + /** @name CumulusPalletXcmpQueueCall (206) */ interface CumulusPalletXcmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2029,7 +2043,7 @@ readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight'; } - /** @name PalletXcmCall (209) */ + /** @name PalletXcmCall (207) */ interface PalletXcmCall extends Enum { readonly isSend: boolean; readonly asSend: { @@ -2091,7 +2105,7 @@ readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets'; } - /** @name XcmVersionedXcm (210) */ + /** @name XcmVersionedXcm (208) */ interface XcmVersionedXcm extends Enum { readonly isV0: boolean; readonly asV0: XcmV0Xcm; @@ -2102,7 +2116,7 @@ readonly type: 'V0' | 'V1' | 'V2'; } - /** @name XcmV0Xcm (211) */ + /** @name XcmV0Xcm (209) */ interface XcmV0Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -2165,7 +2179,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom'; } - /** @name XcmV0Order (213) */ + /** @name XcmV0Order (211) */ interface XcmV0Order extends Enum { readonly isNull: boolean; readonly isDepositAsset: boolean; @@ -2213,14 +2227,14 @@ readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV0Response (215) */ + /** @name XcmV0Response (213) */ interface XcmV0Response extends Enum { readonly isAssets: boolean; readonly asAssets: Vec; readonly type: 'Assets'; } - /** @name XcmV1Xcm (216) */ + /** @name XcmV1Xcm (214) */ interface XcmV1Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -2289,7 +2303,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion'; } - /** @name XcmV1Order (218) */ + /** @name XcmV1Order (216) */ interface XcmV1Order extends Enum { readonly isNoop: boolean; readonly isDepositAsset: boolean; @@ -2339,7 +2353,7 @@ readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV1Response (220) */ + /** @name XcmV1Response (218) */ interface XcmV1Response extends Enum { readonly isAssets: boolean; readonly asAssets: XcmV1MultiassetMultiAssets; @@ -2348,10 +2362,10 @@ readonly type: 'Assets' | 'Version'; } - /** @name CumulusPalletXcmCall (234) */ + /** @name CumulusPalletXcmCall (232) */ type CumulusPalletXcmCall = Null; - /** @name CumulusPalletDmpQueueCall (235) */ + /** @name CumulusPalletDmpQueueCall (233) */ interface CumulusPalletDmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2361,7 +2375,7 @@ readonly type: 'ServiceOverweight'; } - /** @name PalletInflationCall (236) */ + /** @name PalletInflationCall (234) */ interface PalletInflationCall extends Enum { readonly isStartInflation: boolean; readonly asStartInflation: { @@ -2370,7 +2384,7 @@ readonly type: 'StartInflation'; } - /** @name PalletUniqueCall (237) */ + /** @name PalletUniqueCall (235) */ interface PalletUniqueCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2528,7 +2542,7 @@ readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition'; } - /** @name UpDataStructsCollectionMode (242) */ + /** @name UpDataStructsCollectionMode (240) */ interface UpDataStructsCollectionMode extends Enum { readonly isNft: boolean; readonly isFungible: boolean; @@ -2537,7 +2551,7 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateCollectionData (243) */ + /** @name UpDataStructsCreateCollectionData (241) */ interface UpDataStructsCreateCollectionData extends Struct { readonly mode: UpDataStructsCollectionMode; readonly access: Option; @@ -2551,14 +2565,14 @@ readonly properties: Vec; } - /** @name UpDataStructsAccessMode (245) */ + /** @name UpDataStructsAccessMode (243) */ interface UpDataStructsAccessMode extends Enum { readonly isNormal: boolean; readonly isAllowList: boolean; readonly type: 'Normal' | 'AllowList'; } - /** @name UpDataStructsCollectionLimits (247) */ + /** @name UpDataStructsCollectionLimits (245) */ interface UpDataStructsCollectionLimits extends Struct { readonly accountTokenOwnershipLimit: Option; readonly sponsoredDataSize: Option; @@ -2571,7 +2585,7 @@ readonly transfersEnabled: Option; } - /** @name UpDataStructsSponsoringRateLimit (249) */ + /** @name UpDataStructsSponsoringRateLimit (247) */ interface UpDataStructsSponsoringRateLimit extends Enum { readonly isSponsoringDisabled: boolean; readonly isBlocks: boolean; @@ -2579,43 +2593,43 @@ readonly type: 'SponsoringDisabled' | 'Blocks'; } - /** @name UpDataStructsCollectionPermissions (252) */ + /** @name UpDataStructsCollectionPermissions (250) */ interface UpDataStructsCollectionPermissions extends Struct { readonly access: Option; readonly mintMode: Option; readonly nesting: Option; } - /** @name UpDataStructsNestingPermissions (254) */ + /** @name UpDataStructsNestingPermissions (252) */ interface UpDataStructsNestingPermissions extends Struct { readonly tokenOwner: bool; readonly collectionAdmin: bool; readonly restricted: Option; } - /** @name UpDataStructsOwnerRestrictedSet (256) */ + /** @name UpDataStructsOwnerRestrictedSet (254) */ interface UpDataStructsOwnerRestrictedSet extends BTreeSet {} - /** @name UpDataStructsPropertyKeyPermission (261) */ + /** @name UpDataStructsPropertyKeyPermission (259) */ interface UpDataStructsPropertyKeyPermission extends Struct { readonly key: Bytes; readonly permission: UpDataStructsPropertyPermission; } - /** @name UpDataStructsPropertyPermission (262) */ + /** @name UpDataStructsPropertyPermission (260) */ interface UpDataStructsPropertyPermission extends Struct { readonly mutable: bool; readonly collectionAdmin: bool; readonly tokenOwner: bool; } - /** @name UpDataStructsProperty (265) */ + /** @name UpDataStructsProperty (263) */ interface UpDataStructsProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name UpDataStructsCreateItemData (268) */ + /** @name UpDataStructsCreateItemData (266) */ interface UpDataStructsCreateItemData extends Enum { readonly isNft: boolean; readonly asNft: UpDataStructsCreateNftData; @@ -2626,23 +2640,23 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateNftData (269) */ + /** @name UpDataStructsCreateNftData (267) */ interface UpDataStructsCreateNftData extends Struct { readonly properties: Vec; } - /** @name UpDataStructsCreateFungibleData (270) */ + /** @name UpDataStructsCreateFungibleData (268) */ interface UpDataStructsCreateFungibleData extends Struct { readonly value: u128; } - /** @name UpDataStructsCreateReFungibleData (271) */ + /** @name UpDataStructsCreateReFungibleData (269) */ interface UpDataStructsCreateReFungibleData extends Struct { readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateItemExData (274) */ + /** @name UpDataStructsCreateItemExData (272) */ interface UpDataStructsCreateItemExData extends Enum { readonly isNft: boolean; readonly asNft: Vec; @@ -2655,65 +2669,75 @@ readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners'; } - /** @name UpDataStructsCreateNftExData (276) */ + /** @name UpDataStructsCreateNftExData (274) */ interface UpDataStructsCreateNftExData extends Struct { readonly properties: Vec; readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsCreateRefungibleExSingleOwner (283) */ + /** @name UpDataStructsCreateRefungibleExSingleOwner (281) */ interface UpDataStructsCreateRefungibleExSingleOwner extends Struct { readonly user: PalletEvmAccountBasicCrossAccountIdRepr; readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateRefungibleExMultipleOwners (285) */ + /** @name UpDataStructsCreateRefungibleExMultipleOwners (283) */ interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct { readonly users: BTreeMap; readonly properties: Vec; } - /** @name PalletUniqueSchedulerCall (286) */ - interface PalletUniqueSchedulerCall extends Enum { + /** @name PalletUniqueSchedulerV2Call (284) */ + interface PalletUniqueSchedulerV2Call extends Enum { + readonly isSchedule: boolean; + readonly asSchedule: { + readonly when: u32; + readonly maybePeriodic: Option>; + readonly priority: Option; + readonly call: Call; + } & Struct; + readonly isCancel: boolean; + readonly asCancel: { + readonly when: u32; + readonly index: u32; + } & Struct; readonly isScheduleNamed: boolean; readonly asScheduleNamed: { readonly id: U8aFixed; readonly when: u32; readonly maybePeriodic: Option>; readonly priority: Option; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: Call; } & Struct; readonly isCancelNamed: boolean; readonly asCancelNamed: { readonly id: U8aFixed; } & Struct; + readonly isScheduleAfter: boolean; + readonly asScheduleAfter: { + readonly after: u32; + readonly maybePeriodic: Option>; + readonly priority: Option; + readonly call: Call; + } & Struct; readonly isScheduleNamedAfter: boolean; readonly asScheduleNamedAfter: { readonly id: U8aFixed; readonly after: u32; readonly maybePeriodic: Option>; readonly priority: Option; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: Call; } & Struct; readonly isChangeNamedPriority: boolean; readonly asChangeNamedPriority: { readonly id: U8aFixed; readonly priority: u8; } & Struct; - readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter' | 'ChangeNamedPriority'; - } - - /** @name FrameSupportScheduleMaybeHashed (289) */ - interface FrameSupportScheduleMaybeHashed extends Enum { - readonly isValue: boolean; - readonly asValue: Call; - readonly isHash: boolean; - readonly asHash: H256; - readonly type: 'Value' | 'Hash'; + readonly type: 'Schedule' | 'Cancel' | 'ScheduleNamed' | 'CancelNamed' | 'ScheduleAfter' | 'ScheduleNamedAfter' | 'ChangeNamedPriority'; } - /** @name PalletConfigurationCall (290) */ + /** @name PalletConfigurationCall (287) */ interface PalletConfigurationCall extends Enum { readonly isSetWeightToFeeCoefficientOverride: boolean; readonly asSetWeightToFeeCoefficientOverride: { @@ -2726,13 +2750,13 @@ readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride'; } - /** @name PalletTemplateTransactionPaymentCall (292) */ + /** @name PalletTemplateTransactionPaymentCall (289) */ type PalletTemplateTransactionPaymentCall = Null; - /** @name PalletStructureCall (293) */ + /** @name PalletStructureCall (290) */ type PalletStructureCall = Null; - /** @name PalletRmrkCoreCall (294) */ + /** @name PalletRmrkCoreCall (291) */ interface PalletRmrkCoreCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2838,7 +2862,7 @@ readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource'; } - /** @name RmrkTraitsResourceResourceTypes (300) */ + /** @name RmrkTraitsResourceResourceTypes (297) */ interface RmrkTraitsResourceResourceTypes extends Enum { readonly isBasic: boolean; readonly asBasic: RmrkTraitsResourceBasicResource; @@ -2849,7 +2873,7 @@ readonly type: 'Basic' | 'Composable' | 'Slot'; } - /** @name RmrkTraitsResourceBasicResource (302) */ + /** @name RmrkTraitsResourceBasicResource (299) */ interface RmrkTraitsResourceBasicResource extends Struct { readonly src: Option; readonly metadata: Option; @@ -2857,7 +2881,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceComposableResource (304) */ + /** @name RmrkTraitsResourceComposableResource (301) */ interface RmrkTraitsResourceComposableResource extends Struct { readonly parts: Vec; readonly base: u32; @@ -2867,7 +2891,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceSlotResource (305) */ + /** @name RmrkTraitsResourceSlotResource (302) */ interface RmrkTraitsResourceSlotResource extends Struct { readonly base: u32; readonly src: Option; @@ -2877,7 +2901,7 @@ readonly thumb: Option; } - /** @name PalletRmrkEquipCall (308) */ + /** @name PalletRmrkEquipCall (305) */ interface PalletRmrkEquipCall extends Enum { readonly isCreateBase: boolean; readonly asCreateBase: { @@ -2899,7 +2923,7 @@ readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable'; } - /** @name RmrkTraitsPartPartType (311) */ + /** @name RmrkTraitsPartPartType (308) */ interface RmrkTraitsPartPartType extends Enum { readonly isFixedPart: boolean; readonly asFixedPart: RmrkTraitsPartFixedPart; @@ -2908,14 +2932,14 @@ readonly type: 'FixedPart' | 'SlotPart'; } - /** @name RmrkTraitsPartFixedPart (313) */ + /** @name RmrkTraitsPartFixedPart (310) */ interface RmrkTraitsPartFixedPart extends Struct { readonly id: u32; readonly z: u32; readonly src: Bytes; } - /** @name RmrkTraitsPartSlotPart (314) */ + /** @name RmrkTraitsPartSlotPart (311) */ interface RmrkTraitsPartSlotPart extends Struct { readonly id: u32; readonly equippable: RmrkTraitsPartEquippableList; @@ -2923,7 +2947,7 @@ readonly z: u32; } - /** @name RmrkTraitsPartEquippableList (315) */ + /** @name RmrkTraitsPartEquippableList (312) */ interface RmrkTraitsPartEquippableList extends Enum { readonly isAll: boolean; readonly isEmpty: boolean; @@ -2932,20 +2956,20 @@ readonly type: 'All' | 'Empty' | 'Custom'; } - /** @name RmrkTraitsTheme (317) */ + /** @name RmrkTraitsTheme (314) */ interface RmrkTraitsTheme extends Struct { readonly name: Bytes; readonly properties: Vec; readonly inherit: bool; } - /** @name RmrkTraitsThemeThemeProperty (319) */ + /** @name RmrkTraitsThemeThemeProperty (316) */ interface RmrkTraitsThemeThemeProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name PalletAppPromotionCall (321) */ + /** @name PalletAppPromotionCall (318) */ interface PalletAppPromotionCall extends Enum { readonly isSetAdminAddress: boolean; readonly asSetAdminAddress: { @@ -2979,7 +3003,7 @@ readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers'; } - /** @name PalletForeignAssetsModuleCall (322) */ + /** @name PalletForeignAssetsModuleCall (319) */ interface PalletForeignAssetsModuleCall extends Enum { readonly isRegisterForeignAsset: boolean; readonly asRegisterForeignAsset: { @@ -2996,7 +3020,7 @@ readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset'; } - /** @name PalletEvmCall (323) */ + /** @name PalletEvmCall (320) */ interface PalletEvmCall extends Enum { readonly isWithdraw: boolean; readonly asWithdraw: { @@ -3041,7 +3065,7 @@ readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2'; } - /** @name PalletEthereumCall (327) */ + /** @name PalletEthereumCall (326) */ interface PalletEthereumCall extends Enum { readonly isTransact: boolean; readonly asTransact: { @@ -3050,7 +3074,7 @@ readonly type: 'Transact'; } - /** @name EthereumTransactionTransactionV2 (328) */ + /** @name EthereumTransactionTransactionV2 (327) */ interface EthereumTransactionTransactionV2 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumTransactionLegacyTransaction; @@ -3061,7 +3085,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumTransactionLegacyTransaction (329) */ + /** @name EthereumTransactionLegacyTransaction (328) */ interface EthereumTransactionLegacyTransaction extends Struct { readonly nonce: U256; readonly gasPrice: U256; @@ -3072,7 +3096,7 @@ readonly signature: EthereumTransactionTransactionSignature; } - /** @name EthereumTransactionTransactionAction (330) */ + /** @name EthereumTransactionTransactionAction (329) */ interface EthereumTransactionTransactionAction extends Enum { readonly isCall: boolean; readonly asCall: H160; @@ -3080,14 +3104,14 @@ readonly type: 'Call' | 'Create'; } - /** @name EthereumTransactionTransactionSignature (331) */ + /** @name EthereumTransactionTransactionSignature (330) */ interface EthereumTransactionTransactionSignature extends Struct { readonly v: u64; readonly r: H256; readonly s: H256; } - /** @name EthereumTransactionEip2930Transaction (333) */ + /** @name EthereumTransactionEip2930Transaction (332) */ interface EthereumTransactionEip2930Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -3102,13 +3126,13 @@ readonly s: H256; } - /** @name EthereumTransactionAccessListItem (335) */ + /** @name EthereumTransactionAccessListItem (334) */ interface EthereumTransactionAccessListItem extends Struct { readonly address: H160; readonly storageKeys: Vec; } - /** @name EthereumTransactionEip1559Transaction (336) */ + /** @name EthereumTransactionEip1559Transaction (335) */ interface EthereumTransactionEip1559Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -3124,7 +3148,7 @@ readonly s: H256; } - /** @name PalletEvmMigrationCall (337) */ + /** @name PalletEvmMigrationCall (336) */ interface PalletEvmMigrationCall extends Enum { readonly isBegin: boolean; readonly asBegin: { @@ -3140,7 +3164,15 @@ readonly address: H160; readonly code: Bytes; } & Struct; - readonly type: 'Begin' | 'SetData' | 'Finish'; + readonly isInsertEthLogs: boolean; + readonly asInsertEthLogs: { + readonly logs: Vec; + } & Struct; + readonly isInsertEvents: boolean; + readonly asInsertEvents: { + readonly events: Vec; + } & Struct; + readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents'; } /** @name PalletMaintenanceCall (340) */ @@ -3168,16 +3200,20 @@ readonly maxTestValue: u32; } & Struct; readonly isJustTakeFee: boolean; - readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'SelfCancelingInc' | 'JustTakeFee'; + readonly isBatchAll: boolean; + readonly asBatchAll: { + readonly calls: Vec; + } & Struct; + readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'SelfCancelingInc' | 'JustTakeFee' | 'BatchAll'; } - /** @name PalletSudoError (342) */ + /** @name PalletSudoError (343) */ interface PalletSudoError extends Enum { readonly isRequireSudo: boolean; readonly type: 'RequireSudo'; } - /** @name OrmlVestingModuleError (344) */ + /** @name OrmlVestingModuleError (345) */ interface OrmlVestingModuleError extends Enum { readonly isZeroVestingPeriod: boolean; readonly isZeroVestingPeriodCount: boolean; @@ -3188,7 +3224,7 @@ readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded'; } - /** @name OrmlXtokensModuleError (345) */ + /** @name OrmlXtokensModuleError (346) */ interface OrmlXtokensModuleError extends Enum { readonly isAssetHasNoReserve: boolean; readonly isNotCrossChainTransfer: boolean; @@ -3212,26 +3248,26 @@ readonly type: 'AssetHasNoReserve' | 'NotCrossChainTransfer' | 'InvalidDest' | 'NotCrossChainTransferableCurrency' | 'UnweighableMessage' | 'XcmExecutionFailed' | 'CannotReanchor' | 'InvalidAncestry' | 'InvalidAsset' | 'DestinationNotInvertible' | 'BadVersion' | 'DistinctReserveForAssetAndFee' | 'ZeroFee' | 'ZeroAmount' | 'TooManyAssetsBeingSent' | 'AssetIndexNonExistent' | 'FeeNotEnough' | 'NotSupportedMultiLocation' | 'MinXcmFeeNotDefined'; } - /** @name OrmlTokensBalanceLock (348) */ + /** @name OrmlTokensBalanceLock (349) */ interface OrmlTokensBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name OrmlTokensAccountData (350) */ + /** @name OrmlTokensAccountData (351) */ interface OrmlTokensAccountData extends Struct { readonly free: u128; readonly reserved: u128; readonly frozen: u128; } - /** @name OrmlTokensReserveData (352) */ + /** @name OrmlTokensReserveData (353) */ interface OrmlTokensReserveData extends Struct { readonly id: Null; readonly amount: u128; } - /** @name OrmlTokensModuleError (354) */ + /** @name OrmlTokensModuleError (355) */ interface OrmlTokensModuleError extends Enum { readonly isBalanceTooLow: boolean; readonly isAmountIntoBalanceFailed: boolean; @@ -3244,21 +3280,21 @@ readonly type: 'BalanceTooLow' | 'AmountIntoBalanceFailed' | 'LiquidityRestrictions' | 'MaxLocksExceeded' | 'KeepAlive' | 'ExistentialDeposit' | 'DeadAccount' | 'TooManyReserves'; } - /** @name CumulusPalletXcmpQueueInboundChannelDetails (356) */ + /** @name CumulusPalletXcmpQueueInboundChannelDetails (357) */ interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct { readonly sender: u32; readonly state: CumulusPalletXcmpQueueInboundState; readonly messageMetadata: Vec>; } - /** @name CumulusPalletXcmpQueueInboundState (357) */ + /** @name CumulusPalletXcmpQueueInboundState (358) */ interface CumulusPalletXcmpQueueInboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name PolkadotParachainPrimitivesXcmpMessageFormat (360) */ + /** @name PolkadotParachainPrimitivesXcmpMessageFormat (361) */ interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum { readonly isConcatenatedVersionedXcm: boolean; readonly isConcatenatedEncodedBlob: boolean; @@ -3266,7 +3302,7 @@ readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals'; } - /** @name CumulusPalletXcmpQueueOutboundChannelDetails (363) */ + /** @name CumulusPalletXcmpQueueOutboundChannelDetails (364) */ interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct { readonly recipient: u32; readonly state: CumulusPalletXcmpQueueOutboundState; @@ -3275,14 +3311,14 @@ readonly lastIndex: u16; } - /** @name CumulusPalletXcmpQueueOutboundState (364) */ + /** @name CumulusPalletXcmpQueueOutboundState (365) */ interface CumulusPalletXcmpQueueOutboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name CumulusPalletXcmpQueueQueueConfigData (366) */ + /** @name CumulusPalletXcmpQueueQueueConfigData (367) */ interface CumulusPalletXcmpQueueQueueConfigData extends Struct { readonly suspendThreshold: u32; readonly dropThreshold: u32; @@ -3292,7 +3328,7 @@ readonly xcmpMaxIndividualWeight: Weight; } - /** @name CumulusPalletXcmpQueueError (368) */ + /** @name CumulusPalletXcmpQueueError (369) */ interface CumulusPalletXcmpQueueError extends Enum { readonly isFailedToSend: boolean; readonly isBadXcmOrigin: boolean; @@ -3302,7 +3338,7 @@ readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit'; } - /** @name PalletXcmError (369) */ + /** @name PalletXcmError (370) */ interface PalletXcmError extends Enum { readonly isUnreachable: boolean; readonly isSendFailure: boolean; @@ -3320,29 +3356,29 @@ readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed'; } - /** @name CumulusPalletXcmError (370) */ + /** @name CumulusPalletXcmError (371) */ type CumulusPalletXcmError = Null; - /** @name CumulusPalletDmpQueueConfigData (371) */ + /** @name CumulusPalletDmpQueueConfigData (372) */ interface CumulusPalletDmpQueueConfigData extends Struct { readonly maxIndividual: Weight; } - /** @name CumulusPalletDmpQueuePageIndexData (372) */ + /** @name CumulusPalletDmpQueuePageIndexData (373) */ interface CumulusPalletDmpQueuePageIndexData extends Struct { readonly beginUsed: u32; readonly endUsed: u32; readonly overweightCount: u64; } - /** @name CumulusPalletDmpQueueError (375) */ + /** @name CumulusPalletDmpQueueError (376) */ interface CumulusPalletDmpQueueError extends Enum { readonly isUnknown: boolean; readonly isOverLimit: boolean; readonly type: 'Unknown' | 'OverLimit'; } - /** @name PalletUniqueError (379) */ + /** @name PalletUniqueError (380) */ interface PalletUniqueError extends Enum { readonly isCollectionDecimalPointLimitExceeded: boolean; readonly isConfirmUnsetSponsorFail: boolean; @@ -3351,16 +3387,34 @@ readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection'; } - /** @name PalletUniqueSchedulerScheduledV3 (382) */ - interface PalletUniqueSchedulerScheduledV3 extends Struct { + /** @name PalletUniqueSchedulerV2BlockAgenda (381) */ + interface PalletUniqueSchedulerV2BlockAgenda extends Struct { + readonly agenda: Vec>; + readonly freePlaces: u32; + } + + /** @name PalletUniqueSchedulerV2Scheduled (384) */ + interface PalletUniqueSchedulerV2Scheduled extends Struct { readonly maybeId: Option; readonly priority: u8; - readonly call: FrameSupportScheduleMaybeHashed; + readonly call: PalletUniqueSchedulerV2ScheduledCall; readonly maybePeriodic: Option>; readonly origin: OpalRuntimeOriginCaller; } - /** @name OpalRuntimeOriginCaller (383) */ + /** @name PalletUniqueSchedulerV2ScheduledCall (385) */ + interface PalletUniqueSchedulerV2ScheduledCall extends Enum { + readonly isInline: boolean; + readonly asInline: Bytes; + readonly isPreimageLookup: boolean; + readonly asPreimageLookup: { + readonly hash_: H256; + readonly unboundedLen: u32; + } & Struct; + readonly type: 'Inline' | 'PreimageLookup'; + } + + /** @name OpalRuntimeOriginCaller (387) */ interface OpalRuntimeOriginCaller extends Enum { readonly isSystem: boolean; readonly asSystem: FrameSupportDispatchRawOrigin; @@ -3374,7 +3428,7 @@ readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum'; } - /** @name FrameSupportDispatchRawOrigin (384) */ + /** @name FrameSupportDispatchRawOrigin (388) */ interface FrameSupportDispatchRawOrigin extends Enum { readonly isRoot: boolean; readonly isSigned: boolean; @@ -3383,7 +3437,7 @@ readonly type: 'Root' | 'Signed' | 'None'; } - /** @name PalletXcmOrigin (385) */ + /** @name PalletXcmOrigin (389) */ interface PalletXcmOrigin extends Enum { readonly isXcm: boolean; readonly asXcm: XcmV1MultiLocation; @@ -3392,7 +3446,7 @@ readonly type: 'Xcm' | 'Response'; } - /** @name CumulusPalletXcmOrigin (386) */ + /** @name CumulusPalletXcmOrigin (390) */ interface CumulusPalletXcmOrigin extends Enum { readonly isRelay: boolean; readonly isSiblingParachain: boolean; @@ -3400,26 +3454,30 @@ readonly type: 'Relay' | 'SiblingParachain'; } - /** @name PalletEthereumRawOrigin (387) */ + /** @name PalletEthereumRawOrigin (391) */ interface PalletEthereumRawOrigin extends Enum { readonly isEthereumTransaction: boolean; readonly asEthereumTransaction: H160; readonly type: 'EthereumTransaction'; } - /** @name SpCoreVoid (388) */ + /** @name SpCoreVoid (392) */ type SpCoreVoid = Null; - /** @name PalletUniqueSchedulerError (389) */ - interface PalletUniqueSchedulerError extends Enum { + /** @name PalletUniqueSchedulerV2Error (394) */ + interface PalletUniqueSchedulerV2Error extends Enum { readonly isFailedToSchedule: boolean; + readonly isAgendaIsExhausted: boolean; + readonly isScheduledCallCorrupted: boolean; + readonly isPreimageNotFound: boolean; + readonly isTooBigScheduledCall: boolean; readonly isNotFound: boolean; readonly isTargetBlockNumberInPast: boolean; - readonly isRescheduleNoChange: boolean; - readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange'; + readonly isNamed: boolean; + readonly type: 'FailedToSchedule' | 'AgendaIsExhausted' | 'ScheduledCallCorrupted' | 'PreimageNotFound' | 'TooBigScheduledCall' | 'NotFound' | 'TargetBlockNumberInPast' | 'Named'; } - /** @name UpDataStructsCollection (390) */ + /** @name UpDataStructsCollection (395) */ interface UpDataStructsCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; @@ -3432,7 +3490,7 @@ readonly flags: U8aFixed; } - /** @name UpDataStructsSponsorshipStateAccountId32 (391) */ + /** @name UpDataStructsSponsorshipStateAccountId32 (396) */ interface UpDataStructsSponsorshipStateAccountId32 extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; @@ -3442,43 +3500,43 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } - /** @name UpDataStructsProperties (393) */ + /** @name UpDataStructsProperties (398) */ interface UpDataStructsProperties extends Struct { readonly map: UpDataStructsPropertiesMapBoundedVec; readonly consumedSpace: u32; readonly spaceLimit: u32; } - /** @name UpDataStructsPropertiesMapBoundedVec (394) */ + /** @name UpDataStructsPropertiesMapBoundedVec (399) */ interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap {} - /** @name UpDataStructsPropertiesMapPropertyPermission (399) */ + /** @name UpDataStructsPropertiesMapPropertyPermission (404) */ interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap {} - /** @name UpDataStructsCollectionStats (406) */ + /** @name UpDataStructsCollectionStats (411) */ interface UpDataStructsCollectionStats extends Struct { readonly created: u32; readonly destroyed: u32; readonly alive: u32; } - /** @name UpDataStructsTokenChild (407) */ + /** @name UpDataStructsTokenChild (412) */ interface UpDataStructsTokenChild extends Struct { readonly token: u32; readonly collection: u32; } - /** @name PhantomTypeUpDataStructs (408) */ + /** @name PhantomTypeUpDataStructs (413) */ interface PhantomTypeUpDataStructs extends Vec> {} - /** @name UpDataStructsTokenData (410) */ + /** @name UpDataStructsTokenData (415) */ interface UpDataStructsTokenData extends Struct { readonly properties: Vec; readonly owner: Option; readonly pieces: u128; } - /** @name UpDataStructsRpcCollection (412) */ + /** @name UpDataStructsRpcCollection (417) */ interface UpDataStructsRpcCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; @@ -3494,13 +3552,13 @@ readonly flags: UpDataStructsRpcCollectionFlags; } - /** @name UpDataStructsRpcCollectionFlags (413) */ + /** @name UpDataStructsRpcCollectionFlags (418) */ interface UpDataStructsRpcCollectionFlags extends Struct { readonly foreign: bool; readonly erc721metadata: bool; } - /** @name RmrkTraitsCollectionCollectionInfo (414) */ + /** @name RmrkTraitsCollectionCollectionInfo (419) */ interface RmrkTraitsCollectionCollectionInfo extends Struct { readonly issuer: AccountId32; readonly metadata: Bytes; @@ -3509,7 +3567,7 @@ readonly nftsCount: u32; } - /** @name RmrkTraitsNftNftInfo (415) */ + /** @name RmrkTraitsNftNftInfo (420) */ interface RmrkTraitsNftNftInfo extends Struct { readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple; readonly royalty: Option; @@ -3518,13 +3576,13 @@ readonly pending: bool; } - /** @name RmrkTraitsNftRoyaltyInfo (417) */ + /** @name RmrkTraitsNftRoyaltyInfo (422) */ interface RmrkTraitsNftRoyaltyInfo extends Struct { readonly recipient: AccountId32; readonly amount: Permill; } - /** @name RmrkTraitsResourceResourceInfo (418) */ + /** @name RmrkTraitsResourceResourceInfo (423) */ interface RmrkTraitsResourceResourceInfo extends Struct { readonly id: u32; readonly resource: RmrkTraitsResourceResourceTypes; @@ -3532,26 +3590,26 @@ readonly pendingRemoval: bool; } - /** @name RmrkTraitsPropertyPropertyInfo (419) */ + /** @name RmrkTraitsPropertyPropertyInfo (424) */ interface RmrkTraitsPropertyPropertyInfo extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name RmrkTraitsBaseBaseInfo (420) */ + /** @name RmrkTraitsBaseBaseInfo (425) */ interface RmrkTraitsBaseBaseInfo extends Struct { readonly issuer: AccountId32; readonly baseType: Bytes; readonly symbol: Bytes; } - /** @name RmrkTraitsNftNftChild (421) */ + /** @name RmrkTraitsNftNftChild (426) */ interface RmrkTraitsNftNftChild extends Struct { readonly collectionId: u32; readonly nftId: u32; } - /** @name PalletCommonError (423) */ + /** @name PalletCommonError (428) */ interface PalletCommonError extends Enum { readonly isCollectionNotFound: boolean; readonly isMustBeTokenOwner: boolean; @@ -3590,7 +3648,7 @@ readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal'; } - /** @name PalletFungibleError (425) */ + /** @name PalletFungibleError (430) */ interface PalletFungibleError extends Enum { readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isFungibleItemsHaveNoId: boolean; @@ -3600,12 +3658,12 @@ readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletRefungibleItemData (426) */ + /** @name PalletRefungibleItemData (431) */ interface PalletRefungibleItemData extends Struct { readonly constData: Bytes; } - /** @name PalletRefungibleError (431) */ + /** @name PalletRefungibleError (436) */ interface PalletRefungibleError extends Enum { readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isWrongRefungiblePieces: boolean; @@ -3615,19 +3673,19 @@ readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletNonfungibleItemData (432) */ + /** @name PalletNonfungibleItemData (437) */ interface PalletNonfungibleItemData extends Struct { readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsPropertyScope (434) */ + /** @name UpDataStructsPropertyScope (439) */ interface UpDataStructsPropertyScope extends Enum { readonly isNone: boolean; readonly isRmrk: boolean; readonly type: 'None' | 'Rmrk'; } - /** @name PalletNonfungibleError (436) */ + /** @name PalletNonfungibleError (441) */ interface PalletNonfungibleError extends Enum { readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isNonfungibleItemsHaveNoAmount: boolean; @@ -3635,7 +3693,7 @@ readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren'; } - /** @name PalletStructureError (437) */ + /** @name PalletStructureError (442) */ interface PalletStructureError extends Enum { readonly isOuroborosDetected: boolean; readonly isDepthLimit: boolean; @@ -3644,7 +3702,7 @@ readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound'; } - /** @name PalletRmrkCoreError (438) */ + /** @name PalletRmrkCoreError (443) */ interface PalletRmrkCoreError extends Enum { readonly isCorruptedCollectionType: boolean; readonly isRmrkPropertyKeyIsTooLong: boolean; @@ -3668,7 +3726,7 @@ readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId'; } - /** @name PalletRmrkEquipError (440) */ + /** @name PalletRmrkEquipError (445) */ interface PalletRmrkEquipError extends Enum { readonly isPermissionError: boolean; readonly isNoAvailableBaseId: boolean; @@ -3680,7 +3738,7 @@ readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart'; } - /** @name PalletAppPromotionError (446) */ + /** @name PalletAppPromotionError (451) */ interface PalletAppPromotionError extends Enum { readonly isAdminNotSet: boolean; readonly isNoPermission: boolean; @@ -3691,7 +3749,7 @@ readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation'; } - /** @name PalletForeignAssetsModuleError (447) */ + /** @name PalletForeignAssetsModuleError (452) */ interface PalletForeignAssetsModuleError extends Enum { readonly isBadLocation: boolean; readonly isMultiLocationExisted: boolean; @@ -3700,7 +3758,7 @@ readonly type: 'BadLocation' | 'MultiLocationExisted' | 'AssetIdNotExists' | 'AssetIdExisted'; } - /** @name PalletEvmError (450) */ + /** @name PalletEvmError (454) */ interface PalletEvmError extends Enum { readonly isBalanceLow: boolean; readonly isFeeOverflow: boolean; @@ -3708,10 +3766,14 @@ readonly isWithdrawFailed: boolean; readonly isGasPriceTooLow: boolean; readonly isInvalidNonce: boolean; - readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce'; + readonly isGasLimitTooLow: boolean; + readonly isGasLimitTooHigh: boolean; + readonly isUndefined: boolean; + readonly isReentrancy: boolean; + readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy'; } - /** @name FpRpcTransactionStatus (453) */ + /** @name FpRpcTransactionStatus (457) */ interface FpRpcTransactionStatus extends Struct { readonly transactionHash: H256; readonly transactionIndex: u32; @@ -3722,10 +3784,10 @@ readonly logsBloom: EthbloomBloom; } - /** @name EthbloomBloom (455) */ + /** @name EthbloomBloom (459) */ interface EthbloomBloom extends U8aFixed {} - /** @name EthereumReceiptReceiptV3 (457) */ + /** @name EthereumReceiptReceiptV3 (461) */ interface EthereumReceiptReceiptV3 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumReceiptEip658ReceiptData; @@ -3736,7 +3798,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumReceiptEip658ReceiptData (458) */ + /** @name EthereumReceiptEip658ReceiptData (462) */ interface EthereumReceiptEip658ReceiptData extends Struct { readonly statusCode: u8; readonly usedGas: U256; @@ -3744,14 +3806,14 @@ readonly logs: Vec; } - /** @name EthereumBlock (459) */ + /** @name EthereumBlock (463) */ interface EthereumBlock extends Struct { readonly header: EthereumHeader; readonly transactions: Vec; readonly ommers: Vec; } - /** @name EthereumHeader (460) */ + /** @name EthereumHeader (464) */ interface EthereumHeader extends Struct { readonly parentHash: H256; readonly ommersHash: H256; @@ -3770,24 +3832,24 @@ readonly nonce: EthereumTypesHashH64; } - /** @name EthereumTypesHashH64 (461) */ + /** @name EthereumTypesHashH64 (465) */ interface EthereumTypesHashH64 extends U8aFixed {} - /** @name PalletEthereumError (466) */ + /** @name PalletEthereumError (470) */ interface PalletEthereumError extends Enum { readonly isInvalidSignature: boolean; readonly isPreLogExists: boolean; readonly type: 'InvalidSignature' | 'PreLogExists'; } - /** @name PalletEvmCoderSubstrateError (467) */ + /** @name PalletEvmCoderSubstrateError (471) */ interface PalletEvmCoderSubstrateError extends Enum { readonly isOutOfGas: boolean; readonly isOutOfFund: boolean; readonly type: 'OutOfGas' | 'OutOfFund'; } - /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (468) */ + /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (472) */ interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; @@ -3797,7 +3859,7 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } - /** @name PalletEvmContractHelpersSponsoringModeT (469) */ + /** @name PalletEvmContractHelpersSponsoringModeT (473) */ interface PalletEvmContractHelpersSponsoringModeT extends Enum { readonly isDisabled: boolean; readonly isAllowlisted: boolean; @@ -3805,7 +3867,7 @@ readonly type: 'Disabled' | 'Allowlisted' | 'Generous'; } - /** @name PalletEvmContractHelpersError (475) */ + /** @name PalletEvmContractHelpersError (479) */ interface PalletEvmContractHelpersError extends Enum { readonly isNoPermission: boolean; readonly isNoPendingSponsor: boolean; @@ -3813,24 +3875,25 @@ readonly type: 'NoPermission' | 'NoPendingSponsor' | 'TooManyMethodsHaveSponsoredLimit'; } - /** @name PalletEvmMigrationError (476) */ + /** @name PalletEvmMigrationError (480) */ interface PalletEvmMigrationError extends Enum { readonly isAccountNotEmpty: boolean; readonly isAccountIsNotMigrating: boolean; - readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating'; + readonly isBadEvent: boolean; + readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating' | 'BadEvent'; } - /** @name PalletMaintenanceError (477) */ + /** @name PalletMaintenanceError (481) */ type PalletMaintenanceError = Null; - /** @name PalletTestUtilsError (478) */ + /** @name PalletTestUtilsError (482) */ interface PalletTestUtilsError extends Enum { readonly isTestPalletDisabled: boolean; readonly isTriggerRollback: boolean; readonly type: 'TestPalletDisabled' | 'TriggerRollback'; } - /** @name SpRuntimeMultiSignature (480) */ + /** @name SpRuntimeMultiSignature (484) */ interface SpRuntimeMultiSignature extends Enum { readonly isEd25519: boolean; readonly asEd25519: SpCoreEd25519Signature; @@ -3841,40 +3904,40 @@ readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa'; } - /** @name SpCoreEd25519Signature (481) */ + /** @name SpCoreEd25519Signature (485) */ interface SpCoreEd25519Signature extends U8aFixed {} - /** @name SpCoreSr25519Signature (483) */ + /** @name SpCoreSr25519Signature (487) */ interface SpCoreSr25519Signature extends U8aFixed {} - /** @name SpCoreEcdsaSignature (484) */ + /** @name SpCoreEcdsaSignature (488) */ interface SpCoreEcdsaSignature extends U8aFixed {} - /** @name FrameSystemExtensionsCheckSpecVersion (487) */ + /** @name FrameSystemExtensionsCheckSpecVersion (491) */ type FrameSystemExtensionsCheckSpecVersion = Null; - /** @name FrameSystemExtensionsCheckTxVersion (488) */ + /** @name FrameSystemExtensionsCheckTxVersion (492) */ type FrameSystemExtensionsCheckTxVersion = Null; - /** @name FrameSystemExtensionsCheckGenesis (489) */ + /** @name FrameSystemExtensionsCheckGenesis (493) */ type FrameSystemExtensionsCheckGenesis = Null; - /** @name FrameSystemExtensionsCheckNonce (492) */ + /** @name FrameSystemExtensionsCheckNonce (496) */ interface FrameSystemExtensionsCheckNonce extends Compact {} - /** @name FrameSystemExtensionsCheckWeight (493) */ + /** @name FrameSystemExtensionsCheckWeight (497) */ type FrameSystemExtensionsCheckWeight = Null; - /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (494) */ + /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (498) */ type OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance = Null; - /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (495) */ + /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (499) */ interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact {} - /** @name OpalRuntimeRuntime (496) */ + /** @name OpalRuntimeRuntime (500) */ type OpalRuntimeRuntime = Null; - /** @name PalletEthereumFakeTransactionFinalizer (497) */ + /** @name PalletEthereumFakeTransactionFinalizer (501) */ type PalletEthereumFakeTransactionFinalizer = Null; } // declare module --- a/tests/src/maintenanceMode.seqtest.ts +++ b/tests/src/maintenanceMode.seqtest.ts @@ -237,7 +237,7 @@ expect(tokenId).to.be.equal('1'); await expect(contract.methods.mintWithTokenURI(receiver, 'Test URI').send()) - .to.be.rejectedWith(/submit transaction to pool failed: Pool\(InvalidTransaction\(InvalidTransaction::Call\)\)/); + .to.be.rejectedWith(/Returned error: unknown error/); await expect(contract.methods.ownerOf(tokenId).call()).rejectedWith(/token not found/); --- a/tests/src/refungible.test.ts +++ b/tests/src/refungible.test.ts @@ -255,3 +255,43 @@ }); }); +describe('Refungible negative tests', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + let bob: IKeyringPair; + let charlie: IKeyringPair; + + before(async function() { + await usingPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = await privateKey({filename: __filename}); + [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor); + }); + }); + + itSub('Cannot transfer incorrect amount of token pieces', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const tokenAlice = await collection.mintToken(alice, 10n, {Substrate: alice.address}); + const tokenBob = await collection.mintToken(alice, 10n, {Substrate: bob.address}); + + // 1. Alice cannot transfer Bob's token: + await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 10n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow'); + + // 2. Alice cannot transfer non-existing token: + await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.TokenValueTooLow'); + await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); + + // 3. Zero transfer allowed (EIP-20): + await tokenAlice.transfer(alice, {Substrate: charlie.address}, 0n); + + expect(await tokenAlice.getTop10Owners()).to.deep.eq([{Substrate: alice.address}]); + expect(await tokenBob.getTop10Owners()).to.deep.eq([{Substrate: bob.address}]); + expect(await tokenAlice.getBalance({Substrate: alice.address})).to.eq(10n); + expect(await tokenBob.getBalance({Substrate: bob.address})).to.eq(10n); + expect(await tokenBob.getBalance({Substrate: charlie.address})).to.eq(0n); + }); +}); --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -122,6 +122,7 @@ }); }); + itSub('[nft] Transfer with not existed collection_id', async ({helper}) => { const collectionId = (1 << 32) - 1; await expect(helper.nft.transferToken(alice, collectionId, 1, {Substrate: bob.address})) @@ -191,6 +192,25 @@ .to.be.rejectedWith(/common\.TokenValueTooLow/); }); + itSub('Zero transfer NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'}); + const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address}); + const tokenBob = await collection.mintToken(alice, {Substrate: bob.address}); + // 1. Zero transfer of own tokens allowed: + await helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: bob.address}, collection.collectionId, tokenAlice.tokenId, 0]); + // 2. Zero transfer of non-owned tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, tokenBob.tokenId, 0])).to.be.rejectedWith('common.NoPermission'); + // 3. Zero transfer of non-existing tokens not allowed: + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, 10, 0])).to.be.rejectedWith('common.TokenNotFound'); + expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: alice.address}); + expect(await tokenBob.getOwner()).to.deep.eq({Substrate: bob.address}); + // 4. Storage is not corrupted: + await tokenAlice.transfer(alice, {Substrate: bob.address}); + await tokenBob.transfer(bob, {Substrate: alice.address}); + expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: bob.address}); + expect(await tokenBob.getOwner()).to.deep.eq({Substrate: alice.address}); + }); + itSub('[nft] Transfer with deleted item_id', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'}); const nft = await collection.mintToken(alice); --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -349,4 +349,27 @@ {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); + + itSub('zero transfer NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Zero', description: 'Zero transfer', tokenPrefix: 'TF'}); + const notApprovedNft = await collection.mintToken(alice, {Substrate: bob.address}); + const approvedNft = await collection.mintToken(alice, {Substrate: bob.address}); + await approvedNft.approve(bob, {Substrate: alice.address}); + + // 1. Cannot zero transferFrom (non-existing token) + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transferFrom', [{Substrate: bob.address}, {Substrate: alice.address}, collection.collectionId, 9999, 0])).to.be.rejectedWith('common.ApprovedValueTooLow'); + // 2. Cannot zero transferFrom (not approved token) + await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transferFrom', [{Substrate: bob.address}, {Substrate: alice.address}, collection.collectionId, notApprovedNft.tokenId, 0])).to.be.rejectedWith('common.ApprovedValueTooLow'); + // 3. Can zero transferFrom (approved token): + await helper.executeExtrinsic(alice, 'api.tx.unique.transferFrom', [{Substrate: bob.address}, {Substrate: alice.address}, collection.collectionId, approvedNft.tokenId, 0]); + + // 4.1 approvedNft still approved: + expect(await approvedNft.isApproved({Substrate: alice.address})).to.be.true; + // 4.2 bob is still the owner: + expect(await approvedNft.getOwner()).to.deep.eq({Substrate: bob.address}); + expect(await notApprovedNft.getOwner()).to.deep.eq({Substrate: bob.address}); + // 4.3 Alice can transfer approved nft: + await approvedNft.transferFrom(alice, {Substrate: bob.address}, {Substrate: alice.address}); + expect(await approvedNft.getOwner()).to.deep.eq({Substrate: alice.address}); + }); }); --- a/tests/src/util/playgrounds/unique.ts +++ b/tests/src/util/playgrounds/unique.ts @@ -2484,7 +2484,7 @@ * @param ethCrossAccount etherium cross account * @returns substrate cross account id */ - convertCrossAccountFromEthCrossAcoount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId { + convertCrossAccountFromEthCrossAccount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId { if (ethCrossAccount.sub === '0') { return {Ethereum: ethCrossAccount.eth.toLocaleLowerCase()}; } -- gitstuff