diff --git a/.github/workflows/check-bittensor-e2e-tests.yml.yml b/.github/workflows/check-bittensor-e2e-tests.yml.yml index f204f870a2..1f0878a548 100644 --- a/.github/workflows/check-bittensor-e2e-tests.yml.yml +++ b/.github/workflows/check-bittensor-e2e-tests.yml.yml @@ -10,49 +10,25 @@ concurrency: on: pull_request: - branches: - - devnet - - devnet-ready - - testnet - - testnet-ready - - main + branches: ["*"] types: [opened, synchronize, reopened, labeled, unlabeled] + workflow_dispatch: + inputs: + verbose: + description: "Output more information when triggered manually" + required: false + default: "" + env: CARGO_TERM_COLOR: always VERBOSE: ${{ github.event.inputs.verbose }} jobs: - apply-label-to-new-pr: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.draft == false }} - outputs: - should_continue: ${{ steps.check.outputs.should_continue }} - steps: - - name: Check - id: check - run: | - ACTION="${{ github.event.action }}" - if [[ "$ACTION" == "opened" || "$ACTION" == "reopened" ]]; then - echo "should_continue=true" >> $GITHUB_OUTPUT - else - echo "should_continue=false" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Add label - if: steps.check.outputs.should_continue == 'true' - uses: actions-ecosystem/action-add-labels@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: run-bittensor-e2e-tests - check-label: - needs: apply-label-to-new-pr runs-on: ubuntu-latest - if: always() outputs: - run-bittensor-e2e-tests: ${{ steps.get-labels.outputs.run-bittensor-e2e-tests }} + skip-bittensor-e2e-tests: ${{ steps.get-labels.outputs.skip-bittensor-e2e-tests }} steps: - name: Check out repository uses: actions/checkout@v4 @@ -62,19 +38,17 @@ jobs: run: | LABELS=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') echo "Current labels: $LABELS" - if echo "$LABELS" | grep -q "run-bittensor-e2e-tests"; then - echo "run-bittensor-e2e-tests=true" >> $GITHUB_ENV - echo "::set-output name=run-bittensor-e2e-tests::true" + if echo "$LABELS" | grep -q "skip-bittensor-e2e-tests"; then + echo "skip-bittensor-e2e-tests=true" >> $GITHUB_OUTPUT else - echo "run-bittensor-e2e-tests=false" >> $GITHUB_ENV - echo "::set-output name=run-bittensor-e2e-tests::false" + echo "skip-bittensor-e2e-tests=false" >> $GITHUB_OUTPUT fi env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} find-btcli-e2e-tests: needs: check-label - if: always() && needs.check-label.outputs.run-bittensor-e2e-tests == 'true' + if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' runs-on: ubuntu-latest outputs: test-files: ${{ steps.get-btcli-tests.outputs.test-files }} @@ -94,12 +68,12 @@ jobs: id: get-btcli-tests run: | test_files=$(find ${{ github.workspace }}/btcli/tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))') - echo "::set-output name=test-files::$test_files" + echo "test-files=$test_files" >> $GITHUB_OUTPUT shell: bash find-sdk-e2e-tests: needs: check-label - if: always() && needs.check-label.outputs.run-bittensor-e2e-tests == 'true' + if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' runs-on: ubuntu-latest outputs: test-files: ${{ steps.get-sdk-tests.outputs.test-files }} @@ -119,7 +93,7 @@ jobs: id: get-sdk-tests run: | test_files=$(find ${{ github.workspace }}/bittensor/tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))') - echo "::set-output name=test-files::$test_files" + echo "test-files=$test_files" >> $GITHUB_OUTPUT shell: bash build-image-with-current-branch: @@ -128,6 +102,13 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Patch non-fast-block node + run: | + chmod +x ./scripts/localnet_patch.sh + ./scripts/localnet_patch.sh - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -153,7 +134,7 @@ jobs: - check-label - find-btcli-e2e-tests - build-image-with-current-branch - if: always() && needs.check-label.outputs.run-bittensor-e2e-tests == 'true' + if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' runs-on: ubuntu-latest strategy: fail-fast: false @@ -182,6 +163,8 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 + with: + enable-cache: 'false' - name: Create Python virtual environment working-directory: ${{ github.workspace }} @@ -201,10 +184,6 @@ jobs: uv run --active pip install '.[dev]' uv run --active pip install pytest - - name: Install uv dependencies - working-directory: ${{ github.workspace }}/btcli - run: uv sync --all-extras --dev - - name: Download Cached Docker Image uses: actions/download-artifact@v4 with: @@ -213,6 +192,9 @@ jobs: - name: Load Docker Image run: docker load -i subtensor-localnet.tar + - name: Retag Docker Image + run: docker tag localnet ghcr.io/opentensor/subtensor-localnet:devnet-ready + # - name: Run tests # working-directory: ${{ github.workspace }}/btcli # run: | @@ -223,6 +205,7 @@ jobs: working-directory: ${{ github.workspace }}/btcli run: | source ${{ github.workspace }}/venv/bin/activate + export SKIP_PULL=1 set +e for i in 1 2; do echo "🔁 Attempt $i: Running tests" @@ -248,7 +231,7 @@ jobs: - check-label - find-sdk-e2e-tests - build-image-with-current-branch - if: always() && needs.check-label.outputs.run-bittensor-e2e-tests == 'true' + if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' runs-on: ubuntu-latest strategy: fail-fast: false @@ -277,6 +260,8 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 + with: + enable-cache: 'false' - name: Create Python virtual environment working-directory: ${{ github.workspace }} @@ -296,10 +281,6 @@ jobs: uv run --active pip install '.[dev]' uv run --active pip install pytest - - name: Install uv dependencies - working-directory: ${{ github.workspace }}/bittensor - run: uv sync --all-extras --dev - - name: Download Cached Docker Image uses: actions/download-artifact@v4 with: @@ -308,6 +289,9 @@ jobs: - name: Load Docker Image run: docker load -i subtensor-localnet.tar + - name: Retag Docker Image + run: docker tag localnet ghcr.io/opentensor/subtensor-localnet:devnet-ready + # - name: Run tests # working-directory: ${{ github.workspace }}/bittensor # run: | @@ -318,6 +302,7 @@ jobs: working-directory: ${{ github.workspace }}/bittensor run: | source ${{ github.workspace }}/venv/bin/activate + export SKIP_PULL=1 set +e for i in 1 2; do echo "🔁 Attempt $i: Running tests" @@ -335,4 +320,4 @@ jobs: echo "🕒 Retrying..." sleep 5 fi - done \ No newline at end of file + done diff --git a/.github/workflows/require-clean-merges.yml b/.github/workflows/require-clean-merges.yml index c00a4b47e2..ac0a5f31fe 100644 --- a/.github/workflows/require-clean-merges.yml +++ b/.github/workflows/require-clean-merges.yml @@ -34,6 +34,14 @@ jobs: else echo "MERGE_BRANCHES=devnet-ready devnet testnet main" >> $GITHUB_ENV fi + + - name: Add Fork Remote and Fetch PR Branch + if: github.event.pull_request.head.repo.fork == true + run: | + PR_BRANCH="${{ github.event.pull_request.head.ref }}" + PR_FORK="${{ github.event.pull_request.head.repo.clone_url }}" + git remote add fork $PR_FORK + git fetch --no-tags --prune fork $PR_BRANCH - name: Check Merge Cleanliness run: | @@ -42,25 +50,33 @@ jobs: echo "Fetching all branches..." git fetch --all --prune + if [[ "${{github.event.pull_request.head.repo.fork}}" == "true" ]]; then + PR_BRANCH_REF="fork/$PR_BRANCH" + echo "Using fork reference: $PR_BRANCH_REF" + else + PR_BRANCH_REF="origin/$PR_BRANCH" + echo "Using origin reference: $PR_BRANCH_REF" + fi + echo "Checking out PR branch: $PR_BRANCH" - git checkout $PR_BRANCH - git reset --hard origin/$PR_BRANCH + git checkout $PR_BRANCH_REF + git reset --hard $PR_BRANCH_REF # Configure a temporary Git identity to allow merging git config --local user.email "github-actions@github.com" git config --local user.name "GitHub Actions" for branch in $MERGE_BRANCHES; do - echo "Checking merge from $branch into $PR_BRANCH..." + echo "Checking merge from $branch into $PR_BRANCH_REF..." # Ensure PR branch is up to date - git reset --hard origin/$PR_BRANCH + git reset --hard $PR_BRANCH_REF # Merge without committing to check for conflicts if git merge --no-commit --no-ff origin/$branch; then - echo "✅ Merge from $branch into $PR_BRANCH is clean." + echo "✅ Merge from $branch into $PR_BRANCH_REF is clean." else - echo "❌ Merge conflict detected when merging $branch into $PR_BRANCH" + echo "❌ Merge conflict detected when merging $branch into $PR_BRANCH_REF" exit 1 fi diff --git a/.github/workflows/run-benchmarks.yml b/.github/workflows/run-benchmarks.yml index 6040485eca..7d4cb9c2a7 100644 --- a/.github/workflows/run-benchmarks.yml +++ b/.github/workflows/run-benchmarks.yml @@ -24,18 +24,20 @@ jobs: if: ${{ env.SKIP_BENCHMARKS != '1' }} uses: actions/checkout@v4 with: - ref: ${{ github.head_ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} fetch-depth: 0 - name: Install GitHub CLI - if: ${{ env.SKIP_BENCHMARKS != '1' }} + # We disallow skipping benchmarks for PRs from forks to avoid exposing secrets + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | sudo apt-get update sudo apt-get install -y gh echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token - name: Check skip label - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then @@ -50,7 +52,7 @@ jobs: sudo apt-get install -y clang curl libssl-dev llvm libudev-dev protobuf-compiler - name: Check skip label - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then @@ -66,7 +68,7 @@ jobs: toolchain: stable - name: Check skip label - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then @@ -81,7 +83,7 @@ jobs: key: bench-${{ hashFiles('**/Cargo.lock') }} - name: Check skip label - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then @@ -95,7 +97,7 @@ jobs: cargo build --profile production -p node-subtensor --features runtime-benchmarks - name: Check skip label - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then @@ -110,7 +112,7 @@ jobs: ./scripts/benchmark_action.sh - name: Check skip label after run - if: ${{ env.SKIP_BENCHMARKS != '1' }} + if: ${{ github.event.pull_request.head.repo.full_name == github.repository && env.SKIP_BENCHMARKS != '1' }} run: | labels=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name') if echo "$labels" | grep -q "skip-validate-benchmarks"; then diff --git a/.gitignore b/.gitignore index 5921b6b937..f6a9e635e2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ **/*.rs.bk **/*.lock +!evm-tests/yarn.lock *.ipynb diff --git a/Cargo.lock b/Cargo.lock index b0c56ffb2e..5c7b02714e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,18 +23,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli 0.31.0", + "gimli 0.31.1", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -77,19 +77,19 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom", + "getrandom 0.2.16", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.3", "once_cell", "version_check", "zerocopy", @@ -106,9 +106,45 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alloy-primitives" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.0.1", + "foldhash", + "indexmap 2.9.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash 2.1.1", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +dependencies = [ + "arrayvec 0.7.6", + "bytes", +] [[package]] name = "android-tzdata" @@ -127,9 +163,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -142,43 +178,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "approx" @@ -200,7 +237,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -210,8 +247,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" dependencies = [ "ark-ec", - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -223,7 +260,7 @@ dependencies = [ "ark-bls12-377", "ark-ec", "ark-models-ext", - "ark-std", + "ark-std 0.4.0", ] [[package]] @@ -233,9 +270,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -246,10 +283,10 @@ checksum = "b1dc4b3d08f19e8ec06e949712f95b8361e43f1391d94f65e4234df03480631c" dependencies = [ "ark-bls12-381", "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-models-ext", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -260,8 +297,8 @@ checksum = "2e0605daf0cc5aa2034b78d008aaf159f56901d92a52ee4f6ecdfdac4f426700" dependencies = [ "ark-bls12-377", "ark-ec", - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -272,9 +309,9 @@ checksum = "ccee5fba47266f460067588ee1bf070a9c760bf2050c1c509982c5719aadb4f2" dependencies = [ "ark-bw6-761", "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-models-ext", - "ark-std", + "ark-std 0.4.0", ] [[package]] @@ -284,16 +321,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3a13b34da09176a8baba701233fdffbaa7c1b1192ce031a3da4e55ce1f1a56" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-r1cs-std", "ark-relations", - "ark-serialize", + "ark-serialize 0.4.2", "ark-snark", - "ark-std", + "ark-std 0.4.0", "blake2 0.10.6", "derivative", "digest 0.10.7", - "sha2 0.10.8", + "sha2 0.10.9", "tracing", ] @@ -303,10 +340,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "ark-ff", + "ark-ff 0.4.2", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", "itertools 0.10.5", @@ -323,8 +360,8 @@ checksum = "b10d901b9ac4b38f9c32beacedfadcdd64e46f8d7f8e88c1ae1060022cf6f6c6" dependencies = [ "ark-bls12-377", "ark-ec", - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -335,9 +372,9 @@ checksum = "524a4fb7540df2e1a8c2e67a83ba1d1e6c3947f4f9342cc2359fc2e789ad731d" dependencies = [ "ark-ec", "ark-ed-on-bls12-377", - "ark-ff", + "ark-ff 0.4.2", "ark-models-ext", - "ark-std", + "ark-std 0.4.0", ] [[package]] @@ -348,8 +385,8 @@ checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" dependencies = [ "ark-bls12-381", "ark-ec", - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -360,9 +397,27 @@ checksum = "d15185f1acb49a07ff8cbe5f11a1adc5a93b19e211e325d826ae98e98e124346" dependencies = [ "ark-ec", "ark-ed-on-bls12-381-bandersnatch", - "ark-ff", + "ark-ff 0.4.2", "ark-models-ext", - "ark-std", + "ark-std 0.4.0", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", ] [[package]] @@ -371,10 +426,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "digest 0.10.7", "itertools 0.10.5", @@ -385,6 +440,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -395,6 +460,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -415,9 +492,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9eab5d4b5ff2f228b763d38442adc9b084b0a465409b059fac5c2308835ec2" dependencies = [ "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", ] @@ -427,9 +504,9 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", ] @@ -441,9 +518,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de1d1472e5cb020cb3405ce2567c91c8d43f21b674aef37b0202f5c3304761db" dependencies = [ "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-relations", - "ark-std", + "ark-std 0.4.0", "derivative", "num-bigint", "num-integer", @@ -457,8 +534,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00796b6efc05a3f48225e59cb6a2cda78881e7c390872d5786aaf112f31fb4f0" dependencies = [ - "ark-ff", - "ark-std", + "ark-ff 0.4.2", + "ark-std 0.4.0", "tracing", "tracing-subscriber 0.2.25", ] @@ -470,9 +547,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51bd73bb6ddb72630987d37fa963e99196896c0d0ea81b7c894567e74a2f83af" dependencies = [ "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "parity-scale-codec", "scale-info", ] @@ -484,13 +561,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" dependencies = [ "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "parity-scale-codec", "scale-info", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + [[package]] name = "ark-serialize" version = "0.4.2" @@ -498,7 +585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-serialize-derive", - "ark-std", + "ark-std 0.4.0", "digest 0.10.7", "num-bigint", ] @@ -520,10 +607,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84d3cc6833a335bb8a600241889ead68ee89a3cf8448081fb7694c0fe503da63" dependencies = [ - "ark-ff", + "ark-ff 0.4.2", "ark-relations", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", ] [[package]] @@ -533,7 +630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", "rayon", ] @@ -549,6 +646,15 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.7.6" @@ -567,23 +673,23 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] [[package]] name = "asn1-rs" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ - "asn1-rs-derive 0.5.1", + "asn1-rs-derive 0.6.0", "asn1-rs-impl 0.2.0", "displaydoc", "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 2.0.12", "time", ] @@ -601,14 +707,14 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", - "synstructure 0.13.1", + "syn 2.0.103", + "synstructure 0.13.2", ] [[package]] @@ -630,7 +736,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -650,11 +756,48 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock", "cfg-if", @@ -663,7 +806,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 0.38.37", + "rustix 1.0.7", "slab", "tracing", "windows-sys 0.59.0", @@ -675,20 +818,74 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" +dependencies = [ + "async-channel 2.3.1", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.4.0", + "futures-lite", + "rustix 1.0.7", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.0.7", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -713,6 +910,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-take" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -732,32 +935,32 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ - "addr2line 0.24.1", + "addr2line 0.24.2", "cfg-if", "libc", "miniz_oxide", - "object 0.36.4", + "object 0.36.7", "rustc-demangle", "windows-targets 0.52.6", ] @@ -774,6 +977,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "base64" version = "0.13.1" @@ -794,9 +1003,28 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "beef" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "binary-merkle-tree" +version = "16.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", +] [[package]] name = "bincode" @@ -819,15 +1047,58 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.22", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "bip32" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db40d3dfbeab4e031d78c844642fa0caa0b0db11ce1607ac9d2986dff1405c69" +dependencies = [ + "bs58", + "hmac 0.12.1", + "k256", + "rand_core 0.6.4", + "ripemd", + "secp256k1 0.27.0", + "sha2 0.10.9", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "bip39" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d193de1f7487df1914d3a568b772458861d33f9c54249612cc2893d6915054" +dependencies = [ + "bitcoin_hashes", + "serde", + "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitcoin-internals" version = "0.2.0" @@ -852,9 +1123,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" @@ -864,6 +1135,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -889,39 +1161,49 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + [[package]] name = "blake2b_simd" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" dependencies = [ "arrayref", - "arrayvec", - "constant_time_eq", + "arrayvec 0.7.6", + "constant_time_eq 0.3.1", ] [[package]] name = "blake2s_simd" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +checksum = "e90f7deecfac93095eb874a40febd69427776e24e1bd7f87f33ac62d6f0174df" dependencies = [ "arrayref", - "arrayvec", - "constant_time_eq", + "arrayvec 0.7.6", + "constant_time_eq 0.3.1", ] [[package]] name = "blake3" -version = "1.5.4" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.6", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.3.1", ] [[package]] @@ -942,11 +1224,24 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bounded-collections" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32385ecb91a31bddaf908e8dcf4a15aef1bcd3913cc03ebfad02ff6d568abc1" +checksum = "64ad8a0bed7827f0b07a5d23cec2e58cc02038a99e4ca81616cb2bb2025f804d" dependencies = [ "log", "parity-scale-codec", @@ -955,10 +1250,13 @@ dependencies = [ ] [[package]] -name = "bs58" -version = "0.4.0" +name = "bounded-vec" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce" +dependencies = [ + "thiserror 1.0.69", +] [[package]] name = "bs58" @@ -966,6 +1264,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ + "sha2 0.10.9", "tinyvec", ] @@ -980,15 +1279,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "byte-tools" @@ -998,9 +1297,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] name = "byteorder" @@ -1010,18 +1309,17 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "bzip2-sys" -version = "0.1.11+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] @@ -1037,18 +1335,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -1061,10 +1359,10 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.23", + "semver 1.0.26", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1075,15 +1373,21 @@ checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "jobserver", "libc", "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1104,9 +1408,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -1115,8 +1419,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] -name = "chacha" -version = "0.3.0" +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862" dependencies = [ @@ -1150,9 +1460,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1160,7 +1470,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1178,15 +1488,14 @@ dependencies = [ [[package]] name = "cid" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a" dependencies = [ "core2", "multibase", - "multihash 0.18.1", - "serde", - "unsigned-varint 0.7.2", + "multihash 0.19.3", + "unsigned-varint 0.8.0", ] [[package]] @@ -1222,9 +1531,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -1232,50 +1541,62 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "coarsetime" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] [[package]] name = "codespan-reporting" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ + "serde", "termcolor", "unicode-width", ] [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" @@ -1289,12 +1610,11 @@ dependencies = [ [[package]] name = "comfy-table" -version = "7.1.1" +version = "7.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" +checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a" dependencies = [ - "strum 0.26.3", - "strum_macros 0.26.4", + "unicode-segmentation", "unicode-width", ] @@ -1315,15 +1635,28 @@ dependencies = [ [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static", "libc", + "once_cell", "unicode-width", - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "const-hex" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", ] [[package]] @@ -1347,11 +1680,37 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom", + "getrandom 0.2.16", "once_cell", "tiny-keccak", ] +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.3.1" @@ -1380,6 +1739,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1406,9 +1775,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -1513,9 +1882,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1535,11 +1904,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1565,15 +1949,15 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" @@ -1582,7 +1966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", - "rand_core", + "rand_core 0.6.4", "subtle 2.6.1", "zeroize", ] @@ -1594,8 +1978,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", - "rand_core", - "typenum 1.17.0", + "rand_core 0.6.4", + "typenum 1.18.0", ] [[package]] @@ -1627,6 +2011,117 @@ dependencies = [ "cipher 0.4.4", ] +[[package]] +name = "cumulus-client-parachain-inherent" +version = "0.15.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-relay-chain-interface", + "cumulus-test-relay-sproof-builder", + "parity-scale-codec", + "sc-client-api", + "sp-api", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "sp-storage 22.0.0", + "sp-trie", + "tracing", +] + +[[package]] +name = "cumulus-primitives-core" +version = "0.17.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", + "sp-trie", + "staging-xcm", +] + +[[package]] +name = "cumulus-primitives-parachain-inherent" +version = "0.17.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "sp-trie", +] + +[[package]] +name = "cumulus-primitives-proof-size-hostfunction" +version = "0.11.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "sp-externalities 0.30.0", + "sp-runtime-interface 29.0.0", + "sp-trie", +] + +[[package]] +name = "cumulus-primitives-storage-weight-reclaim" +version = "9.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "cumulus-primitives-core", + "cumulus-primitives-proof-size-hostfunction", + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + +[[package]] +name = "cumulus-relay-chain-interface" +version = "0.21.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "futures", + "jsonrpsee-core 0.24.9", + "parity-scale-codec", + "polkadot-overseer", + "sc-client-api", + "sp-api", + "sp-blockchain", + "sp-state-machine", + "sp-version", + "thiserror 1.0.69", +] + +[[package]] +name = "cumulus-test-relay-sproof-builder" +version = "0.17.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "cumulus-primitives-core", + "parity-scale-codec", + "polkadot-primitives", + "sp-runtime", + "sp-state-machine", + "sp-trie", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1651,86 +2146,136 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "cxx" -version = "1.0.128" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ccead7d199d584d139148b04b4a368d1ec7556a1d9ea2548febb1b9d49f9a4" +checksum = "a71ea7f29c73f7ffa64c50b83c9fe4d3a6d4be89a86b009eb80d5a6d3429d741" dependencies = [ "cc", + "cxxbridge-cmd", "cxxbridge-flags", "cxxbridge-macro", + "foldhash", "link-cplusplus", ] [[package]] name = "cxx-build" -version = "1.0.128" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77953e99f01508f89f55c494bfa867171ef3a6c8cea03d26975368f2121a5c1" +checksum = "36a8232661d66dcf713394726157d3cfe0a89bfc85f52d6e9f9bbc2306797fe7" dependencies = [ "cc", "codespan-reporting", - "once_cell", "proc-macro2", "quote", "scratch", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f44296c8693e9ea226a48f6a122727f77aa9e9e338380cb021accaeeb7ee279" +dependencies = [ + "clap", + "codespan-reporting", + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] name = "cxxbridge-flags" -version = "1.0.128" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65777e06cc48f0cb0152024c77d6cf9e4bdb4408e7b48bea993d42fa0f5b02b6" +checksum = "c42f69c181c176981ae44ba9876e2ea41ce8e574c296b38d06925ce9214fb8e4" [[package]] name = "cxxbridge-macro" -version = "1.0.128" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98532a60dedaebc4848cb2cba5023337cc9ea3af16a5b062633fabfd9f18fb60" +checksum = "8faff5d4467e0709448187df29ccbf3b0982cc426ee444a193f87b11afb565a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "rustversion", + "syn 2.0.103", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", ] [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling_core" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ - "darling_core", - "darling_macro", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", ] [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.90", + "strsim 0.11.1", + "syn 2.0.103", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -1743,20 +2288,20 @@ dependencies = [ "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.11", ] [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-encoding-macro" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1764,19 +2309,19 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "zeroize", @@ -1798,11 +2343,11 @@ dependencies = [ [[package]] name = "der-parser" -version = "9.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs 0.7.1", "displaydoc", "nom", "num-bigint", @@ -1812,9 +2357,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -1839,20 +2384,72 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "derive-where" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", + "unicode-xid", ] [[package]] @@ -1941,23 +2538,23 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "docify" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" dependencies = [ "common-path", "derive-syn-parse", @@ -1965,9 +2562,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.90", + "syn 2.0.103", "termcolor", - "toml 0.8.19", + "toml 0.8.23", "walkdir", ] @@ -1983,17 +2580,23 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dtoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" [[package]] name = "dyn-clonable" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +checksum = "a36efbb9bfd58e1723780aa04b61aba95ace6a05d9ffabfdb0b43672552f0805" dependencies = [ "dyn-clonable-impl", "dyn-clone", @@ -2001,20 +2604,20 @@ dependencies = [ [[package]] name = "dyn-clonable-impl" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +checksum = "7e8671d54058979a37a26f3511fbf8d198ba1aa35ffb202c42587d918d77213a" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] name = "dyn-clone" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "ecdsa" @@ -2049,9 +2652,9 @@ checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core", + "rand_core 0.6.4", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "subtle 2.6.1", "zeroize", ] @@ -2066,16 +2669,16 @@ dependencies = [ "ed25519", "hashbrown 0.14.5", "hex", - "rand_core", - "sha2 0.10.8", + "rand_core 0.6.4", + "sha2 0.10.9", "zeroize", ] [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ "serde", ] @@ -2093,7 +2696,7 @@ dependencies = [ "generic-array 0.14.7", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "serdect", "subtle 2.6.1", @@ -2102,9 +2705,9 @@ dependencies = [ [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enum-as-inner" @@ -2127,27 +2730,27 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "enumflags2" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -2171,18 +2774,18 @@ checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2193,9 +2796,22 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", + "impl-rlp 0.3.0", + "impl-serde 0.4.0", + "tiny-keccak", +] + +[[package]] +name = "ethbloom" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec 0.7.1", + "impl-rlp 0.4.0", + "impl-serde 0.5.0", "scale-info", "tiny-keccak", ] @@ -2203,15 +2819,14 @@ dependencies = [ [[package]] name = "ethereum" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04d24d20b8ff2235cffbf242d5092de3aa45f77c5270ddbfadd2778ca13fea" +source = "git+https://github.com/rust-ethereum/ethereum?rev=3be0d8fd4c2ad1ba216b69ef65b9382612efc8ba#3be0d8fd4c2ad1ba216b69ef65b9382612efc8ba" dependencies = [ "bytes", - "ethereum-types", + "ethereum-types 0.15.1", "hash-db", "hash256-std-hasher", "parity-scale-codec", - "rlp", + "rlp 0.6.1", "scale-info", "serde", "sha3", @@ -2224,14 +2839,28 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ - "ethbloom", + "ethbloom 0.13.0", + "fixed-hash", + "impl-rlp 0.3.0", + "impl-serde 0.4.0", + "primitive-types 0.12.2", + "uint 0.9.5", +] + +[[package]] +name = "ethereum-types" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab15ed80916029f878e0267c3a9f92b67df55e79af370bf66199059ae2b4ee3" +dependencies = [ + "ethbloom 0.14.1", "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", + "impl-codec 0.7.1", + "impl-rlp 0.4.0", + "impl-serde 0.5.0", + "primitive-types 0.13.1", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -2242,9 +2871,19 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.3.1" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -2253,19 +2892,18 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.0", "pin-project-lite", ] [[package]] name = "evm" -version = "0.41.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767f43e9630cc36cf8ff2777cbb0121b055f0d1fd6eaaa13b46a1808f0d0e7e9" +version = "0.42.0" +source = "git+https://github.com/rust-ethereum/evm?rev=e81732d6bb47e3d3d68d233e43919c4522598361#e81732d6bb47e3d3d68d233e43919c4522598361" dependencies = [ "auto_impl", "environmental", @@ -2275,8 +2913,8 @@ dependencies = [ "evm-runtime", "log", "parity-scale-codec", - "primitive-types", - "rlp", + "primitive-types 0.13.1", + "rlp 0.6.1", "scale-info", "serde", "sha3", @@ -2284,38 +2922,35 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da6cedc5cedb4208e59467106db0d1f50db01b920920589f8e672c02fdc04f" +version = "0.42.0" +source = "git+https://github.com/rust-ethereum/evm?rev=e81732d6bb47e3d3d68d233e43919c4522598361#e81732d6bb47e3d3d68d233e43919c4522598361" dependencies = [ "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-info", "serde", ] [[package]] name = "evm-gasometer" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dc0eb591abc5cd7b05bef6a036c2bb6c66ab6c5e0c5ce94bfe377ab670b1fd7" +version = "0.42.0" +source = "git+https://github.com/rust-ethereum/evm?rev=e81732d6bb47e3d3d68d233e43919c4522598361#e81732d6bb47e3d3d68d233e43919c4522598361" dependencies = [ "environmental", "evm-core", "evm-runtime", - "primitive-types", + "primitive-types 0.13.1", ] [[package]] name = "evm-runtime" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84bbe09b64ae13a29514048c1bb6fda6374ac0b4f6a1f15a443348ab88ef42cd" +version = "0.42.0" +source = "git+https://github.com/rust-ethereum/evm?rev=e81732d6bb47e3d3d68d233e43919c4522598361#e81732d6bb47e3d3d68d233e43919c4522598361" dependencies = [ "auto_impl", "environmental", "evm-core", - "primitive-types", + "primitive-types 0.13.1", "sha3", ] @@ -2337,10 +2972,10 @@ dependencies = [ "blake2 0.10.6", "file-guard", "fs-err", - "prettyplease 0.2.22", + "prettyplease", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -2357,14 +2992,60 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec 0.7.6", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec 0.7.6", + "auto_impl", + "bytes", +] + +[[package]] +name = "fatality" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019" +dependencies = [ + "fatality-proc-macro", + "thiserror 1.0.69", +] + +[[package]] +name = "fatality-proc-macro" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" +dependencies = [ + "expander", + "indexmap 2.9.0", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.103", +] [[package]] name = "fc-api" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "async-trait", "fp-storage", @@ -2376,7 +3057,7 @@ dependencies = [ [[package]] name = "fc-aura" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fc-rpc", "fp-storage", @@ -2392,7 +3073,7 @@ dependencies = [ [[package]] name = "fc-consensus" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "async-trait", "fp-consensus", @@ -2402,13 +3083,13 @@ dependencies = [ "sp-block-builder", "sp-consensus", "sp-runtime", - "thiserror", + "thiserror 2.0.12", ] [[package]] name = "fc-db" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "async-trait", "ethereum", @@ -2422,7 +3103,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-client-db", "smallvec", @@ -2438,7 +3119,7 @@ dependencies = [ [[package]] name = "fc-mapping-sync" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fc-db", "fc-storage", @@ -2447,7 +3128,7 @@ dependencies = [ "futures", "futures-timer", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-utils", "sp-api", @@ -2461,10 +3142,10 @@ dependencies = [ [[package]] name = "fc-rpc" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", + "ethereum-types 0.15.1", "evm", "fc-api", "fc-mapping-sync", @@ -2475,20 +3156,19 @@ dependencies = [ "fp-storage", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.24.9", "libsecp256k1", "log", "pallet-evm", "parity-scale-codec", "prometheus", - "rand", - "rlp", + "rand 0.9.1", + "rlp 0.6.1", "sc-client-api", "sc-network", "sc-network-sync", "sc-rpc", "sc-service", - "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", "schnellru", @@ -2498,39 +3178,40 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-inherents", "sp-io", "sp-runtime", "sp-state-machine", - "sp-storage 21.0.0", + "sp-storage 22.0.0", + "sp-trie", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 2.0.12", "tokio", ] [[package]] name = "fc-rpc-core" version = "1.1.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", - "jsonrpsee", - "rlp", + "ethereum-types 0.15.1", + "jsonrpsee 0.24.9", + "rlp 0.6.1", "rustc-hex", "serde", "serde_json", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", ] [[package]] name = "fc-storage" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", + "ethereum-types 0.15.1", "fp-rpc", "fp-storage", "parity-scale-codec", @@ -2538,7 +3219,7 @@ dependencies = [ "sp-api", "sp-io", "sp-runtime", - "sp-storage 21.0.0", + "sp-storage 22.0.0", ] [[package]] @@ -2548,16 +3229,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle 2.6.1", ] @@ -2601,9 +3282,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +checksum = "b4f8f43dc520133541781ec03a8cab158ae8b7f7169cdf22e9050aa6cf0fbdfc" dependencies = [ "either", "futures", @@ -2611,10 +3292,20 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "scale-info", ] +[[package]] +name = "finito" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2384245d85162258a14b43567a9ee3598f5ae746a1581fb5d3d2cb780f0dbf95" +dependencies = [ + "futures-timer", + "pin-project", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2622,7 +3313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -2633,6 +3324,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "float-cmp" version = "0.9.0" @@ -2661,9 +3358,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -2682,8 +3379,8 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "13.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", ] @@ -2704,16 +3401,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" dependencies = [ "nonempty", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "fp-account" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "hex", - "impl-serde", + "impl-serde 0.5.0", "libsecp256k1", "log", "parity-scale-codec", @@ -2722,14 +3419,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", "staging-xcm", ] [[package]] name = "fp-consensus" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", "parity-scale-codec", @@ -2740,10 +3437,10 @@ dependencies = [ [[package]] name = "fp-ethereum" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", + "ethereum-types 0.15.1", "fp-evm", "frame-support", "parity-scale-codec", @@ -2752,8 +3449,9 @@ dependencies = [ [[package]] name = "fp-evm" version = "3.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ + "environmental", "evm", "frame-support", "num_enum", @@ -2767,10 +3465,10 @@ dependencies = [ [[package]] name = "fp-rpc" version = "3.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", + "ethereum-types 0.15.1", "fp-evm", "parity-scale-codec", "scale-info", @@ -2783,7 +3481,7 @@ dependencies = [ [[package]] name = "fp-self-contained" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "frame-support", "parity-scale-codec", @@ -2795,7 +3493,7 @@ dependencies = [ [[package]] name = "fp-storage" version = "2.0.0" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "parity-scale-codec", "serde", @@ -2803,14 +3501,14 @@ dependencies = [ [[package]] name = "fragile" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" +checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "frame-benchmarking" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-support-procedural", @@ -2826,32 +3524,36 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-runtime-interface 28.0.0", - "sp-storage 21.0.0", + "sp-runtime-interface 29.0.0", + "sp-storage 22.0.0", "static_assertions", ] [[package]] name = "frame-benchmarking-cli" -version = "43.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "46.2.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "Inflector", "array-bytes", "chrono", "clap", "comfy-table", + "cumulus-client-parachain-inherent", + "cumulus-primitives-proof-size-hostfunction", "frame-benchmarking", "frame-support", "frame-system", "gethostname", "handlebars", + "hex", "itertools 0.11.0", - "lazy_static", "linked-hash-map", "log", "parity-scale-codec", - "rand", + "polkadot-parachain-primitives", + "polkadot-primitives", + "rand 0.8.5", "rand_pcg", "sc-block-builder", "sc-chain-spec", @@ -2859,32 +3561,40 @@ dependencies = [ "sc-client-api", "sc-client-db", "sc-executor", + "sc-executor-common", "sc-service", "sc-sysinfo", "serde", "serde_json", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-core", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-database", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keystore", "sp-runtime", "sp-state-machine", - "sp-storage 21.0.0", + "sp-storage 22.0.0", + "sp-timestamp", + "sp-transaction-pool", "sp-trie", + "sp-version", "sp-wasm-interface 21.0.1", - "thiserror", + "subxt", + "subxt-signer", + "thiserror 1.0.69", "thousands", ] [[package]] name = "frame-executive" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "aquamarine", "frame-support", @@ -2899,6 +3609,17 @@ dependencies = [ "sp-tracing 17.0.1", ] +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "frame-metadata" version = "16.0.0" @@ -2911,12 +3632,25 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-metadata" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daaf440c68eb2c3d88e5760fe8c7af3f9fee9181fab6c2f2c4e7cc48dcc40bb8" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + [[package]] name = "frame-metadata-hash-extension" -version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.7.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", + "const-hex", "docify", "frame-support", "frame-system", @@ -2928,15 +3662,16 @@ dependencies = [ [[package]] name = "frame-support" -version = "38.2.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "aquamarine", "array-bytes", + "binary-merkle-tree", "bitflags 1.3.2", "docify", "environmental", - "frame-metadata", + "frame-metadata 18.0.0", "frame-support-procedural", "impl-trait-for-tuples", "k256", @@ -2952,7 +3687,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-crypto-hashing-proc-macro", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-genesis-builder", "sp-inherents", "sp-io", @@ -2960,8 +3695,9 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-tracing 17.0.1", + "sp-trie", "sp-weights", "static_assertions", "tt-call", @@ -2969,22 +3705,22 @@ dependencies = [ [[package]] name = "frame-support-procedural" -version = "30.0.6" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "31.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse", "docify", "expander", - "frame-support-procedural-tools 13.0.0", + "frame-support-procedural-tools 13.0.1", "itertools 0.11.0", "macro_magic", - "proc-macro-warning 1.0.2", + "proc-macro-warning 1.84.1", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "syn 2.0.90", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "syn 2.0.103", ] [[package]] @@ -2994,22 +3730,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3363df38464c47a73eb521a4f648bfcc7537a82d70347ef8af3f73b6d019e910" dependencies = [ "frame-support-procedural-tools-derive 11.0.0", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "frame-support-procedural-tools" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "13.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support-procedural-tools-derive 12.0.0", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -3020,23 +3756,23 @@ checksum = "68672b9ec6fe72d259d3879dc212c5e42e977588cdac830c76f54d9f492aeb58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "frame-support-procedural-tools-derive" version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "frame-system" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "cfg-if", "docify", @@ -3048,15 +3784,15 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-version", "sp-weights", ] [[package]] name = "frame-system-benchmarking" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-benchmarking", "frame-support", @@ -3069,8 +3805,8 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "parity-scale-codec", @@ -3079,8 +3815,8 @@ dependencies = [ [[package]] name = "frame-try-runtime" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.45.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "parity-scale-codec", @@ -3174,7 +3910,7 @@ checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.12.3", + "parking_lot 0.12.4", ] [[package]] @@ -3185,11 +3921,14 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ + "fastrand", "futures-core", + "futures-io", + "parking", "pin-project-lite", ] @@ -3201,7 +3940,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -3259,13 +3998,27 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.61.3", +] + [[package]] name = "generic-array" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ - "typenum 1.17.0", + "typenum 1.18.0", ] [[package]] @@ -3274,7 +4027,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "typenum 1.17.0", + "typenum 1.18.0", "version_check", "zeroize", ] @@ -3291,13 +4044,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -3306,8 +4071,8 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" dependencies = [ - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", ] [[package]] @@ -3343,15 +4108,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "governor" @@ -3365,10 +4130,10 @@ dependencies = [ "futures-timer", "no-std-compat", "nonzero_ext", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "portable-atomic", "quanta", - "rand", + "rand 0.8.5", "smallvec", "spinning_top", ] @@ -3380,7 +4145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle 2.6.1", ] @@ -3396,7 +4161,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -3405,17 +4170,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.6.0", + "http 1.3.1", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -3439,7 +4204,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3472,7 +4237,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", ] [[package]] @@ -3481,15 +4246,16 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "allocator-api2", + "serde", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -3507,11 +4273,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.4", ] [[package]] @@ -3534,9 +4300,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3559,6 +4325,52 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.6.1", + "futures-channel", + "futures-io", + "futures-util", + "idna 1.0.3", + "ipnet", + "once_cell", + "rand 0.9.1", + "ring 0.17.14", + "thiserror 2.0.12", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot 0.12.4", + "rand 0.9.1", + "resolv-conf", + "smallvec", + "thiserror 2.0.12", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -3598,26 +4410,6 @@ dependencies = [ "hmac 0.8.1", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "http" version = "0.2.12" @@ -3631,9 +4423,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -3658,27 +4450,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.1.0", + "futures-core", + "http 1.3.1", "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -3688,15 +4480,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -3709,7 +4501,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -3718,15 +4510,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.10", + "http 1.3.1", "http-body 1.0.1", "httparse", "httpdate", @@ -3734,6 +4526,7 @@ dependencies = [ "pin-project-lite", "smallvec", "tokio", + "want", ] [[package]] @@ -3744,42 +4537,66 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "log", "rustls 0.21.12", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] -name = "hyper-util" -version = "0.1.10" +name = "hyper-rustls" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.5.0", - "pin-project-lite", + "http 1.3.1", + "hyper 1.6.0", + "hyper-util", + "log", + "rustls 0.23.28", + "rustls-native-certs 0.8.1", + "rustls-pki-types", "tokio", + "tokio-rustls 0.26.2", "tower-service", ] [[package]] -name = "iana-time-zone" -version = "0.1.61" +name = "hyper-util" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "android_system_properties", - "core-foundation-sys", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", + "libc", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.61.2", ] [[package]] @@ -3791,6 +4608,92 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3820,12 +4723,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -3840,21 +4754,25 @@ dependencies = [ [[package]] name = "if-watch" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" +checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.4", "fnv", "futures", "if-addrs", "ipnet", "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-proto", + "netlink-sys", "rtnetlink", "system-configuration", "tokio", - "windows", + "windows 0.53.0", ] [[package]] @@ -3868,9 +4786,9 @@ dependencies = [ "bytes", "futures", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "log", - "rand", + "rand 0.8.5", "tokio", "url", "xmltree", @@ -3885,13 +4803,42 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-codec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-num-traits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint 0.10.0", +] + [[package]] name = "impl-rlp" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" dependencies = [ - "rlp", + "rlp 0.5.2", +] + +[[package]] +name = "impl-rlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90" +dependencies = [ + "rlp 0.6.1", ] [[package]] @@ -3903,15 +4850,24 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-serde" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] @@ -3946,19 +4902,25 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array 0.14.7", ] @@ -4004,7 +4966,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.7", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -4012,19 +4974,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4060,100 +5022,263 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "jsonrpsee" -version = "0.24.7" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" +checksum = "cfdb12a2381ea5b2e68c3469ec604a007b367778cdb14d09612c8069ebd616ad" dependencies = [ - "jsonrpsee-core", + "jsonrpsee-client-transport 0.22.5", + "jsonrpsee-core 0.22.5", + "jsonrpsee-http-client", + "jsonrpsee-types 0.22.5", +] + +[[package]] +name = "jsonrpsee" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b089779ad7f80768693755a031cc14a7766aba707cbe886674e3f79e9b7e47" +dependencies = [ + "jsonrpsee-core 0.23.2", + "jsonrpsee-types 0.23.2", + "jsonrpsee-ws-client", +] + +[[package]] +name = "jsonrpsee" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b26c20e2178756451cfeb0661fb74c47dd5988cb7e3939de7e9241fd604d42" +dependencies = [ + "jsonrpsee-core 0.24.9", "jsonrpsee-proc-macros", "jsonrpsee-server", - "jsonrpsee-types", + "jsonrpsee-types 0.24.9", "tokio", "tracing", ] +[[package]] +name = "jsonrpsee-client-transport" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4978087a58c3ab02efc5b07c5e5e2803024536106fd5506f558db172c889b3aa" +dependencies = [ + "futures-util", + "http 0.2.12", + "jsonrpsee-core 0.22.5", + "pin-project", + "rustls-native-certs 0.7.3", + "rustls-pki-types", + "soketto 0.7.1", + "thiserror 1.0.69", + "tokio", + "tokio-rustls 0.25.0", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08163edd8bcc466c33d79e10f695cdc98c00d1e6ddfb95cec41b6b0279dd5432" +dependencies = [ + "base64 0.22.1", + "futures-util", + "http 1.3.1", + "jsonrpsee-core 0.23.2", + "pin-project", + "rustls 0.23.28", + "rustls-pki-types", + "rustls-platform-verifier", + "soketto 0.8.1", + "thiserror 1.0.69", + "tokio", + "tokio-rustls 0.26.2", + "tokio-util", + "tracing", + "url", +] + [[package]] name = "jsonrpsee-core" -version = "0.24.7" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" +checksum = "b4b257e1ec385e07b0255dde0b933f948b5c8b8c28d42afda9587c3a967b896d" +dependencies = [ + "anyhow", + "async-trait", + "beef", + "futures-timer", + "futures-util", + "hyper 0.14.32", + "jsonrpsee-types 0.22.5", + "pin-project", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79712302e737d23ca0daa178e752c9334846b08321d439fd89af9a384f8c830b" +dependencies = [ + "anyhow", + "async-trait", + "beef", + "futures-timer", + "futures-util", + "jsonrpsee-types 0.23.2", + "pin-project", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "jsonrpsee-types", - "parking_lot 0.12.3", - "rand", - "rustc-hash 2.0.0", + "jsonrpsee-types 0.24.9", + "parking_lot 0.12.4", + "rand 0.8.5", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ccf93fc4a0bfe05d851d37d7c32b7f370fe94336b52a2f0efc5f1981895c2e5" +dependencies = [ + "async-trait", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "jsonrpsee-core 0.22.5", + "jsonrpsee-types 0.22.5", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", + "tower", "tracing", + "url", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06c01ae0007548e73412c08e2285ffe5d723195bf268bce67b1b77c3bb2a14d" +checksum = "5e65763c942dfc9358146571911b0cd1c361c2d63e2d2305622d40d36376ca80" dependencies = [ "heck 0.5.0", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "jsonrpsee-server" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ad8ddc14be1d4290cd68046e7d1d37acd408efed6d3ca08aefcc3ad6da069c" +checksum = "55e363146da18e50ad2b51a0a7925fc423137a0b1371af8235b1c231a0647328" dependencies = [ "futures-util", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.6.0", "hyper-util", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.24.9", + "jsonrpsee-types 0.24.9", "pin-project", "route-recognizer", "serde", "serde_json", - "soketto", - "thiserror", + "soketto 0.8.1", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util", @@ -4163,14 +5288,53 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.7" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" +checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" dependencies = [ - "http 1.1.0", + "anyhow", + "beef", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af" +dependencies = [ + "beef", + "http 1.3.1", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +dependencies = [ + "http 1.3.1", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c28759775f5cb2f1ea9667672d3fe2b0e701d1f4b7b67954e60afe7fd058b5e" +dependencies = [ + "http 1.3.1", + "jsonrpsee-client-transport 0.23.2", + "jsonrpsee-core 0.23.2", + "jsonrpsee-types 0.23.2", + "url", ] [[package]] @@ -4184,7 +5348,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -4196,6 +5360,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "keccak-hash" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b286e6b663fb926e1eeb68528e69cb70ed46c6d65871a21b2215ae8154c6d3c" +dependencies = [ + "primitive-types 0.12.2", + "tiny-keccak", +] + [[package]] name = "keystream" version = "1.0.0" @@ -4218,7 +5402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parking_lot 0.12.3", + "parking_lot 0.12.4", ] [[package]] @@ -4229,7 +5413,7 @@ checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" dependencies = [ "kvdb", "num_cpus", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "regex", "rocksdb", "smallvec", @@ -4249,25 +5433,25 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.2", ] [[package]] name = "libm" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libp2p" @@ -4279,7 +5463,7 @@ dependencies = [ "either", "futures", "futures-timer", - "getrandom", + "getrandom 0.2.16", "instant", "libp2p-allow-block-list", "libp2p-connection-limits", @@ -4303,7 +5487,7 @@ dependencies = [ "multiaddr 0.18.2", "pin-project", "rw-stream-sink", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4344,16 +5528,16 @@ dependencies = [ "libp2p-identity", "log", "multiaddr 0.18.2", - "multihash 0.19.2", + "multihash 0.19.3", "multistream-select", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project", "quick-protobuf", - "rand", + "rand 0.8.5", "rw-stream-sink", "smallvec", - "thiserror", + "thiserror 1.0.69", "unsigned-varint 0.7.2", "void", ] @@ -4369,7 +5553,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "smallvec", "trust-dns-resolver", ] @@ -4393,24 +5577,24 @@ dependencies = [ "quick-protobuf", "quick-protobuf-codec", "smallvec", - "thiserror", + "thiserror 1.0.69", "void", ] [[package]] name = "libp2p-identity" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" +checksum = "fbb68ea10844211a59ce46230909fd0ea040e8a192454d4cc2ee0d53e12280eb" dependencies = [ - "bs58 0.5.1", + "bs58", "ed25519-dalek", "hkdf", - "multihash 0.19.2", + "multihash 0.19.3", "quick-protobuf", - "rand", - "sha2 0.10.8", - "thiserror", + "rand 0.8.5", + "sha2 0.10.9", + "thiserror 2.0.12", "tracing", "zeroize", ] @@ -4421,7 +5605,7 @@ version = "0.44.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16ea178dabba6dde6ffc260a8e0452ccdc8f79becf544946692fff9d412fc29d" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "asynchronous-codec", "bytes", "either", @@ -4435,11 +5619,11 @@ dependencies = [ "log", "quick-protobuf", "quick-protobuf-codec", - "rand", - "sha2 0.10.8", + "rand 0.8.5", + "sha2 0.10.9", "smallvec", - "thiserror", - "uint", + "thiserror 1.0.69", + "uint 0.9.5", "unsigned-varint 0.7.2", "void", ] @@ -4457,9 +5641,9 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand", + "rand 0.8.5", "smallvec", - "socket2 0.5.7", + "socket2 0.5.10", "tokio", "trust-dns-proto 0.22.0", "void", @@ -4495,14 +5679,14 @@ dependencies = [ "libp2p-identity", "log", "multiaddr 0.18.2", - "multihash 0.19.2", + "multihash 0.19.3", "once_cell", "quick-protobuf", - "rand", - "sha2 0.10.8", + "rand 0.8.5", + "sha2 0.10.9", "snow", "static_assertions", - "thiserror", + "thiserror 1.0.69", "x25519-dalek", "zeroize", ] @@ -4521,7 +5705,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand", + "rand 0.8.5", "void", ] @@ -4539,13 +5723,13 @@ dependencies = [ "libp2p-identity", "libp2p-tls", "log", - "parking_lot 0.12.3", - "quinn 0.10.2", - "rand", + "parking_lot 0.12.4", + "quinn", + "rand 0.8.5", "ring 0.16.20", "rustls 0.21.12", - "socket2 0.5.7", - "thiserror", + "socket2 0.5.10", + "thiserror 1.0.69", "tokio", ] @@ -4562,7 +5746,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "rand", + "rand 0.8.5", "smallvec", "void", ] @@ -4584,7 +5768,7 @@ dependencies = [ "log", "multistream-select", "once_cell", - "rand", + "rand 0.8.5", "smallvec", "tokio", "void", @@ -4600,7 +5784,7 @@ dependencies = [ "proc-macro-warning 0.4.2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -4616,7 +5800,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "socket2 0.5.7", + "socket2 0.5.10", "tokio", ] @@ -4633,8 +5817,8 @@ dependencies = [ "rcgen", "ring 0.16.20", "rustls 0.21.12", - "rustls-webpki", - "thiserror", + "rustls-webpki 0.101.7", + "thiserror 1.0.69", "x509-parser 0.15.1", "yasna", ] @@ -4681,13 +5865,13 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project-lite", "rw-stream-sink", - "soketto", - "thiserror", + "soketto 0.8.1", + "thiserror 1.0.69", "url", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] @@ -4699,8 +5883,8 @@ dependencies = [ "futures", "libp2p-core", "log", - "thiserror", - "yamux", + "thiserror 1.0.69", + "yamux 0.12.1", ] [[package]] @@ -4709,9 +5893,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.13", ] [[package]] @@ -4742,10 +5926,10 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand", + "rand 0.8.5", "serde", "sha2 0.9.9", - "typenum 1.17.0", + "typenum 1.18.0", ] [[package]] @@ -4790,9 +5974,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "pkg-config", @@ -4801,9 +5985,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" dependencies = [ "cc", ] @@ -4816,18 +6000,18 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linked_hash_set" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" +checksum = "bae85b5be22d9843c80e5fc80e9b64c8a3b1f98f867c709956eca3efff4e92e2" dependencies = [ "linked-hash-map", ] [[package]] name = "linregress" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de04dcecc58d366391f9920245b85ffa684558a5ef6e7736e754347c3aea9c2" +checksum = "a9eda9dcf4f2a99787827661f312ac3219292549c2ee992bf9a6248ffb066bf7" dependencies = [ "nalgebra", ] @@ -4840,9 +6024,15 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "lioness" @@ -4856,66 +6046,64 @@ dependencies = [ "keystream", ] +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + [[package]] name = "litep2p" -version = "0.6.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f46c51c205264b834ceed95c8b195026e700494bc3991aaba3b4ea9e20626d9" +checksum = "14fb10e63363204b89d91e1292df83322fd9de5d7fa76c3d5c78ddc2f8f3efa9" dependencies = [ "async-trait", - "bs58 0.4.0", + "bs58", "bytes", - "cid 0.10.1", + "cid 0.11.1", "ed25519-dalek", "futures", "futures-timer", - "hex-literal", - "indexmap 2.6.0", + "hickory-resolver", + "indexmap 2.9.0", "libc", - "mockall 0.12.1", + "mockall 0.13.1", "multiaddr 0.17.1", "multihash 0.17.0", "network-interface", - "nohash-hasher", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project", - "prost 0.12.6", - "prost-build 0.11.9", - "quinn 0.9.4", - "rand", - "rcgen", - "ring 0.16.20", - "rustls 0.20.9", + "prost 0.13.5", + "prost-build", + "rand 0.8.5", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "simple-dns", "smallvec", "snow", - "socket2 0.5.7", - "static_assertions", - "str0m", - "thiserror", + "socket2 0.5.10", + "thiserror 2.0.12", "tokio", "tokio-stream", "tokio-tungstenite", "tokio-util", "tracing", - "trust-dns-resolver", - "uint", + "uint 0.10.0", "unsigned-varint 0.8.0", "url", - "webpki", "x25519-dalek", - "x509-parser 0.16.0", + "x509-parser 0.17.0", + "yamux 0.13.5", "yasna", "zeroize", ] [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -4923,9 +6111,22 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber 0.3.19", +] [[package]] name = "lru" @@ -4942,7 +6143,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] [[package]] @@ -4956,9 +6157,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" +checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" dependencies = [ "lz4-sys", ] @@ -4991,7 +6192,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -5005,7 +6206,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -5016,7 +6217,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -5027,15 +6228,9 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.90", + "syn 2.0.103", ] -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -5053,9 +6248,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -5063,9 +6258,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memfd" @@ -5073,7 +6268,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.37", + "rustix 0.38.44", ] [[package]] @@ -5114,13 +6309,13 @@ dependencies = [ [[package]] name = "merkleized-metadata" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +checksum = "38c592efaf1b3250df14c8f3c2d952233f0302bb81d3586db2f303666c1cd607" dependencies = [ "array-bytes", "blake3", - "frame-metadata", + "frame-metadata 18.0.0", "parity-scale-codec", "scale-decode", "scale-info", @@ -5134,7 +6329,7 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core", + "rand_core 0.6.4", "zeroize", ] @@ -5146,23 +6341,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "hermit-abi 0.3.9", "libc", - "wasi", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] @@ -5172,7 +6366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daa3eb39495d8e2e2947a1d862852c90cc6a4a8845f8b41c8829cb9fcc047f4a" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.6", "bitflags 1.3.2", "blake2 0.10.6", "c2-chacha", @@ -5181,12 +6375,12 @@ dependencies = [ "hashlink 0.8.4", "lioness", "log", - "parking_lot 0.12.3", - "rand", - "rand_chacha", + "parking_lot 0.12.4", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_distr", "subtle 2.6.1", - "thiserror", + "thiserror 1.0.69", "zeroize", ] @@ -5207,16 +6401,15 @@ dependencies = [ [[package]] name = "mockall" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", - "mockall_derive 0.12.1", - "predicates 3.1.2", + "mockall_derive 0.13.1", + "predicates 3.1.3", "predicates-tree", ] @@ -5234,14 +6427,33 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "moka" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "loom", + "parking_lot 0.12.4", + "portable-atomic", + "rustc_version 0.4.1", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "uuid", ] [[package]] @@ -5274,7 +6486,7 @@ dependencies = [ "data-encoding", "libp2p-identity", "multibase", - "multihash 0.19.2", + "multihash 0.19.3", "percent-encoding", "serde", "static_assertions", @@ -5305,33 +6517,16 @@ dependencies = [ "core2", "digest 0.10.7", "multihash-derive", - "sha2 0.10.8", - "sha3", - "unsigned-varint 0.7.2", -] - -[[package]] -name = "multihash" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", "unsigned-varint 0.7.2", ] [[package]] name = "multihash" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc41f430805af9d1cf4adae4ed2149c759b877b01d909a1f40256188d09345d2" +checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" dependencies = [ "core2", "unsigned-varint 0.8.0", @@ -5353,9 +6548,9 @@ dependencies = [ [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "multistream-select" @@ -5373,29 +6568,17 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.6" +version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" dependencies = [ "approx", "matrixmultiply", - "nalgebra-macros", "num-complex", "num-rational", "num-traits", "simba", - "typenum 1.17.0", -] - -[[package]] -name = "nalgebra-macros" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "typenum 1.18.0", ] [[package]] @@ -5404,14 +6587,20 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc" dependencies = [ - "rand", + "rand 0.8.5", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" + [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -5419,7 +6608,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -5439,21 +6628,20 @@ dependencies = [ [[package]] name = "netlink-packet-core" -version = "0.4.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" dependencies = [ "anyhow", "byteorder", - "libc", "netlink-packet-utils", ] [[package]] name = "netlink-packet-route" -version = "0.12.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" dependencies = [ "anyhow", "bitflags 1.3.2", @@ -5472,29 +6660,28 @@ dependencies = [ "anyhow", "byteorder", "paste", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "netlink-proto" -version = "0.10.0" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" dependencies = [ "bytes", "futures", "log", "netlink-packet-core", "netlink-sys", - "thiserror", - "tokio", + "thiserror 2.0.12", ] [[package]] name = "netlink-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" +checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" dependencies = [ "bytes", "futures", @@ -5505,21 +6692,21 @@ dependencies = [ [[package]] name = "network-interface" -version = "1.1.4" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a43439bf756eed340bdf8feba761e2d50c7d47175d87545cd5cbe4a137c4d1" +checksum = "c3329f515506e4a2de3aa6e07027a6758e22e0f0e8eaf64fa47261cec2282602" dependencies = [ "cc", "libc", - "thiserror", + "thiserror 1.0.69", "winapi", ] [[package]] name = "nix" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", @@ -5532,12 +6719,19 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "node-subtensor" version = "4.0.0-dev" dependencies = [ "async-trait", "clap", + "cumulus-primitives-proof-size-hostfunction", "fc-api", "fc-aura", "fc-consensus", @@ -5555,12 +6749,14 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.24.9", "memmap2 0.9.5", "node-subtensor-runtime", "num-traits", "pallet-commitments", "pallet-drand", + "pallet-subtensor-swap-rpc", + "pallet-subtensor-swap-runtime-api", "pallet-transaction-payment", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", @@ -5596,7 +6792,7 @@ dependencies = [ "sp-consensus-aura", "sp-consensus-grandpa", "sp-core", - "sp-crypto-ec-utils 0.14.0", + "sp-crypto-ec-utils 0.15.0", "sp-inherents", "sp-io", "sp-keyring", @@ -5612,28 +6808,28 @@ dependencies = [ "subtensor-custom-rpc", "subtensor-custom-rpc-runtime-api", "subtensor-runtime-common", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "node-subtensor-runtime" version = "4.0.0-dev" dependencies = [ - "ark-serialize", + "ark-serialize 0.4.2", "fp-account", "fp-evm", "fp-rpc", "fp-self-contained", "frame-benchmarking", "frame-executive", - "frame-metadata", + "frame-metadata 18.0.0", "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "getrandom", + "getrandom 0.2.16", "hex", "log", "pallet-admin-utils", @@ -5661,6 +6857,8 @@ dependencies = [ "pallet-safe-mode", "pallet-scheduler", "pallet-subtensor", + "pallet-subtensor-swap", + "pallet-subtensor-swap-runtime-api", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -5668,10 +6866,10 @@ dependencies = [ "pallet-utility 38.0.0", "parity-scale-codec", "precompile-utils", - "rand_chacha", + "rand_chacha 0.3.1", "scale-info", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "smallvec", "sp-api", "sp-block-builder", @@ -5683,20 +6881,28 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-storage 21.0.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-storage 22.0.0", "sp-tracing 17.0.1", "sp-transaction-pool", "sp-version", + "substrate-fixed", "substrate-wasm-builder", "subtensor-custom-rpc-runtime-api", "subtensor-macros", "subtensor-precompiles", "subtensor-runtime-common", + "subtensor-swap-interface", "tle", "w3f-bls", ] +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -5786,7 +6992,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "itoa", ] @@ -5833,11 +7039,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", ] @@ -5856,10 +7062,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -5885,9 +7091,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -5903,22 +7109,29 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs 0.7.1", ] [[package]] name = "once_cell" -version = "1.20.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" dependencies = [ + "critical-section", "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -5933,11 +7146,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -5954,33 +7167,23 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "300.4.0+3.4.0" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" -dependencies = [ - "cc", -] +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] @@ -5991,6 +7194,39 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "orchestra" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19051f0b0512402f5d52d6776999f55996f01887396278aeeccbbdfbc83eef2d" +dependencies = [ + "async-trait", + "dyn-clonable", + "futures", + "futures-timer", + "orchestra-proc-macro", + "pin-project", + "prioritized-metered-channel", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "orchestra-proc-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dfaf083aef571385fccfdc3a2f8ede8d0a1863160455d4f2b014d8f7d04a3f" +dependencies = [ + "expander", + "indexmap 2.9.0", + "itertools 0.11.0", + "petgraph 0.6.5", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "overload" version = "0.1.1" @@ -6011,6 +7247,7 @@ dependencies = [ "pallet-grandpa", "pallet-scheduler", "pallet-subtensor", + "pallet-subtensor-swap", "parity-scale-codec", "scale-info", "sp-consensus-aura", @@ -6018,17 +7255,19 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-tracing 17.0.1", "sp-weights", "substrate-fixed", "subtensor-macros", + "subtensor-runtime-common", + "subtensor-swap-interface", ] [[package]] name = "pallet-aura" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-system", @@ -6043,8 +7282,8 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-system", @@ -6056,8 +7295,8 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "39.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "40.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-benchmarking", @@ -6072,7 +7311,7 @@ dependencies = [ [[package]] name = "pallet-base-fee" version = "1.0.0" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fp-evm", "frame-support", @@ -6096,7 +7335,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "subtensor-macros", ] @@ -6104,7 +7343,7 @@ dependencies = [ name = "pallet-commitments" version = "4.0.0-dev" dependencies = [ - "ark-serialize", + "ark-serialize 0.4.2", "enumflags2", "frame-benchmarking", "frame-support", @@ -6115,14 +7354,15 @@ dependencies = [ "pallet-drand", "pallet-subtensor", "parity-scale-codec", - "rand_chacha", + "rand_chacha 0.3.1", "scale-info", - "sha2 0.10.8", + "sha2 0.10.9", "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "subtensor-macros", + "subtensor-runtime-common", "tle", "w3f-bls", ] @@ -6142,7 +7382,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "subtensor-macros", ] @@ -6154,10 +7394,10 @@ dependencies = [ "ark-bls12-381", "ark-crypto-primitives", "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-scale 0.0.11", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "frame-benchmarking", "frame-support", "frame-system", @@ -6167,7 +7407,7 @@ dependencies = [ "scale-info", "serde", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "sp-ark-bls12-381", "sp-core", "sp-io", @@ -6182,10 +7422,10 @@ dependencies = [ [[package]] name = "pallet-ethereum" version = "4.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "ethereum", - "ethereum-types", + "ethereum-types 0.15.1", "evm", "fp-consensus", "fp-ethereum", @@ -6199,13 +7439,15 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", + "sp-version", ] [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ + "cumulus-primitives-storage-weight-reclaim", "environmental", "evm", "fp-account", @@ -6227,7 +7469,7 @@ dependencies = [ [[package]] name = "pallet-evm-chain-id" version = "1.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "frame-support", "frame-system", @@ -6235,10 +7477,22 @@ dependencies = [ "scale-info", ] +[[package]] +name = "pallet-evm-precompile-dispatch" +version = "2.0.0-dev" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" +dependencies = [ + "fp-evm", + "frame-support", + "pallet-evm", + "parity-scale-codec", + "sp-runtime", +] + [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fp-evm", "num", @@ -6247,7 +7501,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-sha3fips" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fp-evm", "tiny-keccak", @@ -6256,7 +7510,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-simple" version = "2.0.0-dev" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "fp-evm", "ripemd", @@ -6265,8 +7519,8 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-benchmarking", "frame-support", @@ -6288,7 +7542,7 @@ dependencies = [ [[package]] name = "pallet-hotfix-sufficients" version = "1.0.0" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "frame-benchmarking", "frame-support", @@ -6302,8 +7556,8 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "27.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-system", @@ -6315,8 +7569,8 @@ dependencies = [ [[package]] name = "pallet-membership" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-benchmarking", "frame-support", @@ -6331,23 +7585,19 @@ dependencies = [ [[package]] name = "pallet-multisig" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "log", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-io", - "sp-runtime", ] [[package]] name = "pallet-preimage" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-benchmarking", "frame-support", @@ -6379,16 +7629,12 @@ dependencies = [ [[package]] name = "pallet-proxy" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-io", - "sp-runtime", ] [[package]] @@ -6404,14 +7650,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "subtensor-macros", ] [[package]] name = "pallet-root-testing" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "15.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-system", @@ -6424,16 +7670,16 @@ dependencies = [ [[package]] name = "pallet-safe-mode" -version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", - "pallet-proxy 38.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "pallet-utility 38.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "pallet-proxy 39.1.0", + "pallet-utility 39.1.0", "parity-scale-codec", "scale-info", "sp-arithmetic", @@ -6442,8 +7688,8 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "39.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "40.2.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-benchmarking", @@ -6459,8 +7705,8 @@ dependencies = [ [[package]] name = "pallet-session" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-support", "frame-system", @@ -6484,7 +7730,7 @@ version = "4.0.0-dev" dependencies = [ "approx", "ark-bls12-381", - "ark-serialize", + "ark-serialize 0.4.2", "frame-benchmarking", "frame-support", "frame-system", @@ -6500,12 +7746,13 @@ dependencies = [ "pallet-membership", "pallet-preimage", "pallet-scheduler", + "pallet-subtensor-swap", "pallet-transaction-payment", "pallet-utility 38.0.0", "parity-scale-codec", "parity-util-mem", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "safe-math", "scale-info", "serde", @@ -6513,24 +7760,75 @@ dependencies = [ "serde_bytes", "serde_json", "serde_with", - "sha2 0.10.8", + "sha2 0.10.9", "share-pool", "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-tracing 17.0.1", "sp-version", "substrate-fixed", "subtensor-macros", + "subtensor-runtime-common", + "subtensor-swap-interface", "tle", "w3f-bls", ] +[[package]] +name = "pallet-subtensor-swap" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "approx", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-subtensor-swap-runtime-api", + "parity-scale-codec", + "safe-math", + "scale-info", + "serde", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-tracing 17.0.1", + "substrate-fixed", + "subtensor-macros", + "subtensor-runtime-common", + "subtensor-swap-interface", +] + +[[package]] +name = "pallet-subtensor-swap-rpc" +version = "1.0.0" +dependencies = [ + "jsonrpsee 0.24.9", + "pallet-subtensor-swap-runtime-api", + "parity-scale-codec", + "sp-api", + "sp-blockchain", + "sp-runtime", +] + +[[package]] +name = "pallet-subtensor-swap-runtime-api" +version = "1.0.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", +] + [[package]] name = "pallet-sudo" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-benchmarking", @@ -6544,8 +7842,8 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-benchmarking", @@ -6557,15 +7855,16 @@ dependencies = [ "sp-inherents", "sp-io", "sp-runtime", - "sp-storage 21.0.0", + "sp-storage 22.0.0", "sp-timestamp", ] [[package]] name = "pallet-transaction-payment" -version = "38.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", @@ -6578,10 +7877,10 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" -version = "41.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "42.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "jsonrpsee", + "jsonrpsee 0.24.9", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "sp-api", @@ -6594,8 +7893,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -6625,8 +7924,8 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "frame-benchmarking", "frame-support", @@ -6645,8 +7944,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ "bitcoin_hashes", - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -6665,38 +7964,40 @@ dependencies = [ "log", "lz4", "memmap2 0.5.10", - "parking_lot 0.12.3", - "rand", - "siphasher", + "parking_lot 0.12.4", + "rand 0.8.5", + "siphasher 0.3.11", "snap", "winapi", ] [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "bitvec", "byte-slice-cast", "bytes", + "const_format", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] @@ -6706,13 +8007,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" dependencies = [ "cfg-if", - "ethereum-types", + "ethereum-types 0.14.1", "hashbrown 0.12.3", "impl-trait-for-tuples", "lru 0.8.1", "parity-util-mem-derive", - "parking_lot 0.12.3", - "primitive-types", + "parking_lot 0.12.4", + "primitive-types 0.12.2", "smallvec", "winapi", ] @@ -6753,12 +8054,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.11", ] [[package]] @@ -6777,13 +8078,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.13", "smallvec", "windows-targets 0.52.6", ] @@ -6801,7 +8102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle 2.6.1", ] @@ -6844,20 +8145,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.13" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", - "thiserror", + "thiserror 2.0.12", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.13" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" dependencies = [ "pest", "pest_generator", @@ -6865,26 +8166,25 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.13" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "pest_meta" -version = "2.7.13" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ - "once_cell", "pest", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -6893,35 +8193,45 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", - "indexmap 2.6.0", + "fixedbitset 0.4.2", + "indexmap 2.9.0", +] + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset 0.5.7", + "indexmap 2.9.0", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -6929,6 +8239,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -6941,9 +8262,230 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polkadot-core-primitives" +version = "16.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "polkadot-node-metrics" +version = "21.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "bs58", + "futures", + "futures-timer", + "log", + "parity-scale-codec", + "polkadot-primitives", + "prioritized-metered-channel", + "sc-cli", + "sc-service", + "sc-tracing", + "substrate-prometheus-endpoint", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-network-protocol" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-channel 1.9.0", + "async-trait", + "bitvec", + "derive_more 0.99.20", + "fatality", + "futures", + "hex", + "parity-scale-codec", + "polkadot-node-primitives", + "polkadot-primitives", + "rand 0.8.5", + "sc-authority-discovery", + "sc-network", + "sc-network-types", + "sp-runtime", + "strum 0.26.3", + "thiserror 1.0.69", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-primitives" +version = "17.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "bitvec", + "bounded-vec", + "futures", + "futures-timer", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "sc-keystore", + "schnorrkel", + "serde", + "sp-application-crypto", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-core", + "sp-keystore", + "sp-maybe-compressed-blob", + "sp-runtime", + "thiserror 1.0.69", + "zstd 0.12.4", +] + +[[package]] +name = "polkadot-node-subsystem-types" +version = "21.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "bitvec", + "derive_more 0.99.20", + "fatality", + "futures", + "orchestra", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-primitives", + "polkadot-statement-table", + "sc-client-api", + "sc-network", + "sc-network-types", + "sc-transaction-pool-api", + "smallvec", + "sp-api", + "sp-authority-discovery", + "sp-blockchain", + "sp-consensus-babe", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.69", +] + +[[package]] +name = "polkadot-overseer" +version = "21.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "orchestra", + "parking_lot 0.12.4", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem-types", + "polkadot-primitives", + "sc-client-api", + "sp-api", + "sp-core", + "tikv-jemalloc-ctl", + "tracing-gum", +] + +[[package]] +name = "polkadot-parachain-primitives" +version = "15.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "bounded-collections", + "derive_more 0.99.20", + "parity-scale-codec", + "polkadot-core-primitives", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-weights", +] + +[[package]] +name = "polkadot-primitives" +version = "17.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "bitvec", + "hex-literal", + "log", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "thiserror 1.0.69", +] + +[[package]] +name = "polkadot-sdk-frame" +version = "0.8.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-block-builder", + "sp-consensus-aura", + "sp-consensus-grandpa", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-keyring", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-storage 22.0.0", + "sp-transaction-pool", + "sp-version", +] + +[[package]] +name = "polkadot-statement-table" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "parity-scale-codec", + "polkadot-primitives", + "sp-core", + "tracing-gum", +] [[package]] name = "polkavm" @@ -6954,7 +8496,7 @@ dependencies = [ "libc", "log", "polkavm-assembler", - "polkavm-common", + "polkavm-common 0.9.0", "polkavm-linux-raw", ] @@ -6976,13 +8518,28 @@ dependencies = [ "log", ] +[[package]] +name = "polkavm-common" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed9e5af472f729fcf3b3c1cf17508ddbb3505259dd6e2ee0fb5a29e105d22" + [[package]] name = "polkavm-derive" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" dependencies = [ - "polkavm-derive-impl-macro", + "polkavm-derive-impl-macro 0.9.0", +] + +[[package]] +name = "polkavm-derive" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176144f8661117ea95fa7cf868c9a62d6b143e8a2ebcb7582464c3faade8669a" +dependencies = [ + "polkavm-derive-impl-macro 0.24.0", ] [[package]] @@ -6991,10 +8548,22 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ - "polkavm-common", + "polkavm-common 0.9.0", + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5a21844afdfcc10c92b9ef288ccb926211af27478d1730fcd55e4aec710179d" +dependencies = [ + "polkavm-common 0.24.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -7003,8 +8572,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ - "polkavm-derive-impl", - "syn 2.0.90", + "polkavm-derive-impl 0.9.0", + "syn 2.0.103", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0ef0f17ad81413ea1ca5b1b67553aedf5650c88269b673d3ba015c83bc2651" +dependencies = [ + "polkavm-derive-impl 0.24.0", + "syn 2.0.103", ] [[package]] @@ -7017,7 +8596,7 @@ dependencies = [ "hashbrown 0.14.5", "log", "object 0.32.2", - "polkavm-common", + "polkavm-common 0.9.0", "regalloc2 0.9.3", "rustc-demangle", ] @@ -7030,15 +8609,15 @@ checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" [[package]] name = "polling" -version = "3.7.3" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "pin-project-lite", - "rustix 0.38.37", + "rustix 1.0.7", "tracing", "windows-sys 0.59.0", ] @@ -7068,9 +8647,18 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -7080,9 +8668,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -7090,7 +8678,7 @@ dependencies = [ [[package]] name = "precompile-utils" version = "0.1.0" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "environmental", "evm", @@ -7114,15 +8702,15 @@ dependencies = [ [[package]] name = "precompile-utils-macro" version = "0.1.0" -source = "git+https://github.com/opentensor/frontier?rev=cd6bca14a3#cd6bca14a366cc7cb1c3b1b1d7bc8213667e4126" +source = "git+https://github.com/opentensor/frontier?rev=4aeb35e5ce815a2d4998a349d47e773190a3396c#4aeb35e5ce815a2d4998a349d47e773190a3396c" dependencies = [ "case", "num_enum", - "prettyplease 0.2.22", + "prettyplease", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "syn 1.0.109", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "syn 2.0.103", ] [[package]] @@ -7141,9 +8729,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "predicates-core", @@ -7151,15 +8739,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" [[package]] name = "predicates-tree" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" dependencies = [ "predicates-core", "termtree", @@ -7167,36 +8755,57 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.1.25" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" dependencies = [ "proc-macro2", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] -name = "prettyplease" -version = "0.2.22" +name = "primitive-types" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ - "proc-macro2", - "syn 2.0.90", + "fixed-hash", + "impl-codec 0.6.0", + "impl-rlp 0.3.0", + "impl-serde 0.4.0", + "scale-info", + "uint 0.9.5", ] [[package]] name = "primitive-types" -version = "0.12.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" dependencies = [ "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", + "impl-codec 0.7.1", + "impl-num-traits", + "impl-rlp 0.4.0", + "impl-serde 0.5.0", "scale-info", - "uint", + "uint 0.10.0", +] + +[[package]] +name = "prioritized-metered-channel" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a172e6cc603231f2cf004232eabcecccc0da53ba576ab286ef7baa0cfc7927ad" +dependencies = [ + "coarsetime", + "crossbeam-queue", + "derive_more 0.99.20", + "futures", + "futures-timer", + "nanorand", + "thiserror 1.0.69", + "tracing", ] [[package]] @@ -7205,15 +8814,15 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "thiserror", + "thiserror 1.0.69", "toml 0.5.11", ] [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ "toml_edit", ] @@ -7250,25 +8859,25 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "proc-macro-warning" -version = "1.0.2" +version = "1.84.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" +checksum = "75eea531cfcd120e0851a3f8aed42c4841f78c889eefafd96339c72677ae42c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -7284,12 +8893,12 @@ dependencies = [ "frame-support-procedural-tools 10.0.0", "itertools 0.10.5", "macro_magic", - "proc-macro-warning 1.0.2", + "proc-macro-warning 1.84.1", "proc-macro2", "quote", "regex", "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -7302,8 +8911,8 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.3", - "thiserror", + "parking_lot 0.12.4", + "thiserror 1.0.69", ] [[package]] @@ -7314,7 +8923,7 @@ checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "prometheus-client-derive-encode", ] @@ -7326,17 +8935,27 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] -name = "prost" -version = "0.11.9" +name = "proptest" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ - "bytes", - "prost-derive 0.11.9", + "bit-set", + "bit-vec", + "bitflags 2.9.1", + "lazy_static", + "num-traits", + "rand 0.9.1", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax 0.8.5", + "rusty-fork", + "tempfile", + "unarray", ] [[package]] @@ -7350,112 +8969,90 @@ dependencies = [ ] [[package]] -name = "prost-build" -version = "0.11.9" +name = "prost" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which", + "prost-derive 0.13.5", ] [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.14.0", "log", "multimap", "once_cell", - "petgraph", - "prettyplease 0.2.22", - "prost 0.12.6", - "prost-types 0.12.6", + "petgraph 0.7.1", + "prettyplease", + "prost 0.13.5", + "prost-types", "regex", - "syn 2.0.90", + "syn 2.0.103", "tempfile", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.90", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", + "syn 2.0.103", ] [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost 0.12.6", + "prost 0.13.5", ] [[package]] name = "psm" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" dependencies = [ "cc", ] [[package]] name = "quanta" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" dependencies = [ "crossbeam-utils", "libc", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -7484,28 +9081,10 @@ dependencies = [ "asynchronous-codec", "bytes", "quick-protobuf", - "thiserror", + "thiserror 1.0.69", "unsigned-varint 0.7.2", ] -[[package]] -name = "quinn" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto 0.9.6", - "quinn-udp 0.3.2", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "thiserror", - "tokio", - "tracing", - "webpki", -] - [[package]] name = "quinn" version = "0.10.2" @@ -7515,33 +9094,15 @@ dependencies = [ "bytes", "futures-io", "pin-project-lite", - "quinn-proto 0.10.6", - "quinn-udp 0.4.1", + "quinn-proto", + "quinn-udp", "rustc-hash 1.1.0", "rustls 0.21.12", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] -[[package]] -name = "quinn-proto" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" -dependencies = [ - "bytes", - "rand", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "slab", - "thiserror", - "tinyvec", - "tracing", - "webpki", -] - [[package]] name = "quinn-proto" version = "0.10.6" @@ -7549,29 +9110,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" dependencies = [ "bytes", - "rand", + "rand 0.8.5", "ring 0.16.20", "rustc-hash 1.1.0", "rustls 0.21.12", "slab", - "thiserror", + "thiserror 1.0.69", "tinyvec", "tracing", ] -[[package]] -name = "quinn-udp" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" -dependencies = [ - "libc", - "quinn-proto 0.9.6", - "socket2 0.4.10", - "tracing", - "windows-sys 0.42.0", -] - [[package]] name = "quinn-udp" version = "0.4.1" @@ -7580,20 +9128,26 @@ checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ "bytes", "libc", - "socket2 0.5.7", + "socket2 0.5.10", "tracing", "windows-sys 0.48.0", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "radium" version = "0.7.0" @@ -7607,8 +9161,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -7618,7 +9182,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -7627,7 +9201,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] @@ -7637,7 +9220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -7646,16 +9229,25 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", ] [[package]] name = "raw-cpuid" -version = "11.2.0" +version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", ] [[package]] @@ -7696,6 +9288,22 @@ dependencies = [ "yasna", ] +[[package]] +name = "reconnecting-jsonrpsee-ws-client" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06fa4f17e09edfc3131636082faaec633c7baa269396b4004040bc6c52f49f65" +dependencies = [ + "cfg_aliases 0.2.1", + "finito", + "futures", + "jsonrpsee 0.23.2", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -7707,11 +9315,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", ] [[package]] @@ -7720,29 +9328,29 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.16", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "ref-cast" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -7772,13 +9380,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -7793,9 +9401,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -7816,13 +9424,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resolv-conf" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", -] +checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" [[package]] name = "rfc6979" @@ -7851,13 +9455,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", "untrusted 0.9.0", "windows-sys 0.52.0", @@ -7877,6 +9481,16 @@ name = "rlp" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rlp" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" dependencies = [ "bytes", "rlp-derive", @@ -7885,13 +9499,13 @@ dependencies = [ [[package]] name = "rlp-derive" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "652db34deaaa57929e10ca18e5454a32cb0efc351ae80d320334bbf907b908b3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] @@ -7912,45 +9526,81 @@ checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] name = "rpassword" -version = "7.3.1" +version = "7.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" +checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "rtnetlink" -version = "0.10.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ "futures", "log", + "netlink-packet-core", "netlink-packet-route", + "netlink-packet-utils", "netlink-proto", + "netlink-sys", "nix", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "rtoolbox" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" +checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "ruint" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types 0.12.2", + "proptest", + "rand 0.8.5", + "rand 0.9.1", + "rlp 0.5.2", + "ruint-macro", + "serde", + "valuable", + "zeroize", ] +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -7960,9 +9610,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-hex" @@ -7979,13 +9629,22 @@ dependencies = [ "semver 0.9.0", ] +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.23", + "semver 1.0.26", ] [[package]] @@ -8013,76 +9672,222 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.14", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring 0.17.14", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +dependencies = [ + "log", + "once_cell", + "ring 0.17.14", + "rustls-pki-types", + "rustls-webpki 0.103.3", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.2.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", ] [[package]] -name = "rustls" -version = "0.20.9" +name = "rustls-pki-types" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "ring 0.16.20", - "sct", - "webpki", + "zeroize", ] [[package]] -name = "rustls" -version = "0.21.12" +name = "rustls-platform-verifier" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ + "core-foundation 0.9.4", + "core-foundation-sys", + "jni", "log", - "ring 0.17.13", - "rustls-webpki", - "sct", + "once_cell", + "rustls 0.23.28", + "rustls-native-certs 0.7.3", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.8", + "security-framework 2.11.1", + "security-framework-sys", + "webpki-roots 0.26.11", + "winapi", ] [[package]] -name = "rustls-native-certs" -version = "0.6.3" +name = "rustls-platform-verifier-android" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", + "ring 0.17.14", + "untrusted 0.9.0", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" +name = "rustls-webpki" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "base64 0.21.7", + "ring 0.17.14", + "rustls-pki-types", + "untrusted 0.9.0", ] [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ - "ring 0.17.13", + "ring 0.17.14", + "rustls-pki-types", "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ruzstd" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +dependencies = [ + "byteorder", + "derive_more 0.99.20", + "twox-hash", +] [[package]] name = "rw-stream-sink" @@ -8097,16 +9902,17 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "safe-math" version = "0.1.0" dependencies = [ "num-traits", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-arithmetic", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "substrate-fixed", ] @@ -8121,9 +9927,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ "bytemuck", ] @@ -8139,19 +9945,49 @@ dependencies = [ [[package]] name = "sc-allocator" -version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "30.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "log", "sp-core", "sp-wasm-interface 21.0.1", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "sc-authority-discovery" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "ip_network", + "libp2p", + "linked_hash_set", + "log", + "multihash 0.19.3", + "parity-scale-codec", + "prost 0.12.6", + "prost-build", + "rand 0.8.5", + "sc-client-api", + "sc-network", + "sc-network-types", + "sp-api", + "sp-authority-discovery", + "sp-blockchain", + "sp-core", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.69", ] [[package]] name = "sc-basic-authorship" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "futures", "futures-timer", @@ -8172,8 +10008,8 @@ dependencies = [ [[package]] name = "sc-block-builder" -version = "0.42.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.43.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "sp-api", @@ -8187,8 +10023,8 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "docify", @@ -8204,7 +10040,7 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-genesis-builder", "sp-io", "sp-runtime", @@ -8215,18 +10051,18 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sc-cli" -version = "0.47.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.50.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "chrono", @@ -8239,7 +10075,7 @@ dependencies = [ "names", "parity-bip39", "parity-scale-codec", - "rand", + "rand 0.8.5", "regex", "rpassword", "sc-client-api", @@ -8250,6 +10086,7 @@ dependencies = [ "sc-service", "sc-telemetry", "sc-tracing", + "sc-transaction-pool", "sc-utils", "serde", "serde_json", @@ -8260,20 +10097,20 @@ dependencies = [ "sp-panic-handler", "sp-runtime", "sp-version", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "sc-client-api" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "fnv", "futures", "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -8282,19 +10119,19 @@ dependencies = [ "sp-consensus", "sp-core", "sp-database", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-runtime", "sp-state-machine", "sp-statement-store", - "sp-storage 21.0.0", + "sp-storage 22.0.0", "sp-trie", "substrate-prometheus-endpoint", ] [[package]] name = "sc-client-db" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.45.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "hash-db", "kvdb", @@ -8304,7 +10141,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-state-db", "schnellru", @@ -8319,14 +10156,14 @@ dependencies = [ [[package]] name = "sc-consensus" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", "log", "mockall 0.11.4", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-network-types", "sc-utils", @@ -8338,13 +10175,13 @@ dependencies = [ "sp-runtime", "sp-state-machine", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-aura" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", @@ -8367,13 +10204,13 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-babe" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "fork-tree", @@ -8383,7 +10220,7 @@ dependencies = [ "num-rational", "num-traits", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -8398,18 +10235,18 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-slots", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-inherents", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-epochs" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "fork-tree", "parity-scale-codec", @@ -8421,10 +10258,10 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" -version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.33.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "array-bytes", "async-trait", "dyn-clone", @@ -8434,8 +10271,8 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -8456,21 +10293,21 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-grandpa-rpc" -version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.33.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "finality-grandpa", "futures", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", "sc-client-api", @@ -8480,19 +10317,19 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-manual-seal" -version = "0.46.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.49.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "assert_matches", "async-trait", "futures", "futures-timer", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", "sc-client-api", @@ -8515,13 +10352,13 @@ dependencies = [ "sp-runtime", "sp-timestamp", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-consensus-slots" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", @@ -8543,21 +10380,21 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.40.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", "schnellru", "sp-api", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-io", "sp-panic-handler", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", "sp-trie", "sp-version", "sp-wasm-interface 21.0.1", @@ -8566,21 +10403,21 @@ dependencies = [ [[package]] name = "sc-executor-common" -version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.36.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "polkavm", "sc-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface 21.0.1", - "thiserror", + "thiserror 1.0.69", "wasm-instrument", ] [[package]] name = "sc-executor-polkavm" -version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.33.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "log", "polkavm", @@ -8590,26 +10427,26 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" -version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.36.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "anyhow", "cfg-if", "libc", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "rustix 0.36.17", "sc-allocator", "sc-executor-common", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", "sp-wasm-interface 21.0.1", "wasmtime", ] [[package]] name = "sc-informant" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "console", "futures", @@ -8625,25 +10462,25 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "33.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "serde_json", "sp-application-crypto", "sp-core", "sp-keystore", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-mixnet" -version = "0.15.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.18.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", - "arrayvec", + "arrayvec 0.7.6", "blake2 0.10.6", "bytes", "futures", @@ -8652,7 +10489,7 @@ dependencies = [ "mixnet", "multiaddr 0.18.2", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-network", "sc-network-types", @@ -8663,16 +10500,16 @@ dependencies = [ "sp-keystore", "sp-mixnet", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-network" -version = "0.45.6" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.4" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", - "async-channel", + "async-channel 1.9.0", "async-trait", "asynchronous-codec", "bytes", @@ -8689,12 +10526,12 @@ dependencies = [ "mockall 0.11.4", "once_cell", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "partial_sort", "pin-project", "prost 0.12.6", - "prost-build 0.12.6", - "rand", + "prost-build", + "rand 0.8.5", "sc-client-api", "sc-network-common", "sc-network-types", @@ -8708,7 +10545,7 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "unsigned-varint 0.7.2", @@ -8719,15 +10556,15 @@ dependencies = [ [[package]] name = "sc-network-common" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "bitflags 1.3.2", "futures", "libp2p-identity", "parity-scale-codec", - "prost-build 0.12.6", + "prost-build", "sc-consensus", "sc-network-types", "sp-consensus", @@ -8737,10 +10574,10 @@ dependencies = [ [[package]] name = "sc-network-gossip" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "futures", "futures-timer", "log", @@ -8756,42 +10593,41 @@ dependencies = [ [[package]] name = "sc-network-light" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", - "async-channel", + "async-channel 1.9.0", "futures", "log", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build", "sc-client-api", "sc-network", "sc-network-types", "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-network-sync" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", - "async-channel", + "async-channel 1.9.0", "async-trait", "fork-tree", "futures", "futures-timer", - "libp2p", "log", "mockall 0.11.4", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build", "sc-client-api", "sc-consensus", "sc-network", @@ -8807,15 +10643,15 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] [[package]] name = "sc-network-transactions" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "futures", @@ -8833,39 +10669,42 @@ dependencies = [ [[package]] name = "sc-network-types" -version = "0.12.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.15.2" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "bs58 0.5.1", + "bs58", "ed25519-dalek", "libp2p-identity", "litep2p", "log", "multiaddr 0.18.2", - "multihash 0.19.2", - "rand", - "thiserror", + "multihash 0.19.3", + "rand 0.8.5", + "thiserror 1.0.69", "zeroize", ] [[package]] name = "sc-offchain" -version = "40.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "bytes", "fnv", "futures", "futures-timer", - "hyper 0.14.30", - "hyper-rustls", + "http-body-util", + "hyper 1.6.0", + "hyper-rustls 0.27.7", + "hyper-util", "log", "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", + "rustls 0.23.28", "sc-client-api", "sc-network", "sc-network-common", @@ -8874,7 +10713,7 @@ dependencies = [ "sc-utils", "sp-api", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-keystore", "sp-offchain", "sp-runtime", @@ -8885,7 +10724,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.18.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -8893,14 +10732,14 @@ dependencies = [ [[package]] name = "sc-rpc" -version = "40.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "futures", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -8925,10 +10764,10 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "jsonrpsee", + "jsonrpsee 0.24.9", "parity-scale-codec", "sc-chain-spec", "sc-mixnet", @@ -8940,23 +10779,23 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-version", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-rpc-server" -version = "17.1.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "dyn-clone", "forwarded-header-value", "futures", "governor", - "http 1.1.0", + "http 1.3.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.6.0", "ip_network", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "sc-rpc-api", "serde", @@ -8969,23 +10808,23 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.48.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "futures", "futures-util", "hex", - "jsonrpsee", + "itertools 0.11.0", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", "sc-chain-spec", "sc-client-api", "sc-rpc", "sc-transaction-pool-api", - "sc-utils", "schnellru", "serde", "sp-api", @@ -8994,27 +10833,27 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-version", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] [[package]] name = "sc-service" -version = "0.46.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.49.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "directories", "exit-future", "futures", "futures-timer", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project", - "rand", + "rand 0.8.5", "sc-chain-spec", "sc-client-api", "sc-client-db", @@ -9044,12 +10883,12 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-keystore", "sp-runtime", "sp-session", "sp-state-machine", - "sp-storage 21.0.0", + "sp-storage 22.0.0", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", @@ -9057,7 +10896,7 @@ dependencies = [ "static_init", "substrate-prometheus-endpoint", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -9065,69 +10904,68 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.36.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.37.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sp-core", ] [[package]] name = "sc-sysinfo" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "derive_more", + "derive_more 0.99.20", "futures", "libc", "log", - "rand", + "rand 0.8.5", "rand_pcg", "regex", "sc-telemetry", "serde", "serde_json", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", ] [[package]] name = "sc-telemetry" -version = "25.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "chrono", "futures", "libp2p", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project", - "rand", + "rand 0.8.5", "sc-network", "sc-utils", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "wasm-timer", ] [[package]] name = "sc-tracing" -version = "37.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "chrono", "console", "is-terminal", - "lazy_static", "libc", "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "rustc-hash 1.1.0", "sc-client-api", "sc-tracing-proc-macro", @@ -9138,35 +10976,37 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-tracing 17.0.1", - "thiserror", + "thiserror 1.0.69", "tracing", "tracing-log", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.19", ] [[package]] name = "sc-tracing-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sc-transaction-pool" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", "futures-timer", + "indexmap 2.9.0", + "itertools 0.11.0", "linked-hash-map", "log", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sc-client-api", "sc-transaction-pool-api", "sc-utils", @@ -9174,18 +11014,20 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-runtime", "sp-tracing 17.0.1", "sp-transaction-pool", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", + "tokio", + "tokio-stream", ] [[package]] name = "sc-transaction-pool-api" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", @@ -9195,20 +11037,19 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sc-utils" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "18.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "async-channel", + "async-channel 1.9.0", "futures", "futures-timer", - "lazy_static", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "prometheus", "sp-arithmetic", ] @@ -9220,7 +11061,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" dependencies = [ "parity-scale-codec", + "scale-info", "scale-type-resolver", + "serde", ] [[package]] @@ -9229,22 +11072,64 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" dependencies = [ - "derive_more", + "derive_more 0.99.20", + "parity-scale-codec", + "primitive-types 0.12.2", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb22f574168103cdd3133b19281639ca65ad985e24612728f727339dcaf4021" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528464e6ae6c8f98e2b79633bf79ef939552e795e316579dab09c61670d56602" +dependencies = [ + "derive_more 0.99.20", "parity-scale-codec", + "primitive-types 0.12.2", "scale-bits", + "scale-encode-derive", "scale-type-resolver", "smallvec", ] +[[package]] +name = "scale-encode-derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef2618f123c88da9cd8853b69d766068f1eddc7692146d7dfe9b89e25ce2efd" +dependencies = [ + "darling 0.20.11", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "scale-info" -version = "2.11.3" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" dependencies = [ "bitvec", "cfg-if", - "derive_more", + "derive_more 1.0.0", "parity-scale-codec", "scale-info-derive", "serde", @@ -9252,14 +11137,14 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.3" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.103", ] [[package]] @@ -9267,23 +11152,61 @@ name = "scale-type-resolver" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" +dependencies = [ + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-typegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498d1aecf2ea61325d4511787c115791639c0fd21ef4f8e11e49dd09eff2bbac" +dependencies = [ + "proc-macro2", + "quote", + "scale-info", + "syn 2.0.103", + "thiserror 1.0.69", +] + +[[package]] +name = "scale-value" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6ab090d823e75cfdb258aad5fe92e13f2af7d04b43a55d607d25fcc38c811" +dependencies = [ + "base58", + "blake2 0.10.6", + "derive_more 0.99.20", + "either", + "frame-metadata 15.1.0", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-type-resolver", + "serde", + "yap", +] [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "schnellru" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "cfg-if", "hashbrown 0.13.2", ] @@ -9296,17 +11219,23 @@ checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" dependencies = [ "aead", "arrayref", - "arrayvec", + "arrayvec 0.7.6", "curve25519-dalek", "getrandom_or_panic", "merlin", - "rand_core", + "rand_core 0.6.4", "serde_bytes", - "sha2 0.10.8", + "sha2 0.10.9", "subtle 2.6.1", "zeroize", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -9315,9 +11244,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scratch" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" +checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52" [[package]] name = "sct" @@ -9325,25 +11254,10 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.13", + "ring 0.17.14", "untrusted 0.9.0", ] -[[package]] -name = "sctp-proto" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" -dependencies = [ - "bytes", - "crc", - "fxhash", - "log", - "rand", - "slab", - "thiserror", -] - [[package]] name = "sec1" version = "0.7.3" @@ -9359,13 +11273,31 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.1", +] + [[package]] name = "secp256k1" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.9.2", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", ] [[package]] @@ -9383,17 +11315,31 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ - "zeroize", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", ] [[package]] name = "security-framework" -version = "2.11.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ - "bitflags 2.6.0", - "core-foundation", + "bitflags 2.9.1", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -9401,9 +11347,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -9415,7 +11361,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", ] [[package]] @@ -9424,14 +11370,23 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.3", ] [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] @@ -9442,6 +11397,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "send_wrapper" version = "0.6.0" @@ -9450,9 +11414,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.216" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] @@ -9468,9 +11432,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" dependencies = [ "serde", ] @@ -9487,20 +11451,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -9510,9 +11474,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -9551,10 +11515,10 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -9569,14 +11533,15 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.10.1" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.10.7", - "sha1-asm", + "digest 0.9.0", + "opaque-debug 0.3.1", ] [[package]] @@ -9590,15 +11555,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha1-asm" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" -dependencies = [ - "cc", -] - [[package]] name = "sha2" version = "0.9.9" @@ -9614,9 +11570,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -9633,6 +11589,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -9647,7 +11613,7 @@ name = "share-pool" version = "0.1.0" dependencies = [ "safe-math", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "substrate-fixed", ] @@ -9659,9 +11625,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -9673,14 +11639,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] name = "simba" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ "approx", "num-complex", @@ -9691,11 +11657,11 @@ dependencies = [ [[package]] name = "simple-dns" -version = "0.5.7" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae9a3fcdadafb6d97f4c0e007e4247b114ee0f119f650c3cbf3a8b3a1479694" +checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", ] [[package]] @@ -9710,14 +11676,17 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "slice-group-by" @@ -9727,9 +11696,117 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smoldot" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d1eaa97d77be4d026a1e7ffad1bb3b78448763b357ea6f8188d3e6f736a9b9" +dependencies = [ + "arrayvec 0.7.6", + "async-lock", + "atomic-take", + "base64 0.21.7", + "bip39", + "blake2-rfc", + "bs58", + "chacha20", + "crossbeam-queue", + "derive_more 0.99.20", + "ed25519-zebra", + "either", + "event-listener 4.0.3", + "fnv", + "futures-lite", + "futures-util", + "hashbrown 0.14.5", + "hex", + "hmac 0.12.1", + "itertools 0.12.1", + "libm", + "libsecp256k1", + "merlin", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2", + "pin-project", + "poly1305", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd", + "schnorrkel", + "serde", + "serde_json", + "sha2 0.10.9", + "sha3", + "siphasher 1.0.1", + "slab", + "smallvec", + "soketto 0.7.1", + "twox-hash", + "wasmi", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot-light" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" +dependencies = [ + "async-channel 2.3.1", + "async-lock", + "base64 0.21.7", + "blake2-rfc", + "derive_more 0.99.20", + "either", + "event-listener 4.0.3", + "fnv", + "futures-channel", + "futures-lite", + "futures-util", + "hashbrown 0.14.5", + "hex", + "itertools 0.12.1", + "log", + "lru 0.12.5", + "no-std-net", + "parking_lot 0.12.4", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "siphasher 1.0.1", + "slab", + "smol", + "smoldot", + "zeroize", +] [[package]] name = "snap" @@ -9747,10 +11824,10 @@ dependencies = [ "blake2 0.10.6", "chacha20poly1305", "curve25519-dalek", - "rand_core", - "ring 0.17.13", + "rand_core 0.6.4", + "ring 0.17.14", "rustc_version 0.4.1", - "sha2 0.10.8", + "sha2 0.10.9", "subtle 2.6.1", ] @@ -9766,9 +11843,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -9776,24 +11853,39 @@ dependencies = [ [[package]] name = "soketto" -version = "0.8.0" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "httparse", + "log", + "rand 0.8.5", + "sha-1", +] + +[[package]] +name = "soketto" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" +checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" dependencies = [ "base64 0.22.1", "bytes", "futures", - "http 1.1.0", + "http 1.3.1", "httparse", "log", - "rand", + "rand 0.8.5", "sha1", ] [[package]] name = "sp-api" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "hash-db", @@ -9802,34 +11894,34 @@ dependencies = [ "scale-info", "sp-api-proc-macro", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-metadata-ir", "sp-runtime", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", "sp-state-machine", "sp-trie", "sp-version", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-api-proc-macro" -version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "Inflector", "blake2 0.10.6", "expander", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-application-crypto" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "scale-info", @@ -9841,7 +11933,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "integer-sqrt", @@ -9855,16 +11947,28 @@ dependencies = [ [[package]] name = "sp-ark-bls12-381" version = "0.4.2" -source = "git+https://github.com/paritytech/substrate-curves#caa2eed74beb885dd07c7db5f916f2281dad818f" +source = "git+https://github.com/paritytech/substrate-curves#f08093a5f7c32778eae1295430ec064dccd062a6" dependencies = [ "ark-bls12-381-ext", "sp-crypto-ec-utils 0.10.0", ] +[[package]] +name = "sp-authority-discovery" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-runtime", +] + [[package]] name = "sp-block-builder" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "sp-api", "sp-inherents", @@ -9873,12 +11977,12 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "37.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "futures", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "schnellru", "sp-api", "sp-consensus", @@ -9886,14 +11990,14 @@ dependencies = [ "sp-database", "sp-runtime", "sp-state-machine", - "thiserror", + "thiserror 1.0.69", "tracing", ] [[package]] name = "sp-consensus" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "futures", @@ -9902,13 +12006,13 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-consensus-aura" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "parity-scale-codec", @@ -9923,8 +12027,8 @@ dependencies = [ [[package]] name = "sp-consensus-babe" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "parity-scale-codec", @@ -9941,8 +12045,8 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" -version = "21.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "22.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "finality-grandpa", "log", @@ -9958,8 +12062,8 @@ dependencies = [ [[package]] name = "sp-consensus-slots" -version = "0.40.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "scale-info", @@ -9969,20 +12073,20 @@ dependencies = [ [[package]] name = "sp-core" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", - "bs58 0.5.1", + "bs58", "dyn-clonable", "ed25519-zebra", "futures", "hash-db", "hash256-std-hasher", - "impl-serde", + "impl-serde 0.5.0", "itertools 0.11.0", "k256", "libsecp256k1", @@ -9990,24 +12094,24 @@ dependencies = [ "merlin", "parity-bip39", "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "paste", - "primitive-types", - "rand", + "primitive-types 0.13.1", + "rand 0.8.5", "scale-info", "schnorrkel", - "secp256k1", + "secp256k1 0.28.2", "secrecy", "serde", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-externalities 0.29.0", - "sp-runtime-interface 28.0.0", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-storage 21.0.0", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-externalities 0.30.0", + "sp-runtime-interface 29.0.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-storage 22.0.0", "ss58-registry", "substrate-bip39", - "thiserror", + "thiserror 1.0.69", "tracing", "w3f-bls", "zeroize", @@ -10016,7 +12120,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -10035,8 +12139,8 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" -version = "0.14.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.15.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -10050,7 +12154,7 @@ dependencies = [ "ark-ed-on-bls12-381-bandersnatch", "ark-ed-on-bls12-381-bandersnatch-ext", "ark-scale 0.0.12", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", ] [[package]] @@ -10062,7 +12166,7 @@ dependencies = [ "blake2b_simd", "byteorder", "digest 0.10.7", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", "twox-hash", ] @@ -10070,12 +12174,12 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "blake2b_simd", "byteorder", "digest 0.10.7", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", "twox-hash", ] @@ -10083,46 +12187,46 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "syn 2.0.90", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "syn 2.0.103", ] [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "kvdb", - "parking_lot 0.12.3", + "parking_lot 0.12.4", ] [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "environmental", "parity-scale-codec", @@ -10131,18 +12235,18 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.30.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "environmental", "parity-scale-codec", - "sp-storage 21.0.0", + "sp-storage 22.0.0", ] [[package]] name = "sp-genesis-builder" -version = "0.15.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.16.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "scale-info", @@ -10153,21 +12257,21 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "impl-trait-for-tuples", "parity-scale-codec", "scale-info", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-io" -version = "38.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "39.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "bytes", "docify", @@ -10175,14 +12279,14 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "polkavm-derive", + "polkavm-derive 0.9.1", "rustversion", - "secp256k1", + "secp256k1 0.28.2", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-externalities 0.29.0", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-externalities 0.30.0", "sp-keystore", - "sp-runtime-interface 28.0.0", + "sp-runtime-interface 29.0.0", "sp-state-machine", "sp-tracing 17.0.1", "sp-trie", @@ -10192,8 +12296,8 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "39.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "40.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "sp-core", "sp-runtime", @@ -10202,38 +12306,38 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", ] [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "thiserror", + "thiserror 1.0.69", "zstd 0.12.4", ] [[package]] name = "sp-metadata-ir" -version = "0.7.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.8.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "frame-metadata", + "frame-metadata 18.0.0", "parity-scale-codec", "scale-info", ] [[package]] name = "sp-mixnet" -version = "0.12.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.13.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "scale-info", @@ -10243,8 +12347,8 @@ dependencies = [ [[package]] name = "sp-offchain" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "sp-api", "sp-core", @@ -10253,18 +12357,17 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "13.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "backtrace", - "lazy_static", "regex", ] [[package]] name = "sp-rpc" -version = "32.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "33.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -10273,9 +12376,10 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "39.0.5" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "40.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ + "binary-merkle-tree", "docify", "either", "hash256-std-hasher", @@ -10284,7 +12388,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "paste", - "rand", + "rand 0.8.5", "scale-info", "serde", "simple-mermaid", @@ -10292,21 +12396,23 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-trie", "sp-weights", "tracing", + "tuplex", ] [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive", - "primitive-types", + "polkavm-derive 0.24.0", + "primitive-types 0.13.1", "sp-externalities 0.25.0", "sp-runtime-interface-proc-macro 17.0.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", @@ -10318,18 +12424,18 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "29.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive", - "primitive-types", - "sp-externalities 0.29.0", + "polkavm-derive 0.9.1", + "primitive-types 0.13.1", + "sp-externalities 0.30.0", "sp-runtime-interface-proc-macro 18.0.0", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-storage 21.0.0", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-storage 22.0.0", "sp-tracing 17.0.1", "sp-wasm-interface 21.0.1", "static_assertions", @@ -10338,33 +12444,33 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "Inflector", "expander", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-runtime-interface-proc-macro" version = "18.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "Inflector", "expander", - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-session" -version = "36.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "scale-info", @@ -10377,8 +12483,8 @@ dependencies = [ [[package]] name = "sp-staking" -version = "36.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -10390,64 +12496,64 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.43.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.44.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", "smallvec", "sp-core", - "sp-externalities 0.29.0", + "sp-externalities 0.30.0", "sp-panic-handler", "sp-trie", - "thiserror", + "thiserror 1.0.69", "tracing", "trie-db", ] [[package]] name = "sp-statement-store" -version = "18.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "19.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "aes-gcm", "curve25519-dalek", "ed25519-dalek", "hkdf", "parity-scale-codec", - "rand", + "rand 0.8.5", "scale-info", - "sha2 0.10.8", + "sha2 0.10.9", "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", - "sp-externalities 0.29.0", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "sp-externalities 0.30.0", "sp-runtime", - "sp-runtime-interface 28.0.0", - "thiserror", + "sp-runtime-interface 29.0.0", + "thiserror 1.0.69", "x25519-dalek", ] [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ - "impl-serde", + "impl-serde 0.5.0", "parity-scale-codec", "ref-cast", "serde", @@ -10456,54 +12562,54 @@ dependencies = [ [[package]] name = "sp-storage" -version = "21.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "22.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "impl-serde", + "impl-serde 0.5.0", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", ] [[package]] name = "sp-timestamp" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", "sp-runtime", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.19", ] [[package]] name = "sp-tracing" version = "17.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber 0.3.18", + "tracing-subscriber 0.3.19", ] [[package]] name = "sp-transaction-pool" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "sp-api", "sp-runtime", @@ -10511,8 +12617,8 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "35.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "async-trait", "parity-scale-codec", @@ -10525,22 +12631,21 @@ dependencies = [ [[package]] name = "sp-trie" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "hash-db", - "lazy_static", "memory-db", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", "scale-info", "schnellru", "sp-core", - "sp-externalities 0.29.0", - "thiserror", + "sp-externalities 0.30.0", + "thiserror 1.0.69", "tracing", "trie-db", "trie-root", @@ -10548,36 +12653,37 @@ dependencies = [ [[package]] name = "sp-version" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ - "impl-serde", + "impl-serde 0.5.0", "parity-scale-codec", "parity-wasm", "scale-info", "serde", "sp-crypto-hashing-proc-macro", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", "sp-version-proc-macro", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "sp-version-proc-macro" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "15.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "parity-scale-codec", + "proc-macro-warning 1.84.1", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#8614dc0e055d06de4a3774ac1da0a422b33f34e2" +source = "git+https://github.com/paritytech/polkadot-sdk#f6cd17e550caeaa1b8184b5f3135ca21f2cb16eb" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -10588,7 +12694,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "21.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -10600,7 +12706,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "31.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -10608,7 +12714,7 @@ dependencies = [ "serde", "smallvec", "sp-arithmetic", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", ] [[package]] @@ -10645,21 +12751,11 @@ dependencies = [ "der", ] -[[package]] -name = "sqlformat" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" -dependencies = [ - "nom", - "unicode_categories", -] - [[package]] name = "sqlx" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", @@ -10668,37 +12764,32 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ - "atoi", - "byteorder", + "base64 0.22.1", "bytes", "crc", "crossbeam-queue", "either", - "event-listener 5.3.1", - "futures-channel", + "event-listener 5.4.0", "futures-core", "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.14.5", - "hashlink 0.9.1", - "hex", - "indexmap 2.6.0", + "hashbrown 0.15.4", + "hashlink 0.10.0", + "indexmap 2.9.0", "log", "memchr", "native-tls", "once_cell", - "paste", "percent-encoding", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "smallvec", - "sqlformat", - "thiserror", + "thiserror 2.0.12", "tokio", "tokio-stream", "tracing", @@ -10707,22 +12798,22 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "sqlx-macros-core" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" dependencies = [ "dotenvy", "either", @@ -10733,20 +12824,19 @@ dependencies = [ "quote", "serde", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "sqlx-core", "sqlx-sqlite", - "syn 2.0.90", - "tempfile", + "syn 2.0.103", "tokio", "url", ] [[package]] name = "sqlx-sqlite" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", "flume", @@ -10761,15 +12851,16 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", + "thiserror 2.0.12", "tracing", "url", ] [[package]] name = "ss58-registry" -version = "1.50.0" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fce22ed1df64d04b262351c8f9d5c6da4f76f79f25ad15529792f893fad25d" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" dependencies = [ "Inflector", "num-format", @@ -10788,13 +12879,15 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-xcm" -version = "14.2.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "15.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "bounded-collections", "derivative", "environmental", + "frame-support", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -10813,52 +12906,38 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "static_init" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" +checksum = "8bae1df58c5fea7502e8e352ec26b5579f6178e1fdb311e088580c980dee25ed" dependencies = [ "bitflags 1.3.2", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", - "parking_lot 0.11.2", - "parking_lot_core 0.8.6", + "parking_lot 0.12.4", + "parking_lot_core 0.9.11", "static_init_macro", "winapi", ] [[package]] name = "static_init_macro" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" +checksum = "1389c88ddd739ec6d3f8f83343764a0e944cd23cfbf126a9796a714b0b6edd6f" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.1.1", "memchr", "proc-macro2", "quote", "syn 1.0.109", ] -[[package]] -name = "str0m" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" -dependencies = [ - "combine", - "crc", - "fastrand", - "hmac 0.12.1", - "once_cell", - "openssl", - "openssl-sys", - "sctp-proto", - "serde", - "sha-1", - "thiserror", - "tracing", -] - +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -10903,25 +12982,25 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "substrate-bip39" version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "hmac 0.12.1", "pbkdf2", "schnorrkel", - "sha2 0.10.8", + "sha2 0.10.9", "zeroize", ] [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" [[package]] name = "substrate-fixed" @@ -10936,13 +13015,13 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" -version = "39.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "42.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "docify", "frame-system-rpc-runtime-api", "futures", - "jsonrpsee", + "jsonrpsee 0.24.9", "log", "parity-scale-codec", "sc-rpc-api", @@ -10956,35 +13035,36 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" -version = "0.17.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "0.17.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "http-body-util", - "hyper 1.5.0", + "hyper 1.6.0", "hyper-util", "log", "prometheus", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "substrate-wasm-builder" -version = "24.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "25.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "array-bytes", "build-helper", "cargo_metadata", "console", "filetime", - "frame-metadata", + "frame-metadata 18.0.0", "jobserver", "merkleized-metadata", "parity-scale-codec", "parity-wasm", "polkavm-linker", "sc-executor", + "shlex", "sp-core", "sp-io", "sp-maybe-compressed-blob", @@ -10992,7 +13072,7 @@ dependencies = [ "sp-version", "strum 0.26.3", "tempfile", - "toml 0.8.19", + "toml 0.8.23", "walkdir", "wasm-opt", ] @@ -11007,7 +13087,7 @@ dependencies = [ "quote", "rayon", "subtensor-linting", - "syn 2.0.90", + "syn 2.0.103", "walkdir", ] @@ -11015,7 +13095,7 @@ dependencies = [ name = "subtensor-custom-rpc" version = "0.0.2" dependencies = [ - "jsonrpsee", + "jsonrpsee 0.24.9", "pallet-subtensor", "parity-scale-codec", "serde", @@ -11024,6 +13104,7 @@ dependencies = [ "sp-rpc", "sp-runtime", "subtensor-custom-rpc-runtime-api", + "subtensor-runtime-common", ] [[package]] @@ -11036,6 +13117,7 @@ dependencies = [ "serde", "sp-api", "sp-runtime", + "subtensor-runtime-common", ] [[package]] @@ -11045,17 +13127,17 @@ dependencies = [ "proc-macro2", "procedural-fork", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "subtensor-macros" version = "0.1.0" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -11070,16 +13152,21 @@ dependencies = [ "pallet-admin-utils", "pallet-balances", "pallet-evm", + "pallet-evm-precompile-dispatch", "pallet-evm-precompile-modexp", "pallet-evm-precompile-sha3fips", "pallet-evm-precompile-simple", "pallet-proxy 38.0.0", "pallet-subtensor", + "pallet-subtensor-swap", "precompile-utils", "sp-core", + "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6)", + "substrate-fixed", "subtensor-runtime-common", + "subtensor-swap-interface", ] [[package]] @@ -11089,8 +13176,21 @@ dependencies = [ "frame-support", "parity-scale-codec", "scale-info", + "serde", "sp-core", "sp-runtime", + "subtensor-macros", +] + +[[package]] +name = "subtensor-swap-interface" +version = "0.1.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "substrate-fixed", + "subtensor-runtime-common", ] [[package]] @@ -11099,7 +13199,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "semver 1.0.23", + "semver 1.0.26", "toml_edit", ] @@ -11115,6 +13215,159 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subxt" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a160cba1edbf3ec4fbbeaea3f1a185f70448116a6bccc8276bb39adb3b3053bd" +dependencies = [ + "async-trait", + "derive-where", + "either", + "frame-metadata 16.0.0", + "futures", + "hex", + "impl-serde 0.4.0", + "instant", + "jsonrpsee 0.22.5", + "parity-scale-codec", + "primitive-types 0.12.2", + "reconnecting-jsonrpsee-ws-client", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subxt-core", + "subxt-lightclient", + "subxt-macro", + "subxt-metadata", + "thiserror 1.0.69", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "subxt-codegen" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d703dca0905cc5272d7cc27a4ac5f37dcaae7671acc7fef0200057cc8c317786" +dependencies = [ + "frame-metadata 16.0.0", + "heck 0.5.0", + "hex", + "jsonrpsee 0.22.5", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "scale-typegen", + "subxt-metadata", + "syn 2.0.103", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "subxt-core" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af3b36405538a36b424d229dc908d1396ceb0994c90825ce928709eac1a159a" +dependencies = [ + "base58", + "blake2 0.10.6", + "derive-where", + "frame-metadata 16.0.0", + "hashbrown 0.14.5", + "hex", + "impl-serde 0.4.0", + "parity-scale-codec", + "primitive-types 0.12.2", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subxt-metadata", + "tracing", +] + +[[package]] +name = "subxt-lightclient" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9406fbdb9548c110803cb8afa750f8b911d51eefdf95474b11319591d225d9" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-macro" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c195f803d70687e409aba9be6c87115b5da8952cd83c4d13f2e043239818fcd" +dependencies = [ + "darling 0.20.11", + "parity-scale-codec", + "proc-macro-error", + "quote", + "scale-typegen", + "subxt-codegen", + "syn 2.0.103", +] + +[[package]] +name = "subxt-metadata" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738be5890fdeff899bbffff4d9c0f244fe2a952fb861301b937e3aa40ebb55da" +dependencies = [ + "frame-metadata 16.0.0", + "hashbrown 0.14.5", + "parity-scale-codec", + "scale-info", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "subxt-signer" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49888ae6ae90fe01b471193528eea5bd4ed52d8eecd2d13f4a2333b87388850" +dependencies = [ + "bip32", + "bip39", + "cfg-if", + "hex", + "hmac 0.12.1", + "keccak-hash", + "parity-scale-codec", + "pbkdf2", + "regex", + "schnorrkel", + "secp256k1 0.28.2", + "secrecy", + "sha2 0.10.9", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subxt-core", + "zeroize", +] + [[package]] name = "syn" version = "1.0.109" @@ -11128,9 +13381,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", @@ -11151,36 +13404,42 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", - "core-foundation", + "bitflags 2.9.1", + "core-foundation 0.9.4", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -11195,14 +13454,14 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.3", "once_cell", - "rustix 0.38.37", + "rustix 1.0.7", "windows-sys 0.59.0", ] @@ -11217,38 +13476,58 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 0.38.37", + "rustix 1.0.7", "windows-sys 0.59.0", ] [[package]] name = "termtree" -version = "0.4.1" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] [[package]] name = "thiserror" -version = "1.0.64" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -11259,12 +13538,11 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -11276,6 +13554,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "tikv-jemalloc-ctl" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c" +dependencies = [ + "libc", + "paste", + "tikv-jemalloc-sys", +] + [[package]] name = "tikv-jemalloc-sys" version = "0.5.4+5.3.0-patched" @@ -11288,9 +13577,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -11303,15 +13592,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -11326,11 +13615,21 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -11350,39 +13649,39 @@ dependencies = [ "ark-bls12-377", "ark-bls12-381", "ark-ec", - "ark-ff", + "ark-ff 0.4.2", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "array-bytes", "chacha20poly1305", "generic-array 0.14.7", "parity-scale-codec", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "scale-info", "serde", "serde_cbor", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", "w3f-bls", ] [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", ] @@ -11395,7 +13694,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -11408,11 +13707,32 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls 0.23.28", + "tokio", +] + [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -11422,24 +13742,25 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.21.12", - "rustls-native-certs", + "rustls 0.23.28", + "rustls-native-certs 0.8.1", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -11460,9 +13781,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -11472,26 +13793,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" version = "0.4.13" @@ -11513,9 +13841,9 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "bytes", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", "pin-project-lite", @@ -11537,9 +13865,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -11549,20 +13877,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -11578,6 +13906,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-gum" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "coarsetime", + "polkadot-primitives", + "tracing", + "tracing-gum-proc-macro", +] + +[[package]] +name = "tracing-gum-proc-macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "expander", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "tracing-log" version = "0.2.0" @@ -11600,14 +13951,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "regex", "sharded-slab", "smallvec", @@ -11655,10 +14006,10 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "rand", + "rand 0.8.5", "smallvec", "socket2 0.4.10", - "thiserror", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -11681,9 +14032,9 @@ dependencies = [ "idna 0.4.0", "ipnet", "once_cell", - "rand", + "rand 0.8.5", "smallvec", - "thiserror", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -11701,11 +14052,11 @@ dependencies = [ "ipconfig", "lru-cache", "once_cell", - "parking_lot 0.12.3", - "rand", + "parking_lot 0.12.4", + "rand 0.8.5", "resolv-conf", "smallvec", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "trust-dns-proto 0.23.2", @@ -11725,24 +14076,30 @@ checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "byteorder", "bytes", "data-encoding", - "http 0.2.12", + "http 1.3.1", "httparse", "log", - "rand", - "rustls 0.21.12", + "rand 0.9.1", + "rustls 0.23.28", + "rustls-pki-types", "sha1", - "thiserror", + "thiserror 2.0.12", "url", "utf-8", ] +[[package]] +name = "tuplex" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" + [[package]] name = "twox-hash" version = "1.6.3" @@ -11751,7 +14108,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand", + "rand 0.8.5", "static_assertions", ] @@ -11766,9 +14123,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ucd-trie" @@ -11788,17 +14145,35 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" @@ -11809,11 +14184,17 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" -version = "0.1.14" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unicode-xid" @@ -11821,12 +14202,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - [[package]] name = "universal-hash" version = "0.5.1" @@ -11873,12 +14248,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", ] @@ -11888,17 +14263,34 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -11927,21 +14319,30 @@ dependencies = [ "ark-bls12-377", "ark-bls12-381", "ark-ec", - "ark-ff", - "ark-serialize", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", "ark-serialize-derive", "arrayref", "constcat", "digest 0.10.7", - "rand", - "rand_chacha", - "rand_core", - "sha2 0.10.8", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "sha2 0.10.9", "sha3", - "thiserror", + "thiserror 1.0.69", "zeroize", ] +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -11963,53 +14364,72 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasix" +version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi 0.11.1+wasi-snapshot-preview1", +] [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12017,22 +14437,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-instrument" @@ -12054,7 +14477,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "tempfile", - "thiserror", + "thiserror 1.0.69", "wasm-opt-cxx-sys", "wasm-opt-sys", ] @@ -12098,6 +14521,37 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmi" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8281d1d660cdf54c76a3efa9ddd0c270cada1383a995db3ccb43d166456c7" +dependencies = [ + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.102.0" @@ -12108,6 +14562,15 @@ dependencies = [ "url", ] +[[package]] +name = "wasmparser-nostd" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" +dependencies = [ + "indexmap-nostd", +] + [[package]] name = "wasmtime" version = "8.0.1" @@ -12159,7 +14622,7 @@ dependencies = [ "log", "rustix 0.36.17", "serde", - "sha2 0.10.8", + "sha2 0.10.9", "toml 0.5.11", "windows-sys 0.45.0", "zstd 0.11.2+zstd.1.5.2", @@ -12181,7 +14644,7 @@ dependencies = [ "log", "object 0.30.4", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -12216,7 +14679,7 @@ dependencies = [ "object 0.30.4", "serde", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-types", ] @@ -12283,7 +14746,7 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand", + "rand 0.8.5", "rustix 0.36.17", "wasmtime-asm-macros", "wasmtime-environ", @@ -12299,28 +14762,28 @@ checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" dependencies = [ "cranelift-entity", "serde", - "thiserror", + "thiserror 1.0.69", "wasmparser", ] [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] -name = "webpki" -version = "0.22.4" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "ring 0.17.13", - "untrusted 0.9.0", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -12330,22 +14793,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] -name = "which" -version = "4.4.2" +name = "webpki-roots" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.37", + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", ] [[package]] name = "wide" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" +checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" dependencies = [ "bytemuck", "safe_arch", @@ -12353,9 +14822,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" [[package]] name = "winapi" @@ -12390,45 +14859,133 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.51.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" dependencies = [ - "windows-core 0.51.1", - "windows-targets 0.48.5", + "windows-core 0.53.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", ] [[package]] name = "windows-core" -version = "0.51.1" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" dependencies = [ - "windows-targets 0.48.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result 0.3.4", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ "windows-targets 0.52.6", ] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-result" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", ] [[package]] @@ -12506,13 +15063,38 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -12531,6 +15113,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -12549,6 +15137,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -12567,12 +15161,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -12591,6 +15197,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -12609,6 +15221,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -12627,6 +15245,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -12645,11 +15269,17 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -12664,6 +15294,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "wyz" version = "0.5.1" @@ -12680,7 +15325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "serde", "zeroize", ] @@ -12698,43 +15343,43 @@ dependencies = [ "nom", "oid-registry 0.6.1", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ - "asn1-rs 0.6.2", + "asn1-rs 0.7.1", "data-encoding", - "der-parser 9.0.0", + "der-parser 10.0.0", "lazy_static", "nom", - "oid-registry 0.7.1", + "oid-registry 0.8.1", "rusticata-macros", - "thiserror", + "thiserror 2.0.12", "time", ] [[package]] name = "xcm-procedural" -version = "10.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409-7#0c9644766f02c872f51e5b72adf1051189fe9126" +version = "11.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmltree" @@ -12754,12 +15399,34 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.3", + "parking_lot 0.12.4", + "pin-project", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "yamux" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da1acad1c2dc53f0dde419115a38bd8221d8c3e47ae9aeceaf453266d29307e" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot 0.12.4", "pin-project", - "rand", + "rand 0.9.1", "static_assertions", + "web-time", ] +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + [[package]] name = "yasna" version = "0.5.2" @@ -12769,25 +15436,69 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", + "synstructure 0.13.2", +] + [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", + "synstructure 0.13.2", ] [[package]] @@ -12807,7 +15518,40 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] @@ -12850,9 +15594,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 548bc5af63..839558d18b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,31 +33,40 @@ members = [ ] resolver = "2" +[workspace.package] +edition = "2024" + [workspace.lints.clippy] -indexing-slicing = "deny" arithmetic-side-effects = "deny" +indexing-slicing = "deny" +manual_inspect = "allow" +result_large_err = "allow" type_complexity = "allow" unwrap-used = "deny" -manual_inspect = "allow" useless_conversion = "allow" # until polkadot is patched [workspace.dependencies] +node-subtensor-runtime = { default-features = false, path = "runtime" } pallet-admin-utils = { default-features = false, path = "pallets/admin-utils" } pallet-collective = { default-features = false, path = "pallets/collective" } pallet-commitments = { default-features = false, path = "pallets/commitments" } pallet-registry = { default-features = false, path = "pallets/registry" } pallet-crowdloan = { default-features = false, path = "pallets/crowdloan" } pallet-subtensor = { default-features = false, path = "pallets/subtensor" } +pallet-subtensor-swap = { default-features = false, path = "pallets/swap" } +pallet-subtensor-swap-runtime-api = { default-features = false, path = "pallets/swap/runtime-api" } +pallet-subtensor-swap-rpc = { default-features = false, path = "pallets/swap/rpc" } +safe-math = { default-features = false, path = "primitives/safe-math" } subtensor-custom-rpc = { default-features = false, path = "pallets/subtensor/rpc" } subtensor-custom-rpc-runtime-api = { default-features = false, path = "pallets/subtensor/runtime-api" } subtensor-precompiles = { default-features = false, path = "precompiles" } subtensor-runtime-common = { default-features = false, path = "common" } -node-subtensor-runtime = { default-features = false, path = "runtime" } +subtensor-swap-interface = { default-features = false, path = "pallets/swap-interface" } async-trait = "0.1" cargo-husky = { version = "1", default-features = false } clap = "4.5.4" -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.7.5", default-features = false, features = [ "derive", ] } ed25519-dalek = { version = "2.1.0", default-features = false, features = [ @@ -67,7 +76,7 @@ enumflags2 = "0.7.9" futures = "0.3.30" hex = { version = "0.4", default-features = false } hex-literal = "0.4.1" -jsonrpsee = { version = "0.24.4", default-features = false } +jsonrpsee = { version = "0.24.9", default-features = false } libsecp256k1 = { version = "0.7.2", default-features = false } log = { version = "0.4.21", default-features = false } memmap2 = "0.9.4" @@ -97,131 +106,135 @@ proc-macro2 = { version = "1", features = ["span-locations"] } thiserror = "1.0" walkdir = "2" approx = "0.5" +alloy-primitives = { version = "0.8.23", default-features = false } subtensor-macros = { path = "support/macros" } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +frame-metadata = "18.0.0" -pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } pallet-proxy = { path = "pallets/proxy", default-features = false } -pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } pallet-utility = { path = "pallets/utility", default-features = false } -pallet-root-testing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +pallet-root-testing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } -sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } +sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } substrate-fixed = { git = "https://github.com/opentensor/substrate-fixed.git", tag = "v0.5.9" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6" } -sc-consensus-manual-seal = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -sc-network-sync = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +sc-consensus-manual-seal = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +sc-network-sync = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } # Frontier -fp-evm = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fp-rpc = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fp-self-contained = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false, features = [ +fp-evm = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fp-rpc = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fp-self-contained = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false, features = [ "serde", ] } -fp-account = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-storage = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-db = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-consensus = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fp-consensus = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fp-dynamic-fee = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-api = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-rpc = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false, features = [ +fp-account = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-storage = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-db = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-consensus = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fp-consensus = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fp-dynamic-fee = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-api = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-rpc = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false, features = [ "rpc-binary-search-estimate", ] } -fc-rpc-core = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-aura = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -fc-mapping-sync = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -precompile-utils = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } +fc-rpc-core = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-aura = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +fc-mapping-sync = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +precompile-utils = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } # Frontier FRAME -pallet-base-fee = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-dynamic-fee = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-ethereum = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-evm = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-evm-chain-id = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-evm-precompile-modexp = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-evm-precompile-sha3fips = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-evm-precompile-simple = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } -pallet-hotfix-sufficients = { git = "https://github.com/opentensor/frontier", rev = "cd6bca14a3", default-features = false } +pallet-base-fee = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-dynamic-fee = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-ethereum = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm-precompile-dispatch = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm-chain-id = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm-precompile-modexp = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm-precompile-sha3fips = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-evm-precompile-simple = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } +pallet-hotfix-sufficients = { git = "https://github.com/opentensor/frontier", rev = "4aeb35e5ce815a2d4998a349d47e773190a3396c", default-features = false } #DRAND pallet-drand = { path = "pallets/drand", default-features = false } -sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", features = [ +sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", features = [ "bls12-381", ] } getrandom = { version = "0.2.15", features = [ "custom", ], default-features = false } -sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2409-7", default-features = false } +sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", default-features = false } w3f-bls = { version = "=0.1.3", default-features = false } ark-crypto-primitives = { version = "0.4.0", default-features = false, features = [ "r1cs", @@ -245,7 +258,7 @@ sha2 = { version = "0.10.8", default-features = false } rand_chacha = { version = "0.3.1", default-features = false } tle = { git = "https://github.com/ideal-lab5/timelock", rev = "5416406cfd32799e31e1795393d4916894de4468", default-features = false } -frame-metadata = "16" +cumulus-primitives-proof-size-hostfunction = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-stable2412-6", package = "cumulus-primitives-proof-size-hostfunction", default-features = false } [profile.release] panic = "unwind" diff --git a/Dockerfile-localnet b/Dockerfile-localnet index 0de11cb866..d95a2f1a2c 100644 --- a/Dockerfile-localnet +++ b/Dockerfile-localnet @@ -15,6 +15,7 @@ LABEL ai.opentensor.image.authors="operations@opentensor.ai" \ # Set up Rust environment ENV RUST_BACKTRACE=1 +RUN sed -i 's|http://archive.ubuntu.com/ubuntu|http://mirrors.edge.kernel.org/ubuntu|g' /etc/apt/sources.list RUN apt-get update RUN apt-get install -y curl build-essential protobuf-compiler clang git pkg-config libssl-dev llvm libudev-dev diff --git a/common/Cargo.toml b/common/Cargo.toml index d0b43cdc1b..b46a4de4a9 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -14,8 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { workspace = true } frame-support = { workspace = true } scale-info = { workspace = true } -sp-runtime = { workspace = true } +serde = { workspace = true } sp-core = { workspace = true } +sp-runtime = { workspace = true } +subtensor-macros = { workspace = true } [lints] workspace = true @@ -27,6 +29,7 @@ std = [ "codec/std", "frame-support/std", "scale-info/std", + "serde/std", "sp-core/std", "sp-runtime/std", ] diff --git a/common/src/lib.rs b/common/src/lib.rs index 75b18e3b14..9134b77295 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -1,11 +1,15 @@ #![cfg_attr(not(feature = "std"), no_std)] +use core::fmt::{self, Display, Formatter}; -use codec::{Decode, Encode, MaxEncodedLen}; +use codec::{Compact, CompactAs, Decode, Encode, Error as CodecError, MaxEncodedLen}; +use frame_support::pallet_prelude::*; use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; use sp_runtime::{ MultiSignature, traits::{IdentifyAccount, Verify}, }; +use subtensor_macros::freeze_struct; /// Balance of an account. pub type Balance = u64; @@ -31,6 +35,90 @@ pub type Nonce = u32; /// Transfers below SMALL_TRANSFER_LIMIT are considered small transfers pub const SMALL_TRANSFER_LIMIT: Balance = 500_000_000; // 0.5 TAO +#[freeze_struct("9b6be98fb98e9b17")] +#[repr(transparent)] +#[derive( + Deserialize, + Serialize, + Clone, + Copy, + Decode, + Default, + Encode, + Eq, + Hash, + MaxEncodedLen, + Ord, + PartialEq, + PartialOrd, + RuntimeDebug, +)] +#[serde(transparent)] +pub struct NetUid(u16); + +impl NetUid { + pub const ROOT: NetUid = Self(0); + + pub fn is_root(&self) -> bool { + *self == Self::ROOT + } + + pub fn next(&self) -> NetUid { + Self(self.0.saturating_add(1)) + } + + pub fn prev(&self) -> NetUid { + Self(self.0.saturating_sub(1)) + } + + pub fn inner(&self) -> u16 { + self.0 + } +} + +impl Display for NetUid { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl CompactAs for NetUid { + type As = u16; + + fn encode_as(&self) -> &Self::As { + &self.0 + } + + fn decode_from(v: Self::As) -> Result { + Ok(Self(v)) + } +} + +impl From> for NetUid { + fn from(c: Compact) -> Self { + c.0 + } +} + +impl From for u16 { + fn from(val: NetUid) -> Self { + val.0 + } +} + +impl From for NetUid { + fn from(value: u16) -> Self { + Self(value) + } +} + +impl TypeInfo for NetUid { + type Identity = ::Identity; + fn type_info() -> scale_info::Type { + ::type_info() + } +} + #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, )] @@ -50,6 +138,7 @@ pub enum ProxyType { RootWeights, ChildKeys, SudoUncheckedSetCode, + SwapHotkey, } impl Default for ProxyType { @@ -59,6 +148,37 @@ impl Default for ProxyType { } } +pub trait SubnetInfo { + fn tao_reserve(netuid: NetUid) -> u64; + fn alpha_reserve(netuid: NetUid) -> u64; + fn exists(netuid: NetUid) -> bool; + fn mechanism(netuid: NetUid) -> u16; + fn is_owner(account_id: &AccountId, netuid: NetUid) -> bool; +} + +pub trait BalanceOps { + fn tao_balance(account_id: &AccountId) -> u64; + fn alpha_balance(netuid: NetUid, coldkey: &AccountId, hotkey: &AccountId) -> u64; + fn increase_balance(coldkey: &AccountId, tao: u64); + fn decrease_balance(coldkey: &AccountId, tao: u64) -> Result; + fn increase_stake( + coldkey: &AccountId, + hotkey: &AccountId, + netuid: NetUid, + alpha: u64, + ) -> Result<(), DispatchError>; + fn decrease_stake( + coldkey: &AccountId, + hotkey: &AccountId, + netuid: NetUid, + alpha: u64, + ) -> Result; + fn increase_provided_tao_reserve(netuid: NetUid, tao: u64); + fn decrease_provided_tao_reserve(netuid: NetUid, tao: u64); + fn increase_provided_alpha_reserve(netuid: NetUid, alpha: u64); + fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: u64); +} + pub mod time { use super::*; @@ -84,3 +204,13 @@ pub mod time { pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn netuid_has_u16_bin_repr() { + assert_eq!(NetUid(5).encode(), 5u16.encode()); + } +} diff --git a/docs/img/sigmoid_steepness.png b/docs/img/sigmoid_steepness.png new file mode 100644 index 0000000000..08dc4f4f5e Binary files /dev/null and b/docs/img/sigmoid_steepness.png differ diff --git a/evm-tests/get-metadata.sh b/evm-tests/get-metadata.sh old mode 100644 new mode 100755 diff --git a/evm-tests/package-lock.json b/evm-tests/package-lock.json deleted file mode 100644 index ce2766fb4e..0000000000 --- a/evm-tests/package-lock.json +++ /dev/null @@ -1,5815 +0,0 @@ -{ - "name": "evm-tests", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "license": "ISC", - "dependencies": { - "@polkadot-labs/hdkd": "^0.0.10", - "@polkadot-labs/hdkd-helpers": "^0.0.11", - "@polkadot/api": "15.1.1", - "@types/mocha": "^10.0.10", - "crypto": "^1.0.1", - "dotenv": "16.4.7", - "ethers": "^6.13.5", - "mocha": "^11.1.0", - "polkadot-api": "^1.9.5", - "scale-ts": "^1.6.1", - "viem": "2.23.4" - }, - "devDependencies": { - "@types/bun": "^1.1.13", - "@types/chai": "^5.0.1", - "assert": "^2.1.0", - "chai": "^5.2.0", - "prettier": "^3.3.3", - "ts-node": "^10.9.2", - "typescript": "^5.7.2", - "vite": "^5.4.8" - } - }, - ".papi/descriptors": { - "name": "@polkadot-api/descriptors", - "version": "0.1.0-autogenerated.7914363913476982777", - "extraneous": true, - "peerDependencies": { - "polkadot-api": "*" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "license": "MIT" - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@commander-js/extra-typings": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-13.1.0.tgz", - "integrity": "sha512-q5P52BYb1hwVWE6dtID7VvuJWrlfbCv4klj7BjUUOqMz4jbSZD4C9fJ9lRjL2jnBGTg+gDDlaXN51rkWcLk4fg==", - "license": "MIT", - "peerDependencies": { - "commander": "~13.1.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@polkadot-api/cli": { - "version": "0.11.9", - "resolved": "https://registry.npmjs.org/@polkadot-api/cli/-/cli-0.11.9.tgz", - "integrity": "sha512-5Qt+YRf/kOCZGiFoWzgyxoZYA9OpN28AFE4jQ4nZI33lty8oH4FR62IF2iLF+KdafhgF9k9l1Kj24zuBFH3Vrw==", - "license": "MIT", - "dependencies": { - "@commander-js/extra-typings": "^13.1.0", - "@polkadot-api/codegen": "0.13.3", - "@polkadot-api/ink-contracts": "0.2.6", - "@polkadot-api/json-rpc-provider": "0.0.4", - "@polkadot-api/known-chains": "0.7.3", - "@polkadot-api/metadata-compatibility": "0.2.0", - "@polkadot-api/observable-client": "0.8.6", - "@polkadot-api/polkadot-sdk-compat": "2.3.2", - "@polkadot-api/sm-provider": "0.1.7", - "@polkadot-api/smoldot": "0.3.8", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/substrate-client": "0.3.0", - "@polkadot-api/utils": "0.1.2", - "@polkadot-api/wasm-executor": "^0.1.2", - "@polkadot-api/ws-provider": "0.4.0", - "@types/node": "^22.14.0", - "commander": "^13.1.0", - "execa": "^9.5.2", - "fs.promises.exists": "^1.1.4", - "ora": "^8.2.0", - "read-pkg": "^9.0.1", - "rxjs": "^7.8.2", - "tsc-prog": "^2.3.0", - "tsup": "^8.4.0", - "typescript": "^5.8.3", - "write-package": "^7.1.0" - }, - "bin": { - "papi": "dist/main.js", - "polkadot-api": "dist/main.js" - } - }, - "node_modules/@polkadot-api/codegen": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/@polkadot-api/codegen/-/codegen-0.13.3.tgz", - "integrity": "sha512-+8mp9k5L9myFSLv6Ad5r63JSIeq80/tKbk67rczDq6Co0PlJHqxult+wZHohHuyJSdtu8dHW9JQktTtM2RZT1w==", - "license": "MIT", - "dependencies": { - "@polkadot-api/ink-contracts": "0.2.6", - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/metadata-compatibility": "0.2.0", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/ink-contracts": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@polkadot-api/ink-contracts/-/ink-contracts-0.2.6.tgz", - "integrity": "sha512-76oHO/rKRa48w1i4DEmB/9e/FmxKuhMJq7l1OhdnX6mbVO+bAif7FkRUHLfIgsWqCdhCdfLe5J474HRudKhU/A==", - "license": "MIT", - "dependencies": { - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/json-rpc-provider": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.4.tgz", - "integrity": "sha512-9cDijLIxzHOBuq6yHqpqjJ9jBmXrctjc1OFqU+tQrS96adQze3mTIH6DTgfb/0LMrqxzxffz1HQGrIlEH00WrA==", - "license": "MIT" - }, - "node_modules/@polkadot-api/json-rpc-provider-proxy": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.4.tgz", - "integrity": "sha512-nuGoY9QpBAiRU7xmXN3nugFvPcnSu3IxTLm1OWcNTGlZ1LW5bvdQHz3JLk56+Jlyb3GJ971hqdg2DJsMXkKCOg==", - "license": "MIT" - }, - "node_modules/@polkadot-api/known-chains": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@polkadot-api/known-chains/-/known-chains-0.7.3.tgz", - "integrity": "sha512-yBRVbOLn0e36+EGWE2/hX8mhTKvfdZtbk2VCgTM9djkz28eDFfiDjEl6biQA8Q0Kd7t3iRzoNbBzpzyBwTMXUg==", - "license": "MIT" - }, - "node_modules/@polkadot-api/logs-provider": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@polkadot-api/logs-provider/-/logs-provider-0.0.6.tgz", - "integrity": "sha512-4WgHlvy+xee1ADaaVf6+MlK/+jGMtsMgAzvbQOJZnP4PfQuagoTqaeayk8HYKxXGphogLlPbD06tANxcb+nvAg==", - "license": "MIT", - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.4" - } - }, - "node_modules/@polkadot-api/metadata-builders": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.10.2.tgz", - "integrity": "sha512-rtdihBFd25oT9/71Q+EOR9q6E6mCl1pPe/2He/LtlY0TyHiYqO2KpMZNXkoGcw1RHvrV+CAtDFMvK1j3n8aW8w==", - "license": "MIT", - "dependencies": { - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/metadata-compatibility": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-compatibility/-/metadata-compatibility-0.2.0.tgz", - "integrity": "sha512-ZvHj4KDQy/JFqV51UN6Gk5xnG0qt/BUS4kjYosLWT9y6p5bHg/4ge7QF5lMloInQqV3Rul9NQo4cKUz3SlSQMQ==", - "license": "MIT", - "dependencies": { - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/substrate-bindings": "0.11.1" - } - }, - "node_modules/@polkadot-api/observable-client": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.8.6.tgz", - "integrity": "sha512-ci5HC8TYjGxoTG/QM+LLuGrfIsn+dtR7BBQz483c/ML8K/Hxl9v+evgZzPi9xNMwZ25mytn9lhA5dovYSEauSA==", - "license": "MIT", - "dependencies": { - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - }, - "peerDependencies": { - "@polkadot-api/substrate-client": "0.3.0", - "rxjs": ">=7.8.0" - } - }, - "node_modules/@polkadot-api/pjs-signer": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@polkadot-api/pjs-signer/-/pjs-signer-0.6.5.tgz", - "integrity": "sha512-RQJtvuX8jNR77h9PFTNQPjC4ii0g0uGrfyu5cbTujojg2QboU/6ny26Ty45rzkSOL0GaBLsS7Uf+/7Vf9hCxig==", - "license": "MIT", - "dependencies": { - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/polkadot-signer": "0.1.6", - "@polkadot-api/signers-common": "0.1.6", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/polkadot-sdk-compat": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/polkadot-sdk-compat/-/polkadot-sdk-compat-2.3.2.tgz", - "integrity": "sha512-rLCveP3a6Xd0r218yRqVY34lJ8bXVmE12cArbU4JFp9p8e8Jbb6xdqOdu7bQtjlZUsahhcmfIHYQSXKziST7PA==", - "license": "MIT", - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.4" - } - }, - "node_modules/@polkadot-api/polkadot-signer": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@polkadot-api/polkadot-signer/-/polkadot-signer-0.1.6.tgz", - "integrity": "sha512-X7ghAa4r7doETtjAPTb50IpfGtrBmy3BJM5WCfNKa1saK04VFY9w+vDn+hwEcM4p0PcDHt66Ts74hzvHq54d9A==", - "license": "MIT" - }, - "node_modules/@polkadot-api/signer": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/@polkadot-api/signer/-/signer-0.1.15.tgz", - "integrity": "sha512-FUFlHrICB4dGlFa6FeFju/ySr8kTAkhTE/aSmfSxW0rl/cTeDO2fbUS9WmIl8wLB0jsI14I2r5J/p13FvIe1BA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.7.1", - "@polkadot-api/polkadot-signer": "0.1.6", - "@polkadot-api/signers-common": "0.1.6", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/signers-common": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@polkadot-api/signers-common/-/signers-common-0.1.6.tgz", - "integrity": "sha512-OEzqpu/AlZIHbvpvwQJ7dhoRIRTXI2D7wYEoT5j0COpAvt3A1L53smECb3xWzkzlb82gINuqpUW5dfhhJ5tQFQ==", - "license": "MIT", - "dependencies": { - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/polkadot-signer": "0.1.6", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/sm-provider": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@polkadot-api/sm-provider/-/sm-provider-0.1.7.tgz", - "integrity": "sha512-BhNKVeIFZdawpPVadXszLl8IP4EDjcLHe/GchfRRFkvoNFuwS2nNv/npYIqCviXV+dd2R8VnEELxwScsf380Og==", - "license": "MIT", - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.4", - "@polkadot-api/json-rpc-provider-proxy": "0.2.4" - }, - "peerDependencies": { - "@polkadot-api/smoldot": ">=0.3" - } - }, - "node_modules/@polkadot-api/smoldot": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@polkadot-api/smoldot/-/smoldot-0.3.8.tgz", - "integrity": "sha512-dbJSMRFtELDW+rZIWRwKE/K8oy7+gYaGl+DvaOjARoBW2n80rJ7RAMOCCu+b5h2zgl3elftFBwMNAuAWgHT/Zg==", - "license": "MIT", - "dependencies": { - "@types/node": "^22.9.0", - "smoldot": "2.0.34" - } - }, - "node_modules/@polkadot-api/smoldot/node_modules/smoldot": { - "version": "2.0.34", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.34.tgz", - "integrity": "sha512-mw9tCbGEhEp0koMqLL0jBEixVY1MIN/xI3pE6ZY1TuOPU+LnYy8FloODVyzkvzQPaBYrETXJdRlmA/+k6g3gow==", - "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", - "dependencies": { - "ws": "^8.8.1" - } - }, - "node_modules/@polkadot-api/substrate-bindings": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.11.1.tgz", - "integrity": "sha512-+oqAZB7y18KrP/DqKmU2P3nNmRzjCY7edtW7tyA1g1jPouF7HhRr/Q13lJseDX9sdE2FZGrKZtivzsw8XeXBng==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.7.1", - "@polkadot-api/utils": "0.1.2", - "@scure/base": "^1.2.4", - "scale-ts": "^1.6.1" - } - }, - "node_modules/@polkadot-api/substrate-client": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.3.0.tgz", - "integrity": "sha512-0hEvQLKH2zhaFzE8DPkWehvJilec8u2O2wbIEUStm0OJ8jIFtJ40MFjXQfB01dXBWUz1KaVBqS6xd3sZA90Dpw==", - "license": "MIT", - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.4", - "@polkadot-api/utils": "0.1.2" - } - }, - "node_modules/@polkadot-api/utils": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.2.tgz", - "integrity": "sha512-yhs5k2a8N1SBJcz7EthZoazzLQUkZxbf+0271Xzu42C5AEM9K9uFLbsB+ojzHEM72O5X8lPtSwGKNmS7WQyDyg==", - "license": "MIT" - }, - "node_modules/@polkadot-api/wasm-executor": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/wasm-executor/-/wasm-executor-0.1.2.tgz", - "integrity": "sha512-a5wGenltB3EFPdf72u8ewi6HsUg2qubUAf3ekJprZf24lTK3+w8a/GUF/y6r08LJF35MALZ32SAtLqtVTIOGnQ==", - "license": "MIT" - }, - "node_modules/@polkadot-api/ws-provider": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/ws-provider/-/ws-provider-0.4.0.tgz", - "integrity": "sha512-ZurjUHHAlQ1Ux8HiZz7mtkg1qjq6LmqxcHljcZxne0U7foCZrXdWHsohwlV8kUQUir5kXuDsNvdZN/MFCUMaVw==", - "license": "MIT", - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.4", - "@polkadot-api/json-rpc-provider-proxy": "0.2.4", - "ws": "^8.18.1" - } - }, - "node_modules/@polkadot-labs/hdkd": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@polkadot-labs/hdkd/-/hdkd-0.0.10.tgz", - "integrity": "sha512-jD8l+Ls/kZjvZja4T2Y0G6Be3rfGn0qNs3hvcNeV2CmOMtI7yRkkWPXI7WiJ8AyEoBwBuZt0rm6yzGla6o2HXQ==", - "license": "MIT", - "dependencies": { - "@polkadot-labs/hdkd-helpers": "0.0.10" - } - }, - "node_modules/@polkadot-labs/hdkd-helpers": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.11.tgz", - "integrity": "sha512-qPlWqC3NNV/2NYc5GEy+Ovi4UBAgkMGvMfyiYuj2BQN4lW59Q1T9coNx0Yp6XzsnJ1ddaF9PWaUtxj3LdM0IDw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "^1.8.1", - "@noble/hashes": "^1.7.1", - "@scure/base": "^1.2.4", - "micro-sr25519": "^0.1.0", - "scale-ts": "^1.6.1" - } - }, - "node_modules/@polkadot-labs/hdkd/node_modules/@polkadot-labs/hdkd-helpers": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.10.tgz", - "integrity": "sha512-wBKenhN7TjNiMXxBvQWzFf+su8xTaRGqyOKAlAfpyY9oWTOt3G05yMvDHEZ4g/NRLoE4P3fQYQ0bdcMKl7KkDw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "^1.7.0", - "@noble/hashes": "^1.6.1", - "@scure/base": "^1.2.1", - "micro-sr25519": "^0.1.0", - "scale-ts": "^1.6.1" - } - }, - "node_modules/@polkadot/api": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-15.1.1.tgz", - "integrity": "sha512-n3QeQ1CXlzjqyh2eFbEQPcnkXO3J4QYNTIj0Lnz/XFUpzKimHPDA2iUfaXuy5dXjnzS21jFANGSUFoZ+XKi/8g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/api-augment": "15.1.1", - "@polkadot/api-base": "15.1.1", - "@polkadot/api-derive": "15.1.1", - "@polkadot/keyring": "^13.2.3", - "@polkadot/rpc-augment": "15.1.1", - "@polkadot/rpc-core": "15.1.1", - "@polkadot/rpc-provider": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/types-augment": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/types-create": "15.1.1", - "@polkadot/types-known": "15.1.1", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "eventemitter3": "^5.0.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/api-augment": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-15.1.1.tgz", - "integrity": "sha512-tYASON7vVLz7FGcXVX9dWSd/9pR6FckayEkc08Z6RyjH7HfjtCZ3/Dz7MlGRNql4SnPi4+xpjSD6rwrZcETU1g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/api-base": "15.1.1", - "@polkadot/rpc-augment": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/types-augment": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/api-base": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-15.1.1.tgz", - "integrity": "sha512-OXLZ7/k2RXLIA8hKA8oyii6o8MuGlqujIDcLVaMdtWnQsBg26h8pv/mujT2YSz2OguLxrfdvD+lUGtwZC8kw4A==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/rpc-core": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/util": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/api-derive": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-15.1.1.tgz", - "integrity": "sha512-UPcKr9FplfYKPaP7FYEF917Sm1rKnQFX4AzQJn3f8ySp7DDf6EYiHrNICtGifPEAoANTSW+YHlSchhtnvfSIhw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/api": "15.1.1", - "@polkadot/api-augment": "15.1.1", - "@polkadot/api-base": "15.1.1", - "@polkadot/rpc-core": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/keyring": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.4.3.tgz", - "integrity": "sha512-2ePNcvBTznDN2luKbZM5fdxgAnj7V8m276qSTgrHlqKVvg9FsQpRCR6CAU+AjhnHzpe7uiZO+UH+jlXWefI3AA==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/util": "13.4.3", - "@polkadot/util-crypto": "13.4.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "13.4.3", - "@polkadot/util-crypto": "13.4.3" - } - }, - "node_modules/@polkadot/networks": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.4.3.tgz", - "integrity": "sha512-Z+YZkltBt//CtkVH8ZYJ1z66qYxdI0yPamzkzZAqw6gj3gjgSxKtxB4baA/rcAw05QTvN2R3dLkkmKr2mnHovQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/util": "13.4.3", - "@substrate/ss58-registry": "^1.51.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/rpc-augment": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-15.1.1.tgz", - "integrity": "sha512-s6i4nTy7/1Q5svIMT4TR55GLRv9asG7xbJcntHEsQ2nDs8zZV/mvPWfEUxgup0xVO8sDgyrf6KTTVRKJjySjUg==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/rpc-core": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/rpc-core": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-15.1.1.tgz", - "integrity": "sha512-KErbVgPChps7NsxcGch5JCArZHNqs81fDEzs+XoHnD05nzuxcO38v4Yu+M04lHLax2m8ky8K6o3gurBglJENlA==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/rpc-augment": "15.1.1", - "@polkadot/rpc-provider": "15.1.1", - "@polkadot/types": "15.1.1", - "@polkadot/util": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/rpc-provider": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-15.1.1.tgz", - "integrity": "sha512-9OWV1dyX+vmAbKkhMU8J7Q0sCaovPrkwZqo2ejmEpZ/Lr12Hw5JAk4gdvB869QEVP7zj0gH3HuYVajmsxesYKg==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types": "15.1.1", - "@polkadot/types-support": "15.1.1", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "@polkadot/x-fetch": "^13.2.3", - "@polkadot/x-global": "^13.2.3", - "@polkadot/x-ws": "^13.2.3", - "eventemitter3": "^5.0.1", - "mock-socket": "^9.3.1", - "nock": "^13.5.5", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@substrate/connect": "0.8.11" - } - }, - "node_modules/@polkadot/types": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-15.1.1.tgz", - "integrity": "sha512-n6lg/quhLp3Zmt/6gHAg2uoSmMmXk3NR19I7qCyeDJ30pP1UhOjtmuWOQDl6SwSEwuHtudLp3p2nCJsymXjgsw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types-augment": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/types-create": "15.1.1", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types-augment": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-15.1.1.tgz", - "integrity": "sha512-6v/FsN/JYCupyGYW+MbS0iOCiWvf6PXJ5+m8ORYYYDPFgQqaQPxKMKWJpnO0s9cCR33QcyNYhErPGuZ62UMJjw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/types": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types-codec": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-15.1.1.tgz", - "integrity": "sha512-cm99CFvDf4UXmw7DeMkRqa/hf7wEgjJZoZZW/B12Js0ObwRmSXMk/gDbyiT6hqPnQ81sU726E72p39DolaEatQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/util": "^13.2.3", - "@polkadot/x-bigint": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types-create": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-15.1.1.tgz", - "integrity": "sha512-AOgz+UsUqsGSENrc+p/dHyXH2TC9qVtUTAxlqaHfOnwqjMWfEqc78mc5a1mk0a+RqxmIHw8nQNSdBdhv+UdtyQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/types-codec": "15.1.1", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types-known": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-15.1.1.tgz", - "integrity": "sha512-L934pYxXdHB3GHlVu57ihO6llhxuggSuQZuJ9kHunG0I6tezXLIgAhwaPgACMVbmBYlkJPqm4Nr6pC3kpIsGow==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/networks": "^13.2.3", - "@polkadot/types": "15.1.1", - "@polkadot/types-codec": "15.1.1", - "@polkadot/types-create": "15.1.1", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/types-support": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-15.1.1.tgz", - "integrity": "sha512-uyn5N7XERHosVq0+aCpEwYnkUroOr7OX8B8/00UkgmfVOXskp/cukEVcGlmI/YGAS+9+V2BZN2GBX7Lz0eeKmw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/util": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.4.3.tgz", - "integrity": "sha512-6v2zvg8l7W22XvjYf7qv9tPQdYl2E6aXY94M4TZKsXZxmlS5BoG+A9Aq0+Gw8zBUjupjEmUkA6Y//msO8Zisug==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-bigint": "13.4.3", - "@polkadot/x-global": "13.4.3", - "@polkadot/x-textdecoder": "13.4.3", - "@polkadot/x-textencoder": "13.4.3", - "@types/bn.js": "^5.1.6", - "bn.js": "^5.2.1", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/util-crypto": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.4.3.tgz", - "integrity": "sha512-Ml0mjhKVetMrRCIosmVNMa6lbFPa3fSAeOggf34NsDIIQOKt9FL644iGz1ZSMOnBwN9qk2qHYmcFMTDXX2yKVQ==", - "license": "Apache-2.0", - "dependencies": { - "@noble/curves": "^1.3.0", - "@noble/hashes": "^1.3.3", - "@polkadot/networks": "13.4.3", - "@polkadot/util": "13.4.3", - "@polkadot/wasm-crypto": "^7.4.1", - "@polkadot/wasm-util": "^7.4.1", - "@polkadot/x-bigint": "13.4.3", - "@polkadot/x-randomvalues": "13.4.3", - "@scure/base": "^1.1.7", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "13.4.3" - } - }, - "node_modules/@polkadot/wasm-bridge": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", - "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.4.1.tgz", - "integrity": "sha512-kHN/kF7hYxm1y0WeFLWeWir6oTzvcFmR4N8fJJokR+ajYbdmrafPN+6iLgQVbhZnDdxyv9jWDuRRsDnBx8tPMQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-init": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-asmjs": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.4.1.tgz", - "integrity": "sha512-pwU8QXhUW7IberyHJIQr37IhbB6DPkCG5FhozCiNTq4vFBsFPjm9q8aZh7oX1QHQaiAZa2m2/VjIVE+FHGbvHQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-init": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.4.1.tgz", - "integrity": "sha512-AVka33+f7MvXEEIGq5U0dhaA2SaXMXnxVCQyhJTaCnJ5bRDj0Xlm3ijwDEQUiaDql7EikbkkRtmlvs95eSUWYQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-wasm": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.4.1.tgz", - "integrity": "sha512-PE1OAoupFR0ZOV2O8tr7D1FEUAwaggzxtfs3Aa5gr+yxlSOaWUKeqsOYe1KdrcjmZVV3iINEAXxgrbzCmiuONg==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-util": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.4.1.tgz", - "integrity": "sha512-RAcxNFf3zzpkr+LX/ItAsvj+QyM56TomJ0xjUMo4wKkHjwsxkz4dWJtx5knIgQz/OthqSDMR59VNEycQeNuXzA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/x-bigint": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.4.3.tgz", - "integrity": "sha512-8NbjF5Q+5lflhvDFve58wULjCVcvXa932LKFtI5zL2gx5VDhMgyfkNcYRjHB18Ecl21963JuGzvGVTZNkh/i6g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-fetch": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.4.3.tgz", - "integrity": "sha512-EwhcwROqWa7mvNTbLVNH71Hbyp5PW5j9lV2UpII5MZzRO95eYwV4oP/xgtTxC+60nC8lrvzAw0JxEHrmNzmtlg==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "node-fetch": "^3.3.2", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-global": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.4.3.tgz", - "integrity": "sha512-6c98kxZdoGRct3ua9Dz6/qz8wb3XFRUkaY+4+RzIgehKMPhu19pGWTrzmbJSyY9FtIpThuWKuDaBEvd5KgSxjA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-randomvalues": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.4.3.tgz", - "integrity": "sha512-pskXP/S2jROZ6aASExsUFlNp7GbJvQikKogvyvMMCzNIbUYLxpLuquLRa3MOORx2c0SNsENg90cx/zHT+IjPRQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "13.4.3", - "@polkadot/wasm-util": "*" - } - }, - "node_modules/@polkadot/x-textdecoder": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.4.3.tgz", - "integrity": "sha512-k7Wg6csAPxfNtpBt3k5yUuPHYmRl/nl7H2OMr40upMjbZXbQ1RJW9Z3GBkLmQczG7NwwfAXHwQE9FYOMUtbuRQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-textencoder": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.4.3.tgz", - "integrity": "sha512-byl2LbN1rnEXKmnsCzEDaIjSIHAr+1ciSe2yj3M0K+oWEEcaFZEovJaf/uoyzkcjn+/l8rDv3nget6mPuQ/DSw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-ws": { - "version": "13.4.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.4.3.tgz", - "integrity": "sha512-GS0I6MYLD/xNAAjODZi/pbG7Ba0e/5sbvDIrT01iKH3SPGN+PZoyAsc04t2IOXA6QmPa1OBHnaU3N4K8gGmJ+w==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.4.3", - "tslib": "^2.8.0", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", - "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", - "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rx-state/core": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz", - "integrity": "sha512-Z+3hjU2xh1HisLxt+W5hlYX/eGSDaXXP+ns82gq/PLZpkXLu0uwcNUh9RLY3Clq4zT+hSsA3vcpIGt6+UAb8rQ==", - "license": "MIT", - "peerDependencies": { - "rxjs": ">=7" - } - }, - "node_modules/@scure/base": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.4.tgz", - "integrity": "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", - "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.8.1", - "@noble/hashes": "~1.7.1", - "@scure/base": "~1.2.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", - "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.7.1", - "@scure/base": "~1.2.4" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "license": "MIT" - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@substrate/connect": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.8.11.tgz", - "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", - "license": "GPL-3.0-only", - "optional": true, - "dependencies": { - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "@substrate/light-client-extension-helpers": "^1.0.0", - "smoldot": "2.0.26" - } - }, - "node_modules/@substrate/connect-extension-protocol": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz", - "integrity": "sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA==", - "license": "GPL-3.0-only", - "optional": true - }, - "node_modules/@substrate/connect-known-chains": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.9.2.tgz", - "integrity": "sha512-uEmm+rKJQQhhbforvmcg74TsDHKFVBkstjPwblGT1RdHMxUKR7Gq7F8vbkGnr5ce9tMK2Ylil760Z7vtX013hw==", - "license": "GPL-3.0-only", - "optional": true - }, - "node_modules/@substrate/light-client-extension-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz", - "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@polkadot-api/json-rpc-provider": "^0.0.1", - "@polkadot-api/json-rpc-provider-proxy": "^0.1.0", - "@polkadot-api/observable-client": "^0.3.0", - "@polkadot-api/substrate-client": "^0.1.2", - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "rxjs": "^7.8.1" - }, - "peerDependencies": { - "smoldot": "2.x" - } - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/json-rpc-provider": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz", - "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==", - "license": "MIT", - "optional": true - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/json-rpc-provider-proxy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz", - "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==", - "license": "MIT", - "optional": true - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/metadata-builders": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz", - "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" - } - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/observable-client": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz", - "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", - "license": "MIT", - "optional": true, - "dependencies": { - "@polkadot-api/metadata-builders": "0.3.2", - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" - }, - "peerDependencies": { - "@polkadot-api/substrate-client": "0.1.4", - "rxjs": ">=7.8.0" - } - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/substrate-bindings": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz", - "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "^1.3.1", - "@polkadot-api/utils": "0.1.0", - "@scure/base": "^1.1.1", - "scale-ts": "^1.6.0" - } - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/substrate-client": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", - "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", - "license": "MIT", - "optional": true, - "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.1", - "@polkadot-api/utils": "0.1.0" - } - }, - "node_modules/@substrate/light-client-extension-helpers/node_modules/@polkadot-api/utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", - "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==", - "license": "MIT", - "optional": true - }, - "node_modules/@substrate/ss58-registry": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz", - "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==", - "license": "Apache-2.0" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bun": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.2.3.tgz", - "integrity": "sha512-054h79ipETRfjtsCW9qJK8Ipof67Pw9bodFWmkfkaUaRiIQ1dIV2VTlheshlBx3mpKr0KeK8VqnMMCtgN9rQtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bun-types": "1.2.3" - } - }, - "node_modules/@types/chai": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz", - "integrity": "sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "license": "MIT" - }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", - "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/abitype": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", - "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "license": "MIT" - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/assert": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", - "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "is-nan": "^1.3.2", - "object-is": "^1.1.5", - "object.assign": "^4.1.4", - "util": "^0.12.5" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "license": "ISC" - }, - "node_modules/bun-types": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.2.3.tgz", - "integrity": "sha512-P7AeyTseLKAvgaZqQrvp3RqFM3yN9PlcLuSTe7SoJOfZkER73mLdT2vEQi8U64S1YvM/ldcNiQjn0Sn7H9lGgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/ws": "~8.5.10" - } - }, - "node_modules/bundle-require": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", - "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", - "license": "MIT", - "dependencies": { - "load-tsconfig": "^0.2.3" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "esbuild": ">=0.18" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", - "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", - "license": "ISC" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ethers": { - "version": "6.13.5", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", - "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "1.10.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "22.7.5", - "aes-js": "4.0.0-beta.5", - "tslib": "2.7.0", - "ws": "8.17.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/ethers/node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethers/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethers/node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/ethers/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "license": "0BSD" - }, - "node_modules/ethers/node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, - "node_modules/ethers/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fs.promises.exists": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fs.promises.exists/-/fs.promises.exists-1.1.4.tgz", - "integrity": "sha512-lJzUGWbZn8vhGWBedA+RYjB/BeJ+3458ljUfmplqhIeb6ewzTFWNPCR1HCiYCkXV9zxcHz9zXkJzMsEgDLzh3Q==", - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/fs.promises.exists?sponsor=1" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/index-to-position": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", - "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/isows": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", - "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, - "node_modules/load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/micro-sr25519": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/micro-sr25519/-/micro-sr25519-0.1.0.tgz", - "integrity": "sha512-at5zfxiKNhh07v4GPb8Sc6wCW+jd18FMMgPM0ACIQMcgvMfB9a34mfOlXr5B04J4yFZ6imlvJfRaFbOxMA7ytw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.7.0", - "@noble/hashes": "~1.6.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/micro-sr25519/node_modules/@noble/curves": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", - "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.6.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/micro-sr25519/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", - "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/micro-sr25519/node_modules/@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mock-socket": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", - "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "devOptional": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 10.13" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "license": "MIT" - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/ox": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", - "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "^1.10.1", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0", - "@scure/bip32": "^1.5.0", - "@scure/bip39": "^1.4.0", - "abitype": "^1.0.6", - "eventemitter3": "5.0.1" - }, - "peerDependencies": { - "typescript": ">=5.4.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/ox/node_modules/@adraffy/ens-normalize": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", - "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", - "license": "MIT" - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, - "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/polkadot-api": { - "version": "1.9.12", - "resolved": "https://registry.npmjs.org/polkadot-api/-/polkadot-api-1.9.12.tgz", - "integrity": "sha512-gYhpef5YnLEPZ3Uxeha5sHIIejINONSGBXTgFyEWsYi4y2DEUlv2ISlNZ9/0AGG6b6ZFDd56mLop/Fohl8vA4Q==", - "license": "MIT", - "dependencies": { - "@polkadot-api/cli": "0.11.9", - "@polkadot-api/ink-contracts": "0.2.6", - "@polkadot-api/json-rpc-provider": "0.0.4", - "@polkadot-api/known-chains": "0.7.3", - "@polkadot-api/logs-provider": "0.0.6", - "@polkadot-api/metadata-builders": "0.10.2", - "@polkadot-api/metadata-compatibility": "0.2.0", - "@polkadot-api/observable-client": "0.8.6", - "@polkadot-api/pjs-signer": "0.6.5", - "@polkadot-api/polkadot-sdk-compat": "2.3.2", - "@polkadot-api/polkadot-signer": "0.1.6", - "@polkadot-api/signer": "0.1.15", - "@polkadot-api/sm-provider": "0.1.7", - "@polkadot-api/smoldot": "0.3.8", - "@polkadot-api/substrate-bindings": "0.11.1", - "@polkadot-api/substrate-client": "0.3.0", - "@polkadot-api/utils": "0.1.2", - "@polkadot-api/ws-provider": "0.4.0", - "@rx-state/core": "^0.1.4" - }, - "bin": { - "papi": "bin/cli.mjs", - "polkadot-api": "bin/cli.mjs" - }, - "peerDependencies": { - "rxjs": ">=7.8.0" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "devOptional": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-ms": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rollup": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", - "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.8", - "@rollup/rollup-android-arm64": "4.34.8", - "@rollup/rollup-darwin-arm64": "4.34.8", - "@rollup/rollup-darwin-x64": "4.34.8", - "@rollup/rollup-freebsd-arm64": "4.34.8", - "@rollup/rollup-freebsd-x64": "4.34.8", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", - "@rollup/rollup-linux-arm-musleabihf": "4.34.8", - "@rollup/rollup-linux-arm64-gnu": "4.34.8", - "@rollup/rollup-linux-arm64-musl": "4.34.8", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", - "@rollup/rollup-linux-riscv64-gnu": "4.34.8", - "@rollup/rollup-linux-s390x-gnu": "4.34.8", - "@rollup/rollup-linux-x64-gnu": "4.34.8", - "@rollup/rollup-linux-x64-musl": "4.34.8", - "@rollup/rollup-win32-arm64-msvc": "4.34.8", - "@rollup/rollup-win32-ia32-msvc": "4.34.8", - "@rollup/rollup-win32-x64-msvc": "4.34.8", - "fsevents": "~2.3.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scale-ts": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz", - "integrity": "sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/smoldot": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", - "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", - "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", - "optional": true, - "dependencies": { - "ws": "^8.8.1" - } - }, - "node_modules/sort-keys": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", - "integrity": "sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==", - "license": "MIT", - "dependencies": { - "is-plain-obj": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "license": "BSD-3-Clause", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "license": "CC0-1.0" - }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", - "license": "MIT", - "dependencies": { - "fdir": "^6.4.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "license": "MIT", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "license": "Apache-2.0" - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tsc-prog": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tsc-prog/-/tsc-prog-2.3.0.tgz", - "integrity": "sha512-ycET2d75EgcX7y8EmG4KiZkLAwUzbY4xRhA6NU0uVbHkY4ZjrAAuzTMxXI85kOwATqPnBI5C/7y7rlpY0xdqHA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "typescript": ">=4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsup": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.4.0.tgz", - "integrity": "sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==", - "license": "MIT", - "dependencies": { - "bundle-require": "^5.1.0", - "cac": "^6.7.14", - "chokidar": "^4.0.3", - "consola": "^3.4.0", - "debug": "^4.4.0", - "esbuild": "^0.25.0", - "joycon": "^3.1.1", - "picocolors": "^1.1.1", - "postcss-load-config": "^6.0.1", - "resolve-from": "^5.0.0", - "rollup": "^4.34.8", - "source-map": "0.8.0-beta.0", - "sucrase": "^3.35.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.11", - "tree-kill": "^1.2.2" - }, - "bin": { - "tsup": "dist/cli-default.js", - "tsup-node": "dist/cli-node.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@microsoft/api-extractor": "^7.36.0", - "@swc/core": "^1", - "postcss": "^8.4.12", - "typescript": ">=4.5.0" - }, - "peerDependenciesMeta": { - "@microsoft/api-extractor": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "postcss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/tsup/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/tsup/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/type-fest": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", - "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/viem": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.4.tgz", - "integrity": "sha512-UQquuolKlS1w5H5e0Fd1KKoUlIPJryIEBzY5AUhGyV1ka+9O6+3uYVhUzj6RbvGK0PtsMKn2ddwPZFwjNDVU/A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@noble/curves": "1.8.1", - "@noble/hashes": "1.7.1", - "@scure/bip32": "1.6.2", - "@scure/bip39": "1.5.4", - "abitype": "1.0.8", - "isows": "1.0.6", - "ox": "0.6.7", - "ws": "8.18.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/viem/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/vite": { - "version": "5.4.14", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", - "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "license": "MIT", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/write-json-file": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-6.0.0.tgz", - "integrity": "sha512-MNHcU3f9WxnNyR6MxsYSj64Jz0+dwIpisWKWq9gqLj/GwmA9INg3BZ3vt70/HB3GEwrnDQWr4RPrywnhNzmUFA==", - "license": "MIT", - "dependencies": { - "detect-indent": "^7.0.1", - "is-plain-obj": "^4.1.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^5.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/write-package": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/write-package/-/write-package-7.1.0.tgz", - "integrity": "sha512-DqUx8GI3r9BFWwU2DPKddL1E7xWfbFED82mLVhGXKlFEPe8IkBftzO7WfNwHtk7oGDHDeuH/o8VMpzzfMwmLUA==", - "license": "MIT", - "dependencies": { - "deepmerge-ts": "^7.1.0", - "read-pkg": "^9.0.1", - "sort-keys": "^5.0.0", - "type-fest": "^4.23.0", - "write-json-file": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/evm-tests/package.json b/evm-tests/package.json index 0e90cdb976..9970967a88 100644 --- a/evm-tests/package.json +++ b/evm-tests/package.json @@ -6,6 +6,7 @@ "author": "", "license": "ISC", "dependencies": { + "@polkadot-api/descriptors": "file:.papi/descriptors", "@polkadot-labs/hdkd": "^0.0.10", "@polkadot-labs/hdkd-helpers": "^0.0.11", "@polkadot/api": "15.1.1", @@ -16,7 +17,8 @@ "mocha": "^11.1.0", "polkadot-api": "^1.9.5", "scale-ts": "^1.6.1", - "viem": "2.23.4" + "viem": "2.23.4", + "ws": "^8.18.2" }, "devDependencies": { "@types/bun": "^1.1.13", diff --git a/evm-tests/run-ci.sh b/evm-tests/run-ci.sh index cd7acb14af..7ad4bb2186 100755 --- a/evm-tests/run-ci.sh +++ b/evm-tests/run-ci.sh @@ -19,14 +19,24 @@ if [ "$i" -eq 1000 ]; then exit 1 fi +sleep 5 + +if ! nc -z localhost 9944; then + echo "node subtensor exit, port not available" + exit 1 +fi + cd evm-tests -yarn +# required for papi in get-metadata.sh, but we cannot run yarn before papi as it adds the descriptors to the package.json which won't resolve +npm i -g polkadot-api bash get-metadata.sh sleep 5 +yarn + yarn run test TEST_EXIT_CODE=$? diff --git a/evm-tests/src/config.ts b/evm-tests/src/config.ts index 00b942f802..1d12e3d584 100644 --- a/evm-tests/src/config.ts +++ b/evm-tests/src/config.ts @@ -20,6 +20,22 @@ export const IEd25519VerifyABI = [ }, ]; +export const ISr25519VERIFY_ADDRESS = "0x0000000000000000000000000000000000000403"; +export const ISr25519VerifyABI = [ + { + inputs: [ + { internalType: "bytes32", name: "message", type: "bytes32" }, + { internalType: "bytes32", name: "publicKey", type: "bytes32" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "verify", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "pure", + type: "function", + }, +]; + export const IBALANCETRANSFER_ADDRESS = "0x0000000000000000000000000000000000000800"; export const IBalanceTransferABI = [ { @@ -35,4 +51,8 @@ export const IBalanceTransferABI = [ stateMutability: "payable", type: "function", }, -]; \ No newline at end of file +]; + +export const IDISPATCH_ADDRESS = "0x0000000000000000000000000000000000000006"; + +export const ISTORAGE_QUERY_ADDRESS = "0x0000000000000000000000000000000000000807"; \ No newline at end of file diff --git a/evm-tests/src/contracts/alpha.ts b/evm-tests/src/contracts/alpha.ts new file mode 100644 index 0000000000..35baf83129 --- /dev/null +++ b/evm-tests/src/contracts/alpha.ts @@ -0,0 +1,249 @@ +export const IALPHA_ADDRESS = "0x0000000000000000000000000000000000000808"; + +export const IAlphaABI = [ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMovingAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getTaoInPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaInPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaOutPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaIssuance", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTaoWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "tao", + "type": "uint64" + } + ], + "name": "simSwapTaoForAlpha", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" + } + ], + "name": "simSwapAlphaForTao", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetMechanism", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRootNetuid", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getEMAPriceHalvingBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetVolume", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/evm-tests/src/contracts/subnet.ts b/evm-tests/src/contracts/subnet.ts index eacdaf3aca..b5a5a9dcbc 100644 --- a/evm-tests/src/contracts/subnet.ts +++ b/evm-tests/src/contracts/subnet.ts @@ -923,4 +923,57 @@ export const ISubnetABI = [ stateMutability: "payable", type: "function" }, + { + inputs: [ + { + internalType: "bytes32", + name: "hotkey", + type: "bytes32" + }, + { + internalType: "string", + name: "subnetName", + type: "string" + }, + { + internalType: "string", + name: "githubRepo", + type: "string" + }, + { + internalType: "string", + name: "subnetContact", + type: "string" + }, + { + internalType: "string", + name: "subnetUrl", + type: "string" + }, + { + internalType: "string", + name: "discord", + type: "string" + }, + { + internalType: "string", + name: "description", + type: "string" + }, + { + internalType: "string", + name: "logoUrl", + type: "string" + }, + { + internalType: "string", + name: "additional", + type: "string" + } + ], + name: "registerNetwork", + outputs: [], + stateMutability: "payable", + type: "function" + }, ]; diff --git a/evm-tests/src/subtensor.ts b/evm-tests/src/subtensor.ts index 3111d90544..e3d5526268 100644 --- a/evm-tests/src/subtensor.ts +++ b/evm-tests/src/subtensor.ts @@ -343,4 +343,12 @@ export async function startCall(api: TypedApi, netuid: number, ke const callStarted = await api.query.SubtensorModule.FirstEmissionBlockNumber .getValue(netuid); assert.notEqual(callStarted, undefined); +} + +export async function setMaxChildkeyTake(api: TypedApi, take: number) { + const alice = getAliceSigner() + const internalCall = api.tx.SubtensorModule.sudo_set_max_childkey_take({ take }) + const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) + + await waitForTransactionWithRetry(api, tx, alice) } \ No newline at end of file diff --git a/evm-tests/test/alpha.precompile.test.ts b/evm-tests/test/alpha.precompile.test.ts new file mode 100644 index 0000000000..85161aae92 --- /dev/null +++ b/evm-tests/test/alpha.precompile.test.ts @@ -0,0 +1,428 @@ +import * as assert from "assert"; + +import { getAliceSigner, getDevnetApi, waitForTransactionCompletion, convertPublicKeyToMultiAddress, getRandomSubstrateKeypair, getSignerFromKeypair } from "../src/substrate" +import { getPublicClient } from "../src/utils"; +import { ETH_LOCAL_URL, SUB_LOCAL_URL } from "../src/config"; +import { devnet } from "@polkadot-api/descriptors" +import { PublicClient } from "viem"; +import { PolkadotSigner, TypedApi } from "polkadot-api"; +import { toViemAddress, convertPublicKeyToSs58 } from "../src/address-utils" +import { IAlphaABI, IALPHA_ADDRESS } from "../src/contracts/alpha" + +describe("Test Alpha Precompile", () => { + // init substrate part + const hotkey = getRandomSubstrateKeypair(); + const coldkey = getRandomSubstrateKeypair(); + let publicClient: PublicClient; + + let api: TypedApi; + + // sudo account alice as signer + let alice: PolkadotSigner; + + // init other variable + let subnetId = 0; + + before(async () => { + // init variables got from await and async + publicClient = await getPublicClient(ETH_LOCAL_URL) + api = await getDevnetApi() + alice = await getAliceSigner(); + + // Fund the hotkey account + { + const multiAddress = convertPublicKeyToMultiAddress(hotkey.publicKey) + const internalCall = api.tx.Balances.force_set_balance({ who: multiAddress, new_free: BigInt(1e12) }) + const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) + + await waitForTransactionCompletion(api, tx, alice) + .then(() => { }) + .catch((error) => { console.log(`transaction error ${error}`) }); + } + + // Fund the coldkey account + { + const multiAddress = convertPublicKeyToMultiAddress(coldkey.publicKey) + const internalCall = api.tx.Balances.force_set_balance({ who: multiAddress, new_free: BigInt(1e12) }) + const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) + + await waitForTransactionCompletion(api, tx, alice) + .then(() => { }) + .catch((error) => { console.log(`transaction error ${error}`) }); + } + + // Register a new subnet + const signer = getSignerFromKeypair(coldkey) + const registerNetworkTx = api.tx.SubtensorModule.register_network({ hotkey: convertPublicKeyToSs58(hotkey.publicKey) }) + await waitForTransactionCompletion(api, registerNetworkTx, signer) + .then(() => { }) + .catch((error) => { console.log(`transaction error ${error}`) }); + + // Get the newly created subnet ID + let totalNetworks = await api.query.SubtensorModule.TotalNetworks.getValue() + assert.ok(totalNetworks > 1) + subnetId = totalNetworks - 1 + + // Register a neuron on the subnet if needed + let uid_count = await api.query.SubtensorModule.SubnetworkN.getValue(subnetId) + if (uid_count === 0) { + const tx = api.tx.SubtensorModule.burned_register({ hotkey: convertPublicKeyToSs58(hotkey.publicKey), netuid: subnetId }) + await waitForTransactionCompletion(api, tx, signer) + .then(() => { }) + .catch((error) => { console.log(`transaction error ${error}`) }); + } + }) + + describe("Alpha Price Functions", () => { + it("getAlphaPrice returns valid price for subnet", async () => { + const alphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaPrice", + args: [subnetId] + }) + + assert.ok(alphaPrice !== undefined, "Alpha price should be defined"); + assert.ok(typeof alphaPrice === 'bigint', "Alpha price should be a bigint"); + assert.ok(alphaPrice >= BigInt(0), "Alpha price should be non-negative"); + }); + + it("getMovingAlphaPrice returns valid moving price for subnet", async () => { + const movingAlphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getMovingAlphaPrice", + args: [subnetId] + }) + + assert.ok(movingAlphaPrice !== undefined, "Moving alpha price should be defined"); + assert.ok(typeof movingAlphaPrice === 'bigint', "Moving alpha price should be a bigint"); + assert.ok(movingAlphaPrice >= BigInt(0), "Moving alpha price should be non-negative"); + }); + + it("alpha prices are consistent for same subnet", async () => { + const alphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaPrice", + args: [subnetId] + }) + + const movingAlphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getMovingAlphaPrice", + args: [subnetId] + }) + + // Both should be defined and valid + assert.ok(alphaPrice !== undefined && movingAlphaPrice !== undefined); + }); + }); + + describe("Pool Data Functions", () => { + it("getTaoInPool returns valid TAO amount", async () => { + const taoInPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getTaoInPool", + args: [subnetId] + }) + + assert.ok(taoInPool !== undefined, "TAO in pool should be defined"); + assert.ok(typeof taoInPool === 'bigint', "TAO in pool should be a bigint"); + assert.ok(taoInPool >= BigInt(0), "TAO in pool should be non-negative"); + }); + + it("getAlphaInPool returns valid Alpha amount", async () => { + const alphaInPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaInPool", + args: [subnetId] + }) + + assert.ok(alphaInPool !== undefined, "Alpha in pool should be defined"); + assert.ok(typeof alphaInPool === 'bigint', "Alpha in pool should be a bigint"); + assert.ok(alphaInPool >= BigInt(0), "Alpha in pool should be non-negative"); + }); + + it("getAlphaOutPool returns valid Alpha out amount", async () => { + const alphaOutPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaOutPool", + args: [subnetId] + }) + + assert.ok(alphaOutPool !== undefined, "Alpha out pool should be defined"); + assert.ok(typeof alphaOutPool === 'bigint', "Alpha out pool should be a bigint"); + assert.ok(alphaOutPool >= BigInt(0), "Alpha out pool should be non-negative"); + }); + + it("getAlphaIssuance returns valid issuance amount", async () => { + const alphaIssuance = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaIssuance", + args: [subnetId] + }) + + assert.ok(alphaIssuance !== undefined, "Alpha issuance should be defined"); + assert.ok(typeof alphaIssuance === 'bigint', "Alpha issuance should be a bigint"); + assert.ok(alphaIssuance >= BigInt(0), "Alpha issuance should be non-negative"); + }); + }); + + describe("Global Functions", () => { + it("getTaoWeight returns valid TAO weight", async () => { + const taoWeight = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getTaoWeight", + args: [] + }) + + assert.ok(taoWeight !== undefined, "TAO weight should be defined"); + assert.ok(typeof taoWeight === 'bigint', "TAO weight should be a bigint"); + assert.ok(taoWeight >= BigInt(0), "TAO weight should be non-negative"); + }); + + it("getRootNetuid returns correct root netuid", async () => { + const rootNetuid = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getRootNetuid", + args: [] + }) + + assert.ok(rootNetuid !== undefined, "Root netuid should be defined"); + assert.ok(typeof rootNetuid === 'number', "Root netuid should be a number"); + assert.strictEqual(rootNetuid, 0, "Root netuid should be 0"); + }); + }); + + describe("Swap Simulation Functions", () => { + it("simSwapTaoForAlpha returns valid simulation", async () => { + const taoAmount = BigInt(1000000000); // 1 TAO in RAO + const simulatedAlpha = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapTaoForAlpha", + args: [subnetId, taoAmount] + }) + + assert.ok(simulatedAlpha !== undefined, "Simulated alpha should be defined"); + assert.ok(typeof simulatedAlpha === 'bigint', "Simulated alpha should be a bigint"); + assert.ok(simulatedAlpha >= BigInt(0), "Simulated alpha should be non-negative"); + }); + + it("simSwapAlphaForTao returns valid simulation", async () => { + const alphaAmount = BigInt(1000000000); // 1 Alpha + const simulatedTao = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapAlphaForTao", + args: [subnetId, alphaAmount] + }) + + assert.ok(simulatedTao !== undefined, "Simulated tao should be defined"); + assert.ok(typeof simulatedTao === 'bigint', "Simulated tao should be a bigint"); + assert.ok(simulatedTao >= BigInt(0), "Simulated tao should be non-negative"); + }); + + it("swap simulations handle zero amounts", async () => { + const zeroTaoForAlpha = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapTaoForAlpha", + args: [subnetId, BigInt(0)] + }) + + const zeroAlphaForTao = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapAlphaForTao", + args: [subnetId, BigInt(0)] + }) + + assert.strictEqual(zeroTaoForAlpha, BigInt(0), "Zero TAO should result in zero Alpha"); + assert.strictEqual(zeroAlphaForTao, BigInt(0), "Zero Alpha should result in zero TAO"); + }); + + it("swap simulations are internally consistent", async () => { + const taoAmount = BigInt(1000000000); // 1 TAO + + // Simulate TAO -> Alpha + const simulatedAlpha = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapTaoForAlpha", + args: [subnetId, taoAmount] + }) + + // If we got alpha, simulate Alpha -> TAO + if ((simulatedAlpha as bigint) > BigInt(0)) { + const simulatedTao = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapAlphaForTao", + args: [subnetId, simulatedAlpha] + }) + + // Check if simulated values are reasonably close (allowing for rounding/fees) + if ((simulatedTao as bigint) > BigInt(0)) { + const ratio = Number(taoAmount) / Number(simulatedTao); + assert.ok(ratio >= 0.5 && ratio <= 2.0, "Swap simulation should be within reasonable bounds"); + } + } + }); + }); + + describe("Subnet Configuration Functions", () => { + it("getSubnetMechanism returns valid mechanism", async () => { + const mechanism = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getSubnetMechanism", + args: [subnetId] + }) + + assert.ok(mechanism !== undefined, "Subnet mechanism should be defined"); + assert.ok(typeof mechanism === 'number', "Subnet mechanism should be a number"); + assert.ok(mechanism >= 0, "Subnet mechanism should be non-negative"); + }); + + it("getEMAPriceHalvingBlocks returns valid halving period", async () => { + const halvingBlocks = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getEMAPriceHalvingBlocks", + args: [subnetId] + }) + + assert.ok(halvingBlocks !== undefined, "EMA price halving blocks should be defined"); + assert.ok(typeof halvingBlocks === 'bigint', "EMA halving blocks should be a bigint"); + assert.ok(halvingBlocks >= BigInt(0), "EMA halving blocks should be non-negative"); + }); + + it("getSubnetVolume returns valid volume data", async () => { + const subnetVolume = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getSubnetVolume", + args: [subnetId] + }) + + assert.ok(subnetVolume !== undefined, "Subnet volume should be defined"); + assert.ok(typeof subnetVolume === 'bigint', "Subnet volume should be a bigint"); + assert.ok(subnetVolume >= BigInt(0), "Subnet volume should be non-negative"); + }); + }); + + describe("Data Consistency with Pallet", () => { + it("precompile data matches pallet values", async () => { + // Get TAO in pool from precompile + const taoInPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getTaoInPool", + args: [subnetId] + }) + + // Get TAO in pool directly from the pallet + const taoInPoolFromPallet = await api.query.SubtensorModule.SubnetTAO.getValue(subnetId); + + // Compare values + assert.strictEqual(taoInPool as bigint, taoInPoolFromPallet, "TAO in pool values should match"); + + // Get Alpha in pool from precompile + const alphaInPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaInPool", + args: [subnetId] + }) + + // Get Alpha in pool directly from the pallet + const alphaInPoolFromPallet = await api.query.SubtensorModule.SubnetAlphaIn.getValue(subnetId); + + // Compare values + assert.strictEqual(alphaInPool as bigint, alphaInPoolFromPallet, "Alpha in pool values should match"); + + // Get Alpha out pool from precompile + const alphaOutPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaOutPool", + args: [subnetId] + }) + + // Get Alpha out pool directly from the pallet + const alphaOutPoolFromPallet = await api.query.SubtensorModule.SubnetAlphaOut.getValue(subnetId); + + // Compare values + assert.strictEqual(alphaOutPool as bigint, alphaOutPoolFromPallet, "Alpha out pool values should match"); + }); + + it("subnet volume data is consistent", async () => { + const subnetVolume = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getSubnetVolume", + args: [subnetId] + }) + + const subnetVolumeFromPallet = await api.query.SubtensorModule.SubnetVolume.getValue(subnetId); + + assert.strictEqual(subnetVolume as bigint, subnetVolumeFromPallet, "Subnet volume values should match"); + }); + }); + + describe("Edge Cases and Error Handling", () => { + it("handles non-existent subnet gracefully", async () => { + const nonExistentSubnet = 9999; + + // These should not throw but return default values + const alphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaPrice", + args: [nonExistentSubnet] + }) + + const taoInPool = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getTaoInPool", + args: [nonExistentSubnet] + }) + + // Should return default values, not throw + assert.ok(alphaPrice !== undefined, "Should handle non-existent subnet gracefully"); + assert.ok(taoInPool !== undefined, "Should handle non-existent subnet gracefully"); + }); + + it("simulation functions handle large amounts", async () => { + const largeAmount = BigInt("1000000000000000000"); // Very large amount + + const simulatedAlpha = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapTaoForAlpha", + args: [subnetId, largeAmount] + }) + + const simulatedTao = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "simSwapAlphaForTao", + args: [subnetId, largeAmount] + }) + + // Should handle large amounts without throwing + assert.ok(simulatedAlpha !== undefined, "Should handle large TAO amounts"); + assert.ok(simulatedTao !== undefined, "Should handle large Alpha amounts"); + }); + }); +}); diff --git a/evm-tests/test/runtime.call.precompile.test.ts b/evm-tests/test/runtime.call.precompile.test.ts new file mode 100644 index 0000000000..4cd7690724 --- /dev/null +++ b/evm-tests/test/runtime.call.precompile.test.ts @@ -0,0 +1,75 @@ +import * as assert from "assert"; +import { getAliceSigner, getDevnetApi } from "../src/substrate" +import { generateRandomEthersWallet, getPublicClient } from "../src/utils"; +import { IDISPATCH_ADDRESS, ISTORAGE_QUERY_ADDRESS, ETH_LOCAL_URL } from "../src/config"; +import { devnet, MultiAddress } from "@polkadot-api/descriptors" +import { hexToNumber, PublicClient } from "viem"; +import { PolkadotSigner, TypedApi } from "polkadot-api"; +import { convertPublicKeyToSs58 } from "../src/address-utils" +import { forceSetBalanceToEthAddress, setMaxChildkeyTake } from "../src/subtensor"; +import { xxhashAsU8a } from '@polkadot/util-crypto'; +import { u8aToHex } from '@polkadot/util'; + +describe("Test the dispatch precompile", () => { + let publicClient: PublicClient; + const wallet1 = generateRandomEthersWallet(); + let api: TypedApi + let alice: PolkadotSigner; + + before(async () => { + publicClient = await getPublicClient(ETH_LOCAL_URL) + api = await getDevnetApi() + alice = await getAliceSigner() + await forceSetBalanceToEthAddress(api, wallet1.address) + }) + + it("Dispatch transfer call via precompile contract works correctly", async () => { + // call for transfer 1 token to alice + const transferAmount = BigInt(1000000000); + + const unsignedTx = api.tx.Balances.transfer_keep_alive({ + dest: MultiAddress.Id(convertPublicKeyToSs58(alice.publicKey)), + value: transferAmount, + }); + const encodedCallDataBytes = await unsignedTx.getEncodedData(); + + // encoded call should be 0x050300d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d02286bee + const transferCall = encodedCallDataBytes.asHex() + + const aliceBalance = (await api.query.System.Account.getValue( convertPublicKeyToSs58(alice.publicKey))).data.free + const txResponse = await wallet1.sendTransaction({ + to: IDISPATCH_ADDRESS, + data: transferCall, + }) + await txResponse.wait() + + const aliceBalanceAfterTransfer = (await api.query.System.Account.getValue( convertPublicKeyToSs58(alice.publicKey))).data.free + + assert.equal(aliceBalance + transferAmount, aliceBalanceAfterTransfer) + }) + + + it("Storage query call via precompile contract works correctly", async () => { + const palletPrefixBytes = xxhashAsU8a("SubtensorModule", 128); + const storageItemPrefixBytes = xxhashAsU8a("MaxChildkeyTake", 128); + const fullStorageKeyBytes = new Uint8Array([...palletPrefixBytes, ...storageItemPrefixBytes]); + // 0x658faa385070e074c85bf6b568cf0555dba018859cab7e989f77669457b394be + // key for max child key take + const fullStorageKeyHex = u8aToHex(fullStorageKeyBytes); + + let maxChildkeyTake = 257; + await setMaxChildkeyTake(api, maxChildkeyTake) + + api.query.SubtensorModule.MaxChildkeyTake.getValue(); + const rawCallResponse = await publicClient.call({ + to: ISTORAGE_QUERY_ADDRESS, + data: fullStorageKeyHex, + }) + const rawResultData = rawCallResponse.data; + if (rawResultData === undefined) { + throw new Error("rawResultData is undefined"); + } + let value = hexToNumber(rawResultData); + assert.equal(value, maxChildkeyTake, "value should be 257") + }) +}); diff --git a/evm-tests/test/sr25519.precompile.verify.test.ts b/evm-tests/test/sr25519.precompile.verify.test.ts new file mode 100644 index 0000000000..234638f195 --- /dev/null +++ b/evm-tests/test/sr25519.precompile.verify.test.ts @@ -0,0 +1,118 @@ +import { ISr25519VERIFY_ADDRESS, ISr25519VerifyABI, ETH_LOCAL_URL } from '../src/config' +import { getPublicClient } from "../src/utils"; +import { toHex, toBytes, keccak256, PublicClient } from 'viem' +import { Keyring } from "@polkadot/keyring"; +import * as assert from "assert"; + +describe("Verfication of sr25519 signature", () => { + // init eth part + let ethClient: PublicClient; + + before(async () => { + ethClient = await getPublicClient(ETH_LOCAL_URL); + }); + + it("Verification of sr25519 works", async () => { + const keyring = new Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + ////////////////////////////////////////////////////////////////////// + // Generate a signature + + // Your message to sign + const message = "Sign this message"; + const messageU8a = new TextEncoder().encode(message); + const messageHex = toHex(messageU8a); // Convert message to hex string + const messageHash = keccak256(messageHex); // Hash the message to fit into bytes32 + console.log(`messageHash = ${messageHash}`); + const hashedMessageBytes = toBytes(messageHash); + console.log(`hashedMessageBytes = ${hashedMessageBytes}`); + + // Sign the message + const signature = await alice.sign(hashedMessageBytes); + console.log(`Signature: ${toHex(signature)}`); + + // Verify the signature locally + const isValid = alice.verify( + hashedMessageBytes, + signature, + alice.publicKey + ); + console.log(`Is the signature valid? ${isValid}`); + + ////////////////////////////////////////////////////////////////////// + // Verify the signature using the precompile contract + + const publicKeyBytes = toHex(alice.publicKey); + console.log(`publicKeyBytes = ${publicKeyBytes}`); + + // Split signture into Commitment (R) and response (s) + let r = signature.slice(0, 32); // Commitment, a.k.a. "r" - first 32 bytes + let s = signature.slice(32, 64); // Response, a.k.a. "s" - second 32 bytes + let rBytes = toHex(r); + let sBytes = toHex(s); + + const isPrecompileValid = await ethClient.readContract({ + address: ISr25519VERIFY_ADDRESS, + abi: ISr25519VerifyABI, + functionName: "verify", + args: [messageHash, + publicKeyBytes, + rBytes, + sBytes] + + }); + + console.log( + `Is the signature valid according to the smart contract? ${isPrecompileValid}` + ); + assert.equal(isPrecompileValid, true) + + ////////////////////////////////////////////////////////////////////// + // Verify the signature for bad data using the precompile contract + + let brokenHashedMessageBytes = hashedMessageBytes; + brokenHashedMessageBytes[0] = (brokenHashedMessageBytes[0] + 1) % 0xff; + const brokenMessageHash = toHex(brokenHashedMessageBytes); + console.log(`brokenMessageHash = ${brokenMessageHash}`); + + const isPrecompileValidBadData = await ethClient.readContract({ + address: ISr25519VERIFY_ADDRESS, + abi: ISr25519VerifyABI, + functionName: "verify", + args: [brokenMessageHash, + publicKeyBytes, + rBytes, + sBytes] + + }); + + console.log( + `Is the signature valid according to the smart contract for broken data? ${isPrecompileValidBadData}` + ); + assert.equal(isPrecompileValidBadData, false) + + ////////////////////////////////////////////////////////////////////// + // Verify the bad signature for good data using the precompile contract + + let brokenR = r; + brokenR[0] = (brokenR[0] + 1) % 0xff; + rBytes = toHex(r); + const isPrecompileValidBadSignature = await ethClient.readContract({ + address: ISr25519VERIFY_ADDRESS, + abi: ISr25519VerifyABI, + functionName: "verify", + args: [messageHash, + publicKeyBytes, + rBytes, + sBytes] + + }); + + console.log( + `Is the signature valid according to the smart contract for broken signature? ${isPrecompileValidBadSignature}` + ); + assert.equal(isPrecompileValidBadSignature, false) + + }); +}); \ No newline at end of file diff --git a/evm-tests/test/subnet.precompile.hyperparameter.test.ts b/evm-tests/test/subnet.precompile.hyperparameter.test.ts index 57efd64f77..bc95ca0716 100644 --- a/evm-tests/test/subnet.precompile.hyperparameter.test.ts +++ b/evm-tests/test/subnet.precompile.hyperparameter.test.ts @@ -56,6 +56,27 @@ describe("Test the Subnet precompile contract", () => { const totalNetworkAfterAdd = await api.query.SubtensorModule.TotalNetworks.getValue() assert.ok(totalNetwork + 1 === totalNetworkAfterAdd) }); + + it.only("Can register network with identity info and logo url", async () => { + const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() + + const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); + const tx = await contract["registerNetwork(bytes32,string,string,string,string,string,string,string,string)"]( + hotkey2.publicKey, + "name", + "repo", + "contact", + "subnetUrl", + "discord", + "description", + "logoUrl", + "additional" + ); + await tx.wait(); + + const totalNetworkAfterAdd = await api.query.SubtensorModule.TotalNetworks.getValue() + assert.ok(totalNetwork + 1 === totalNetworkAfterAdd) + }); it("Can set servingRateLimit parameter", async () => { diff --git a/evm-tests/test/uid.precompile.lookup.test.ts b/evm-tests/test/uid.precompile.lookup.test.ts index 6e702d612e..f6e22ce032 100644 --- a/evm-tests/test/uid.precompile.lookup.test.ts +++ b/evm-tests/test/uid.precompile.lookup.test.ts @@ -55,12 +55,11 @@ describe("Test the UID Lookup precompile", () => { const signature = await evmWallet.signMessage(concatenatedArray); const associateEvmKeyTx = api.tx.SubtensorModule.associate_evm_key({ netuid: netuid, - hotkey: convertPublicKeyToSs58(hotkey.publicKey), evm_key: convertToFixedSizeBinary(evmWallet.address, 20), block_number: BigInt(blockNumber), signature: convertToFixedSizeBinary(signature, 65) }); - const signer = getSignerFromKeypair(coldkey); + const signer = getSignerFromKeypair(hotkey); await waitForTransactionCompletion(api, associateEvmKeyTx, signer) .then(() => { }) .catch((error) => { console.log(`transaction error ${error}`) }); diff --git a/evm-tests/yarn.lock b/evm-tests/yarn.lock new file mode 100644 index 0000000000..043a97f2ef --- /dev/null +++ b/evm-tests/yarn.lock @@ -0,0 +1,3225 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@adraffy/ens-normalize@^1.10.1": + version "1.11.0" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== + +"@babel/code-frame@^7.26.2": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@commander-js/extra-typings@^13.1.0": + version "13.1.0" + resolved "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-13.1.0.tgz" + integrity sha512-q5P52BYb1hwVWE6dtID7VvuJWrlfbCv4klj7BjUUOqMz4jbSZD4C9fJ9lRjL2jnBGTg+gDDlaXN51rkWcLk4fg== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/aix-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" + integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" + integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" + integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/android-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" + integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz" + integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/darwin-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" + integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" + integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/freebsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" + integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" + integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" + integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" + integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-loong64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" + integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-mips64el@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" + integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" + integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-riscv64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" + integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-s390x@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" + integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/linux-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" + integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== + +"@esbuild/netbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" + integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/netbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" + integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== + +"@esbuild/openbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" + integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/openbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" + integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/sunos-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" + integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" + integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" + integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + +"@esbuild/win32-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" + integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.8" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.8.1", "@noble/curves@^1.3.0", "@noble/curves@^1.6.0", "@noble/curves@^1.7.0", "@noble/curves@^1.8.1", "@noble/curves@~1.8.1": + version "1.8.1" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz" + integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ== + dependencies: + "@noble/hashes" "1.7.1" + +"@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@1.7.1", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.5.0", "@noble/hashes@^1.6.1", "@noble/hashes@^1.7.1", "@noble/hashes@~1.7.1": + version "1.7.1" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz" + integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== + +"@noble/hashes@^1.8.0": + version "1.8.0" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@noble/hashes@~1.6.0": + version "1.6.1" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@polkadot-api/cli@0.13.0": + version "0.13.0" + resolved "https://registry.npmjs.org/@polkadot-api/cli/-/cli-0.13.0.tgz" + integrity sha512-uumqacO1+YxuhHYOr75czxvV0KmRxm3DaZtRKzxIf2zpICnj/QnBTpJwlxU56g+pQDU5P/hTR0Thh0vrnUTNVw== + dependencies: + "@commander-js/extra-typings" "^13.1.0" + "@polkadot-api/codegen" "0.16.0" + "@polkadot-api/ink-contracts" "0.3.2" + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/known-chains" "0.7.6" + "@polkadot-api/metadata-compatibility" "0.2.3" + "@polkadot-api/observable-client" "0.11.0" + "@polkadot-api/polkadot-sdk-compat" "2.3.2" + "@polkadot-api/sm-provider" "0.1.7" + "@polkadot-api/smoldot" "0.3.8" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/substrate-client" "0.3.0" + "@polkadot-api/utils" "0.1.2" + "@polkadot-api/wasm-executor" "^0.1.2" + "@polkadot-api/ws-provider" "0.4.0" + "@types/node" "^22.15.18" + commander "^13.1.0" + execa "^9.5.3" + fs.promises.exists "^1.1.4" + ora "^8.2.0" + read-pkg "^9.0.1" + rxjs "^7.8.2" + tsc-prog "^2.3.0" + tsup "^8.4.0" + typescript "^5.8.3" + write-package "^7.1.0" + +"@polkadot-api/codegen@0.16.0": + version "0.16.0" + resolved "https://registry.npmjs.org/@polkadot-api/codegen/-/codegen-0.16.0.tgz" + integrity sha512-2Sq/fkB7a9Oi3t7nGc0EbTt1Nd8Pb8XGiKKS9i/wwFAdCLN2oXd33DxmRQTX0Hm2/nrBzXYh1zBuyxRUb9+Sdw== + dependencies: + "@polkadot-api/ink-contracts" "0.3.2" + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/metadata-compatibility" "0.2.3" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/descriptors@file:.papi/descriptors": + version "0.1.0-autogenerated.9294084971075542043" + +"@polkadot-api/ink-contracts@0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@polkadot-api/ink-contracts/-/ink-contracts-0.3.2.tgz" + integrity sha512-ipWuClaySrPI7XHIomiswXhIZfU4q/EmHmLFIwLdn9iNhLd7YLuUtGF6kacSQu76YtWd3tkLe2rGx4cRRaLjOA== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/json-rpc-provider-proxy@0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.4.tgz" + integrity sha512-nuGoY9QpBAiRU7xmXN3nugFvPcnSu3IxTLm1OWcNTGlZ1LW5bvdQHz3JLk56+Jlyb3GJ971hqdg2DJsMXkKCOg== + +"@polkadot-api/json-rpc-provider-proxy@^0.1.0": + version "0.1.0" + resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz" + integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== + +"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": + version "0.0.1" + resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz" + integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== + +"@polkadot-api/json-rpc-provider@0.0.4": + version "0.0.4" + resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.4.tgz" + integrity sha512-9cDijLIxzHOBuq6yHqpqjJ9jBmXrctjc1OFqU+tQrS96adQze3mTIH6DTgfb/0LMrqxzxffz1HQGrIlEH00WrA== + +"@polkadot-api/known-chains@0.7.6": + version "0.7.6" + resolved "https://registry.npmjs.org/@polkadot-api/known-chains/-/known-chains-0.7.6.tgz" + integrity sha512-em+p9AVfTYulC4U10I+nO42wdczN9ZSAEyb5ppQsxxsKAxaJVPVe4xsDkWzlhheheEN6OBojNHnoYNBVG6X2bg== + +"@polkadot-api/logs-provider@0.0.6": + version "0.0.6" + resolved "https://registry.npmjs.org/@polkadot-api/logs-provider/-/logs-provider-0.0.6.tgz" + integrity sha512-4WgHlvy+xee1ADaaVf6+MlK/+jGMtsMgAzvbQOJZnP4PfQuagoTqaeayk8HYKxXGphogLlPbD06tANxcb+nvAg== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + +"@polkadot-api/merkleize-metadata@1.1.17": + version "1.1.17" + resolved "https://registry.npmjs.org/@polkadot-api/merkleize-metadata/-/merkleize-metadata-1.1.17.tgz" + integrity sha512-3wlLrYjpBluN5l8M1H9zgXlFHfJhqIXYvSVXTvkBYcEVKxZt0PO0f43Zgskeabg29Lx83OiPINcEHFWF8ndAzg== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/metadata-builders@0.12.1": + version "0.12.1" + resolved "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.12.1.tgz" + integrity sha512-heGt+WgcxrS1CqMm9XwD2DC+fI6azMKJf2ToMP+H12yw6FAy++nijASDZ3MlV/0ZpA/QGZpuZmgQmxKh6jbxVg== + dependencies: + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/metadata-builders@0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz" + integrity sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg== + dependencies: + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/metadata-compatibility@0.2.3": + version "0.2.3" + resolved "https://registry.npmjs.org/@polkadot-api/metadata-compatibility/-/metadata-compatibility-0.2.3.tgz" + integrity sha512-rtym491RA2yl8qGdEDJVujiCya+DK0CW5AwB6InSo85Um04/WWMq7oboRiXQZmspwLkfm2vYBusl/Q9k4Rxshw== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/substrate-bindings" "0.13.0" + +"@polkadot-api/observable-client@0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.11.0.tgz" + integrity sha512-cyXyih+RI73vPcUQ6GxyMelm1Z3bGDvBIow8W3MqBdpUy4mZ87QGQXGpyBC0Op/qnIxrUFP1cLyT38fUe0i6KQ== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/observable-client@^0.3.0": + version "0.3.2" + resolved "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz" + integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== + dependencies: + "@polkadot-api/metadata-builders" "0.3.2" + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/pjs-signer@0.6.8": + version "0.6.8" + resolved "https://registry.npmjs.org/@polkadot-api/pjs-signer/-/pjs-signer-0.6.8.tgz" + integrity sha512-YBp+uF2mPZFH4VjT5xgIU462EXbdLrFz09D6vY4SgoS2FRbPV7ktnqiNK2BykKJPGV4TiqpEjNB4OtX6ZLzafg== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signers-common" "0.1.9" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/polkadot-sdk-compat@2.3.2": + version "2.3.2" + resolved "https://registry.npmjs.org/@polkadot-api/polkadot-sdk-compat/-/polkadot-sdk-compat-2.3.2.tgz" + integrity sha512-rLCveP3a6Xd0r218yRqVY34lJ8bXVmE12cArbU4JFp9p8e8Jbb6xdqOdu7bQtjlZUsahhcmfIHYQSXKziST7PA== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + +"@polkadot-api/polkadot-signer@0.1.6": + version "0.1.6" + resolved "https://registry.npmjs.org/@polkadot-api/polkadot-signer/-/polkadot-signer-0.1.6.tgz" + integrity sha512-X7ghAa4r7doETtjAPTb50IpfGtrBmy3BJM5WCfNKa1saK04VFY9w+vDn+hwEcM4p0PcDHt66Ts74hzvHq54d9A== + +"@polkadot-api/signer@0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@polkadot-api/signer/-/signer-0.2.1.tgz" + integrity sha512-z3BPDIglLh/hghQExQVVHR3xgIijjEVcIA2P+xLan5vO4cglGm4U6vIBXgKBuU2oxKlG494ixH8BkXSv5F79zw== + dependencies: + "@noble/hashes" "^1.8.0" + "@polkadot-api/merkleize-metadata" "1.1.17" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signers-common" "0.1.9" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/signers-common@0.1.9": + version "0.1.9" + resolved "https://registry.npmjs.org/@polkadot-api/signers-common/-/signers-common-0.1.9.tgz" + integrity sha512-eOAPfnNpa0kJrtM/OPHOt+jlFP97c4CWZmzfcPzOqfrLUgyyLzVCFzgBipffpzPXNPQsToM6FM+7DQEgQmoDuA== + dependencies: + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/sm-provider@0.1.7": + version "0.1.7" + resolved "https://registry.npmjs.org/@polkadot-api/sm-provider/-/sm-provider-0.1.7.tgz" + integrity sha512-BhNKVeIFZdawpPVadXszLl8IP4EDjcLHe/GchfRRFkvoNFuwS2nNv/npYIqCviXV+dd2R8VnEELxwScsf380Og== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/json-rpc-provider-proxy" "0.2.4" + +"@polkadot-api/smoldot@0.3.8": + version "0.3.8" + resolved "https://registry.npmjs.org/@polkadot-api/smoldot/-/smoldot-0.3.8.tgz" + integrity sha512-dbJSMRFtELDW+rZIWRwKE/K8oy7+gYaGl+DvaOjARoBW2n80rJ7RAMOCCu+b5h2zgl3elftFBwMNAuAWgHT/Zg== + dependencies: + "@types/node" "^22.9.0" + smoldot "2.0.34" + +"@polkadot-api/substrate-bindings@0.13.0": + version "0.13.0" + resolved "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.13.0.tgz" + integrity sha512-M/60lXtHr4flwx4K7L4xv2jLk44EhD8UB4jvah+jbZM195I89nZGXKo2JOkgyR5DHoLj//TAoBkLedZmaaAiaQ== + dependencies: + "@noble/hashes" "^1.8.0" + "@polkadot-api/utils" "0.1.2" + "@scure/base" "^1.2.5" + scale-ts "^1.6.1" + +"@polkadot-api/substrate-bindings@0.6.0": + version "0.6.0" + resolved "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz" + integrity sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw== + dependencies: + "@noble/hashes" "^1.3.1" + "@polkadot-api/utils" "0.1.0" + "@scure/base" "^1.1.1" + scale-ts "^1.6.0" + +"@polkadot-api/substrate-client@0.3.0": + version "0.3.0" + resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.3.0.tgz" + integrity sha512-0hEvQLKH2zhaFzE8DPkWehvJilec8u2O2wbIEUStm0OJ8jIFtJ40MFjXQfB01dXBWUz1KaVBqS6xd3sZA90Dpw== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/utils" "0.1.2" + +"@polkadot-api/substrate-client@^0.1.2": + version "0.1.4" + resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/utils@0.1.0": + version "0.1.0" + resolved "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz" + integrity sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA== + +"@polkadot-api/utils@0.1.2": + version "0.1.2" + resolved "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.2.tgz" + integrity sha512-yhs5k2a8N1SBJcz7EthZoazzLQUkZxbf+0271Xzu42C5AEM9K9uFLbsB+ojzHEM72O5X8lPtSwGKNmS7WQyDyg== + +"@polkadot-api/wasm-executor@^0.1.2": + version "0.1.2" + resolved "https://registry.npmjs.org/@polkadot-api/wasm-executor/-/wasm-executor-0.1.2.tgz" + integrity sha512-a5wGenltB3EFPdf72u8ewi6HsUg2qubUAf3ekJprZf24lTK3+w8a/GUF/y6r08LJF35MALZ32SAtLqtVTIOGnQ== + +"@polkadot-api/ws-provider@0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@polkadot-api/ws-provider/-/ws-provider-0.4.0.tgz" + integrity sha512-ZurjUHHAlQ1Ux8HiZz7mtkg1qjq6LmqxcHljcZxne0U7foCZrXdWHsohwlV8kUQUir5kXuDsNvdZN/MFCUMaVw== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/json-rpc-provider-proxy" "0.2.4" + ws "^8.18.1" + +"@polkadot-labs/hdkd-helpers@0.0.10": + version "0.0.10" + resolved "https://registry.npmjs.org/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.10.tgz" + integrity sha512-wBKenhN7TjNiMXxBvQWzFf+su8xTaRGqyOKAlAfpyY9oWTOt3G05yMvDHEZ4g/NRLoE4P3fQYQ0bdcMKl7KkDw== + dependencies: + "@noble/curves" "^1.7.0" + "@noble/hashes" "^1.6.1" + "@scure/base" "^1.2.1" + micro-sr25519 "^0.1.0" + scale-ts "^1.6.1" + +"@polkadot-labs/hdkd-helpers@^0.0.11": + version "0.0.11" + resolved "https://registry.npmjs.org/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.11.tgz" + integrity sha512-qPlWqC3NNV/2NYc5GEy+Ovi4UBAgkMGvMfyiYuj2BQN4lW59Q1T9coNx0Yp6XzsnJ1ddaF9PWaUtxj3LdM0IDw== + dependencies: + "@noble/curves" "^1.8.1" + "@noble/hashes" "^1.7.1" + "@scure/base" "^1.2.4" + micro-sr25519 "^0.1.0" + scale-ts "^1.6.1" + +"@polkadot-labs/hdkd@^0.0.10": + version "0.0.10" + resolved "https://registry.npmjs.org/@polkadot-labs/hdkd/-/hdkd-0.0.10.tgz" + integrity sha512-jD8l+Ls/kZjvZja4T2Y0G6Be3rfGn0qNs3hvcNeV2CmOMtI7yRkkWPXI7WiJ8AyEoBwBuZt0rm6yzGla6o2HXQ== + dependencies: + "@polkadot-labs/hdkd-helpers" "0.0.10" + +"@polkadot/api-augment@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-15.1.1.tgz" + integrity sha512-tYASON7vVLz7FGcXVX9dWSd/9pR6FckayEkc08Z6RyjH7HfjtCZ3/Dz7MlGRNql4SnPi4+xpjSD6rwrZcETU1g== + dependencies: + "@polkadot/api-base" "15.1.1" + "@polkadot/rpc-augment" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/types-augment" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/api-base@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/api-base/-/api-base-15.1.1.tgz" + integrity sha512-OXLZ7/k2RXLIA8hKA8oyii6o8MuGlqujIDcLVaMdtWnQsBg26h8pv/mujT2YSz2OguLxrfdvD+lUGtwZC8kw4A== + dependencies: + "@polkadot/rpc-core" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/util" "^13.2.3" + rxjs "^7.8.1" + tslib "^2.8.0" + +"@polkadot/api-derive@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-15.1.1.tgz" + integrity sha512-UPcKr9FplfYKPaP7FYEF917Sm1rKnQFX4AzQJn3f8ySp7DDf6EYiHrNICtGifPEAoANTSW+YHlSchhtnvfSIhw== + dependencies: + "@polkadot/api" "15.1.1" + "@polkadot/api-augment" "15.1.1" + "@polkadot/api-base" "15.1.1" + "@polkadot/rpc-core" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/util" "^13.2.3" + "@polkadot/util-crypto" "^13.2.3" + rxjs "^7.8.1" + tslib "^2.8.0" + +"@polkadot/api@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/api/-/api-15.1.1.tgz" + integrity sha512-n3QeQ1CXlzjqyh2eFbEQPcnkXO3J4QYNTIj0Lnz/XFUpzKimHPDA2iUfaXuy5dXjnzS21jFANGSUFoZ+XKi/8g== + dependencies: + "@polkadot/api-augment" "15.1.1" + "@polkadot/api-base" "15.1.1" + "@polkadot/api-derive" "15.1.1" + "@polkadot/keyring" "^13.2.3" + "@polkadot/rpc-augment" "15.1.1" + "@polkadot/rpc-core" "15.1.1" + "@polkadot/rpc-provider" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/types-augment" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/types-create" "15.1.1" + "@polkadot/types-known" "15.1.1" + "@polkadot/util" "^13.2.3" + "@polkadot/util-crypto" "^13.2.3" + eventemitter3 "^5.0.1" + rxjs "^7.8.1" + tslib "^2.8.0" + +"@polkadot/keyring@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.4.3.tgz" + integrity sha512-2ePNcvBTznDN2luKbZM5fdxgAnj7V8m276qSTgrHlqKVvg9FsQpRCR6CAU+AjhnHzpe7uiZO+UH+jlXWefI3AA== + dependencies: + "@polkadot/util" "13.4.3" + "@polkadot/util-crypto" "13.4.3" + tslib "^2.8.0" + +"@polkadot/networks@13.4.3", "@polkadot/networks@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/networks/-/networks-13.4.3.tgz" + integrity sha512-Z+YZkltBt//CtkVH8ZYJ1z66qYxdI0yPamzkzZAqw6gj3gjgSxKtxB4baA/rcAw05QTvN2R3dLkkmKr2mnHovQ== + dependencies: + "@polkadot/util" "13.4.3" + "@substrate/ss58-registry" "^1.51.0" + tslib "^2.8.0" + +"@polkadot/rpc-augment@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-15.1.1.tgz" + integrity sha512-s6i4nTy7/1Q5svIMT4TR55GLRv9asG7xbJcntHEsQ2nDs8zZV/mvPWfEUxgup0xVO8sDgyrf6KTTVRKJjySjUg== + dependencies: + "@polkadot/rpc-core" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/rpc-core@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-15.1.1.tgz" + integrity sha512-KErbVgPChps7NsxcGch5JCArZHNqs81fDEzs+XoHnD05nzuxcO38v4Yu+M04lHLax2m8ky8K6o3gurBglJENlA== + dependencies: + "@polkadot/rpc-augment" "15.1.1" + "@polkadot/rpc-provider" "15.1.1" + "@polkadot/types" "15.1.1" + "@polkadot/util" "^13.2.3" + rxjs "^7.8.1" + tslib "^2.8.0" + +"@polkadot/rpc-provider@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-15.1.1.tgz" + integrity sha512-9OWV1dyX+vmAbKkhMU8J7Q0sCaovPrkwZqo2ejmEpZ/Lr12Hw5JAk4gdvB869QEVP7zj0gH3HuYVajmsxesYKg== + dependencies: + "@polkadot/keyring" "^13.2.3" + "@polkadot/types" "15.1.1" + "@polkadot/types-support" "15.1.1" + "@polkadot/util" "^13.2.3" + "@polkadot/util-crypto" "^13.2.3" + "@polkadot/x-fetch" "^13.2.3" + "@polkadot/x-global" "^13.2.3" + "@polkadot/x-ws" "^13.2.3" + eventemitter3 "^5.0.1" + mock-socket "^9.3.1" + nock "^13.5.5" + tslib "^2.8.0" + optionalDependencies: + "@substrate/connect" "0.8.11" + +"@polkadot/types-augment@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-15.1.1.tgz" + integrity sha512-6v/FsN/JYCupyGYW+MbS0iOCiWvf6PXJ5+m8ORYYYDPFgQqaQPxKMKWJpnO0s9cCR33QcyNYhErPGuZ62UMJjw== + dependencies: + "@polkadot/types" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/types-codec@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-15.1.1.tgz" + integrity sha512-cm99CFvDf4UXmw7DeMkRqa/hf7wEgjJZoZZW/B12Js0ObwRmSXMk/gDbyiT6hqPnQ81sU726E72p39DolaEatQ== + dependencies: + "@polkadot/util" "^13.2.3" + "@polkadot/x-bigint" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/types-create@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types-create/-/types-create-15.1.1.tgz" + integrity sha512-AOgz+UsUqsGSENrc+p/dHyXH2TC9qVtUTAxlqaHfOnwqjMWfEqc78mc5a1mk0a+RqxmIHw8nQNSdBdhv+UdtyQ== + dependencies: + "@polkadot/types-codec" "15.1.1" + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/types-known@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types-known/-/types-known-15.1.1.tgz" + integrity sha512-L934pYxXdHB3GHlVu57ihO6llhxuggSuQZuJ9kHunG0I6tezXLIgAhwaPgACMVbmBYlkJPqm4Nr6pC3kpIsGow== + dependencies: + "@polkadot/networks" "^13.2.3" + "@polkadot/types" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/types-create" "15.1.1" + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/types-support@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types-support/-/types-support-15.1.1.tgz" + integrity sha512-uyn5N7XERHosVq0+aCpEwYnkUroOr7OX8B8/00UkgmfVOXskp/cukEVcGlmI/YGAS+9+V2BZN2GBX7Lz0eeKmw== + dependencies: + "@polkadot/util" "^13.2.3" + tslib "^2.8.0" + +"@polkadot/types@15.1.1": + version "15.1.1" + resolved "https://registry.npmjs.org/@polkadot/types/-/types-15.1.1.tgz" + integrity sha512-n6lg/quhLp3Zmt/6gHAg2uoSmMmXk3NR19I7qCyeDJ30pP1UhOjtmuWOQDl6SwSEwuHtudLp3p2nCJsymXjgsw== + dependencies: + "@polkadot/keyring" "^13.2.3" + "@polkadot/types-augment" "15.1.1" + "@polkadot/types-codec" "15.1.1" + "@polkadot/types-create" "15.1.1" + "@polkadot/util" "^13.2.3" + "@polkadot/util-crypto" "^13.2.3" + rxjs "^7.8.1" + tslib "^2.8.0" + +"@polkadot/util-crypto@13.4.3", "@polkadot/util-crypto@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.4.3.tgz" + integrity sha512-Ml0mjhKVetMrRCIosmVNMa6lbFPa3fSAeOggf34NsDIIQOKt9FL644iGz1ZSMOnBwN9qk2qHYmcFMTDXX2yKVQ== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "13.4.3" + "@polkadot/util" "13.4.3" + "@polkadot/wasm-crypto" "^7.4.1" + "@polkadot/wasm-util" "^7.4.1" + "@polkadot/x-bigint" "13.4.3" + "@polkadot/x-randomvalues" "13.4.3" + "@scure/base" "^1.1.7" + tslib "^2.8.0" + +"@polkadot/util@13.4.3", "@polkadot/util@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/util/-/util-13.4.3.tgz" + integrity sha512-6v2zvg8l7W22XvjYf7qv9tPQdYl2E6aXY94M4TZKsXZxmlS5BoG+A9Aq0+Gw8zBUjupjEmUkA6Y//msO8Zisug== + dependencies: + "@polkadot/x-bigint" "13.4.3" + "@polkadot/x-global" "13.4.3" + "@polkadot/x-textdecoder" "13.4.3" + "@polkadot/x-textencoder" "13.4.3" + "@types/bn.js" "^5.1.6" + bn.js "^5.2.1" + tslib "^2.8.0" + +"@polkadot/wasm-bridge@7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz" + integrity sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g== + dependencies: + "@polkadot/wasm-util" "7.4.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-asmjs@7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.4.1.tgz" + integrity sha512-pwU8QXhUW7IberyHJIQr37IhbB6DPkCG5FhozCiNTq4vFBsFPjm9q8aZh7oX1QHQaiAZa2m2/VjIVE+FHGbvHQ== + dependencies: + tslib "^2.7.0" + +"@polkadot/wasm-crypto-init@7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.4.1.tgz" + integrity sha512-AVka33+f7MvXEEIGq5U0dhaA2SaXMXnxVCQyhJTaCnJ5bRDj0Xlm3ijwDEQUiaDql7EikbkkRtmlvs95eSUWYQ== + dependencies: + "@polkadot/wasm-bridge" "7.4.1" + "@polkadot/wasm-crypto-asmjs" "7.4.1" + "@polkadot/wasm-crypto-wasm" "7.4.1" + "@polkadot/wasm-util" "7.4.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-wasm@7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.4.1.tgz" + integrity sha512-PE1OAoupFR0ZOV2O8tr7D1FEUAwaggzxtfs3Aa5gr+yxlSOaWUKeqsOYe1KdrcjmZVV3iINEAXxgrbzCmiuONg== + dependencies: + "@polkadot/wasm-util" "7.4.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto@^7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.4.1.tgz" + integrity sha512-kHN/kF7hYxm1y0WeFLWeWir6oTzvcFmR4N8fJJokR+ajYbdmrafPN+6iLgQVbhZnDdxyv9jWDuRRsDnBx8tPMQ== + dependencies: + "@polkadot/wasm-bridge" "7.4.1" + "@polkadot/wasm-crypto-asmjs" "7.4.1" + "@polkadot/wasm-crypto-init" "7.4.1" + "@polkadot/wasm-crypto-wasm" "7.4.1" + "@polkadot/wasm-util" "7.4.1" + tslib "^2.7.0" + +"@polkadot/wasm-util@7.4.1", "@polkadot/wasm-util@^7.4.1": + version "7.4.1" + resolved "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.4.1.tgz" + integrity sha512-RAcxNFf3zzpkr+LX/ItAsvj+QyM56TomJ0xjUMo4wKkHjwsxkz4dWJtx5knIgQz/OthqSDMR59VNEycQeNuXzA== + dependencies: + tslib "^2.7.0" + +"@polkadot/x-bigint@13.4.3", "@polkadot/x-bigint@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.4.3.tgz" + integrity sha512-8NbjF5Q+5lflhvDFve58wULjCVcvXa932LKFtI5zL2gx5VDhMgyfkNcYRjHB18Ecl21963JuGzvGVTZNkh/i6g== + dependencies: + "@polkadot/x-global" "13.4.3" + tslib "^2.8.0" + +"@polkadot/x-fetch@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.4.3.tgz" + integrity sha512-EwhcwROqWa7mvNTbLVNH71Hbyp5PW5j9lV2UpII5MZzRO95eYwV4oP/xgtTxC+60nC8lrvzAw0JxEHrmNzmtlg== + dependencies: + "@polkadot/x-global" "13.4.3" + node-fetch "^3.3.2" + tslib "^2.8.0" + +"@polkadot/x-global@13.4.3", "@polkadot/x-global@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.4.3.tgz" + integrity sha512-6c98kxZdoGRct3ua9Dz6/qz8wb3XFRUkaY+4+RzIgehKMPhu19pGWTrzmbJSyY9FtIpThuWKuDaBEvd5KgSxjA== + dependencies: + tslib "^2.8.0" + +"@polkadot/x-randomvalues@13.4.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.4.3.tgz" + integrity sha512-pskXP/S2jROZ6aASExsUFlNp7GbJvQikKogvyvMMCzNIbUYLxpLuquLRa3MOORx2c0SNsENg90cx/zHT+IjPRQ== + dependencies: + "@polkadot/x-global" "13.4.3" + tslib "^2.8.0" + +"@polkadot/x-textdecoder@13.4.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.4.3.tgz" + integrity sha512-k7Wg6csAPxfNtpBt3k5yUuPHYmRl/nl7H2OMr40upMjbZXbQ1RJW9Z3GBkLmQczG7NwwfAXHwQE9FYOMUtbuRQ== + dependencies: + "@polkadot/x-global" "13.4.3" + tslib "^2.8.0" + +"@polkadot/x-textencoder@13.4.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.4.3.tgz" + integrity sha512-byl2LbN1rnEXKmnsCzEDaIjSIHAr+1ciSe2yj3M0K+oWEEcaFZEovJaf/uoyzkcjn+/l8rDv3nget6mPuQ/DSw== + dependencies: + "@polkadot/x-global" "13.4.3" + tslib "^2.8.0" + +"@polkadot/x-ws@^13.2.3": + version "13.4.3" + resolved "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.4.3.tgz" + integrity sha512-GS0I6MYLD/xNAAjODZi/pbG7Ba0e/5sbvDIrT01iKH3SPGN+PZoyAsc04t2IOXA6QmPa1OBHnaU3N4K8gGmJ+w== + dependencies: + "@polkadot/x-global" "13.4.3" + tslib "^2.8.0" + ws "^8.18.0" + +"@rollup/rollup-android-arm-eabi@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" + integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== + +"@rollup/rollup-android-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" + integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== + +"@rollup/rollup-darwin-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" + integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== + +"@rollup/rollup-darwin-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" + integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== + +"@rollup/rollup-freebsd-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" + integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== + +"@rollup/rollup-freebsd-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" + integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" + integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== + +"@rollup/rollup-linux-arm-musleabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" + integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== + +"@rollup/rollup-linux-arm64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" + integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== + +"@rollup/rollup-linux-arm64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" + integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== + +"@rollup/rollup-linux-loongarch64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" + integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== + +"@rollup/rollup-linux-powerpc64le-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" + integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== + +"@rollup/rollup-linux-riscv64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" + integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== + +"@rollup/rollup-linux-s390x-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" + integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== + +"@rollup/rollup-linux-x64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" + integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== + +"@rollup/rollup-linux-x64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678" + integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== + +"@rollup/rollup-win32-arm64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" + integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== + +"@rollup/rollup-win32-ia32-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" + integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== + +"@rollup/rollup-win32-x64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" + integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== + +"@rx-state/core@^0.1.4": + version "0.1.4" + resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz" + integrity sha512-Z+3hjU2xh1HisLxt+W5hlYX/eGSDaXXP+ns82gq/PLZpkXLu0uwcNUh9RLY3Clq4zT+hSsA3vcpIGt6+UAb8rQ== + +"@scure/base@^1.1.1", "@scure/base@^1.1.7", "@scure/base@^1.2.1", "@scure/base@^1.2.4", "@scure/base@^1.2.5", "@scure/base@~1.2.2", "@scure/base@~1.2.4": + version "1.2.5" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.2.5.tgz" + integrity sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw== + +"@scure/bip32@1.6.2", "@scure/bip32@^1.5.0": + version "1.6.2" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz" + integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.2" + +"@scure/bip39@1.5.4", "@scure/bip39@^1.4.0": + version "1.5.4" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz" + integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA== + dependencies: + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.4" + +"@sec-ant/readable-stream@^0.4.1": + version "0.4.1" + resolved "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz" + integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== + +"@sindresorhus/merge-streams@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz" + integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== + +"@substrate/connect-extension-protocol@^2.0.0": + version "2.2.2" + resolved "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz" + integrity sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA== + +"@substrate/connect-known-chains@^1.1.5": + version "1.9.2" + resolved "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.9.2.tgz" + integrity sha512-uEmm+rKJQQhhbforvmcg74TsDHKFVBkstjPwblGT1RdHMxUKR7Gq7F8vbkGnr5ce9tMK2Ylil760Z7vtX013hw== + +"@substrate/connect@0.8.11": + version "0.8.11" + resolved "https://registry.npmjs.org/@substrate/connect/-/connect-0.8.11.tgz" + integrity sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw== + dependencies: + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + "@substrate/light-client-extension-helpers" "^1.0.0" + smoldot "2.0.26" + +"@substrate/light-client-extension-helpers@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz" + integrity sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg== + dependencies: + "@polkadot-api/json-rpc-provider" "^0.0.1" + "@polkadot-api/json-rpc-provider-proxy" "^0.1.0" + "@polkadot-api/observable-client" "^0.3.0" + "@polkadot-api/substrate-client" "^0.1.2" + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + rxjs "^7.8.1" + +"@substrate/ss58-registry@^1.51.0": + version "1.51.0" + resolved "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz" + integrity sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ== + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/bn.js@^5.1.6": + version "5.1.6" + resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== + dependencies: + "@types/node" "*" + +"@types/bun@^1.1.13": + version "1.2.3" + resolved "https://registry.npmjs.org/@types/bun/-/bun-1.2.3.tgz" + integrity sha512-054h79ipETRfjtsCW9qJK8Ipof67Pw9bodFWmkfkaUaRiIQ1dIV2VTlheshlBx3mpKr0KeK8VqnMMCtgN9rQtw== + dependencies: + bun-types "1.2.3" + +"@types/chai@^5.0.1": + version "5.0.1" + resolved "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz" + integrity sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA== + dependencies: + "@types/deep-eql" "*" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/estree@1.0.6": + version "1.0.6" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@*", "@types/node@^22.15.18", "@types/node@^22.9.0": + version "22.15.21" + resolved "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz" + integrity sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ== + dependencies: + undici-types "~6.21.0" + +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/normalize-package-data@^2.4.3": + version "2.4.4" + resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + +"@types/ws@~8.5.10": + version "8.5.14" + resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz" + integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== + dependencies: + "@types/node" "*" + +abitype@1.0.8, abitype@^1.0.6: + version "1.0.8" + resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz" + integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1: + version "8.14.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +assert@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +bun-types@1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/bun-types/-/bun-types-1.2.3.tgz" + integrity sha512-P7AeyTseLKAvgaZqQrvp3RqFM3yN9PlcLuSTe7SoJOfZkER73mLdT2vEQi8U64S1YvM/ldcNiQjn0Sn7H9lGgg== + dependencies: + "@types/node" "*" + "@types/ws" "~8.5.10" + +bundle-require@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz" + integrity sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA== + dependencies: + load-tsconfig "^0.2.3" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz" + integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.3.0: + version "5.4.1" + resolved "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz" + integrity sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w== + +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + dependencies: + restore-cursor "^5.0.0" + +cli-spinners@^2.9.2: + version "2.9.2" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^13.1.0: + version "13.1.0" + resolved "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +consola@^3.4.0: + version "3.4.2" + resolved "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz" + integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz" + integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@^4.1.0, debug@^4.3.5, debug@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + +deepmerge-ts@^7.1.0: + version "7.1.5" + resolved "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz" + integrity sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +detect-indent@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz" + integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dotenv@16.4.7: + version "16.4.7" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz" + integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +esbuild@^0.25.0: + version "0.25.5" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz" + integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.5" + "@esbuild/android-arm" "0.25.5" + "@esbuild/android-arm64" "0.25.5" + "@esbuild/android-x64" "0.25.5" + "@esbuild/darwin-arm64" "0.25.5" + "@esbuild/darwin-x64" "0.25.5" + "@esbuild/freebsd-arm64" "0.25.5" + "@esbuild/freebsd-x64" "0.25.5" + "@esbuild/linux-arm" "0.25.5" + "@esbuild/linux-arm64" "0.25.5" + "@esbuild/linux-ia32" "0.25.5" + "@esbuild/linux-loong64" "0.25.5" + "@esbuild/linux-mips64el" "0.25.5" + "@esbuild/linux-ppc64" "0.25.5" + "@esbuild/linux-riscv64" "0.25.5" + "@esbuild/linux-s390x" "0.25.5" + "@esbuild/linux-x64" "0.25.5" + "@esbuild/netbsd-arm64" "0.25.5" + "@esbuild/netbsd-x64" "0.25.5" + "@esbuild/openbsd-arm64" "0.25.5" + "@esbuild/openbsd-x64" "0.25.5" + "@esbuild/sunos-x64" "0.25.5" + "@esbuild/win32-arm64" "0.25.5" + "@esbuild/win32-ia32" "0.25.5" + "@esbuild/win32-x64" "0.25.5" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +ethers@^6.13.5: + version "6.13.5" + resolved "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz" + integrity sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + +eventemitter3@5.0.1, eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@^9.5.3: + version "9.6.0" + resolved "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz" + integrity sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw== + dependencies: + "@sindresorhus/merge-streams" "^4.0.0" + cross-spawn "^7.0.6" + figures "^6.1.0" + get-stream "^9.0.0" + human-signals "^8.0.1" + is-plain-obj "^4.1.0" + is-stream "^4.0.1" + npm-run-path "^6.0.0" + pretty-ms "^9.2.0" + signal-exit "^4.1.0" + strip-final-newline "^4.0.0" + yoctocolors "^2.1.1" + +fdir@^6.4.4: + version "6.4.4" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz" + integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +figures@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz" + integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== + dependencies: + is-unicode-supported "^2.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +fix-dts-default-cjs-exports@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz" + integrity sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg== + dependencies: + magic-string "^0.30.17" + mlly "^1.7.4" + rollup "^4.34.8" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +for-each@^0.3.3: + version "0.3.5" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fs.promises.exists@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/fs.promises.exists/-/fs.promises.exists-1.1.4.tgz" + integrity sha512-lJzUGWbZn8vhGWBedA+RYjB/BeJ+3458ljUfmplqhIeb6ewzTFWNPCR1HCiYCkXV9zxcHz9zXkJzMsEgDLzh3Q== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-east-asian-width@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz" + integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz" + integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== + dependencies: + "@sec-ant/readable-stream" "^0.4.1" + is-stream "^4.0.1" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^10.3.10, glob@^10.4.5: + version "10.4.5" + resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hosted-git-info@^7.0.0: + version "7.0.2" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz" + integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== + dependencies: + lru-cache "^10.0.1" + +human-signals@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz" + integrity sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +index-to-position@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz" + integrity sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg== + +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arguments@^1.0.4: + version "1.2.0" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.1.0" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== + dependencies: + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz" + integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== + +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^4.0.0, is-plain-obj@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz" + integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== + +is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-unicode-supported@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz" + integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== + +is-unicode-supported@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz" + integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +lilconfig@^3.1.1: + version "3.1.3" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-tsconfig@^0.2.3: + version "0.2.5" + resolved "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz" + integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-symbols@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz" + integrity sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw== + dependencies: + chalk "^5.3.0" + is-unicode-supported "^1.3.0" + +loupe@^3.1.0: + version "3.1.3" + resolved "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz" + integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== + +lru-cache@^10.0.1, lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +micro-sr25519@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/micro-sr25519/-/micro-sr25519-0.1.0.tgz" + integrity sha512-at5zfxiKNhh07v4GPb8Sc6wCW+jd18FMMgPM0ACIQMcgvMfB9a34mfOlXr5B04J4yFZ6imlvJfRaFbOxMA7ytw== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + +minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mlly@^1.7.4: + version "1.7.4" + resolved "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz" + integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + dependencies: + acorn "^8.14.0" + pathe "^2.0.1" + pkg-types "^1.3.0" + ufo "^1.5.4" + +mocha@^11.1.0: + version "11.1.0" + resolved "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz" + integrity sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +mock-socket@^9.3.1: + version "9.3.1" + resolved "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz" + integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.8: + version "3.3.8" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + +nock@^13.5.5: + version "13.5.6" + resolved "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz" + integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +normalize-package-data@^6.0.0: + version "6.0.2" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz" + integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== + dependencies: + hosted-git-info "^7.0.0" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz" + integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + dependencies: + path-key "^4.0.0" + unicorn-magic "^0.3.0" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.7" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + +ora@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz" + integrity sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw== + dependencies: + chalk "^5.3.0" + cli-cursor "^5.0.0" + cli-spinners "^2.9.2" + is-interactive "^2.0.0" + is-unicode-supported "^2.0.0" + log-symbols "^6.0.0" + stdin-discarder "^0.2.2" + string-width "^7.2.0" + strip-ansi "^7.1.0" + +ox@0.6.7: + version "0.6.7" + resolved "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz" + integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parse-json@^8.0.0: + version "8.3.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz" + integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== + dependencies: + "@babel/code-frame" "^7.26.2" + index-to-position "^1.1.0" + type-fest "^4.39.1" + +parse-ms@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz" + integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +pathe@^2.0.1: + version "2.0.3" + resolved "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pirates@^4.0.1: + version "4.0.7" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkg-types@^1.3.0: + version "1.3.1" + resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +polkadot-api@^1.9.5: + version "1.12.0" + resolved "https://registry.npmjs.org/polkadot-api/-/polkadot-api-1.12.0.tgz" + integrity sha512-CstKp0ySE3JRVnG4nzl6hDhYLf4Qs/XpVk1xJrypYMqVbTu8FwjBK3l3j4pHhEttVudlEjK2hoVzQ1MdxMLeEg== + dependencies: + "@polkadot-api/cli" "0.13.0" + "@polkadot-api/ink-contracts" "0.3.2" + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/known-chains" "0.7.6" + "@polkadot-api/logs-provider" "0.0.6" + "@polkadot-api/metadata-builders" "0.12.1" + "@polkadot-api/metadata-compatibility" "0.2.3" + "@polkadot-api/observable-client" "0.11.0" + "@polkadot-api/pjs-signer" "0.6.8" + "@polkadot-api/polkadot-sdk-compat" "2.3.2" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signer" "0.2.1" + "@polkadot-api/sm-provider" "0.1.7" + "@polkadot-api/smoldot" "0.3.8" + "@polkadot-api/substrate-bindings" "0.13.0" + "@polkadot-api/substrate-client" "0.3.0" + "@polkadot-api/utils" "0.1.2" + "@polkadot-api/ws-provider" "0.4.0" + "@rx-state/core" "^0.1.4" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss-load-config@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + +postcss@^8.4.43: + version "8.5.3" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prettier@^3.3.3: + version "3.5.2" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz" + integrity sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg== + +pretty-ms@^9.2.0: + version "9.2.0" + resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz" + integrity sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg== + dependencies: + parse-ms "^4.0.0" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +read-pkg@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz" + integrity sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA== + dependencies: + "@types/normalize-package-data" "^2.4.3" + normalize-package-data "^6.0.0" + parse-json "^8.0.0" + type-fest "^4.6.0" + unicorn-magic "^0.1.0" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + +rollup@^4.20.0, rollup@^4.34.8: + version "4.34.8" + resolved "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz" + integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== + dependencies: + "@types/estree" "1.0.6" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.34.8" + "@rollup/rollup-android-arm64" "4.34.8" + "@rollup/rollup-darwin-arm64" "4.34.8" + "@rollup/rollup-darwin-x64" "4.34.8" + "@rollup/rollup-freebsd-arm64" "4.34.8" + "@rollup/rollup-freebsd-x64" "4.34.8" + "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" + "@rollup/rollup-linux-arm-musleabihf" "4.34.8" + "@rollup/rollup-linux-arm64-gnu" "4.34.8" + "@rollup/rollup-linux-arm64-musl" "4.34.8" + "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" + "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" + "@rollup/rollup-linux-riscv64-gnu" "4.34.8" + "@rollup/rollup-linux-s390x-gnu" "4.34.8" + "@rollup/rollup-linux-x64-gnu" "4.34.8" + "@rollup/rollup-linux-x64-musl" "4.34.8" + "@rollup/rollup-win32-arm64-msvc" "4.34.8" + "@rollup/rollup-win32-ia32-msvc" "4.34.8" + "@rollup/rollup-win32-x64-msvc" "4.34.8" + fsevents "~2.3.2" + +rxjs@^7.8.1, rxjs@^7.8.2: + version "7.8.2" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +scale-ts@^1.6.0, scale-ts@^1.6.1: + version "1.6.1" + resolved "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz" + integrity sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g== + +semver@^7.3.5: + version "7.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +smoldot@2.0.26: + version "2.0.26" + resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + +smoldot@2.0.34: + version "2.0.34" + resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.34.tgz" + integrity sha512-mw9tCbGEhEp0koMqLL0jBEixVY1MIN/xI3pE6ZY1TuOPU+LnYy8FloODVyzkvzQPaBYrETXJdRlmA/+k6g3gow== + dependencies: + ws "^8.8.1" + +sort-keys@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz" + integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ== + dependencies: + is-plain-obj "^4.0.0" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map@0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" + +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.21" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz" + integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg== + +stdin-discarder@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz" + integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string-width@^7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1, strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz" + integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +sucrase@^3.35.0: + version "3.35.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.11: + version "0.2.14" + resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz" + integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== + dependencies: + punycode "^2.1.0" + +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsc-prog@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/tsc-prog/-/tsc-prog-2.3.0.tgz" + integrity sha512-ycET2d75EgcX7y8EmG4KiZkLAwUzbY4xRhA6NU0uVbHkY4ZjrAAuzTMxXI85kOwATqPnBI5C/7y7rlpY0xdqHA== + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.1.0, tslib@^2.7.0, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsup@^8.4.0: + version "8.5.0" + resolved "https://registry.npmjs.org/tsup/-/tsup-8.5.0.tgz" + integrity sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ== + dependencies: + bundle-require "^5.1.0" + cac "^6.7.14" + chokidar "^4.0.3" + consola "^3.4.0" + debug "^4.4.0" + esbuild "^0.25.0" + fix-dts-default-cjs-exports "^1.0.0" + joycon "^3.1.1" + picocolors "^1.1.1" + postcss-load-config "^6.0.1" + resolve-from "^5.0.0" + rollup "^4.34.8" + source-map "0.8.0-beta.0" + sucrase "^3.35.0" + tinyexec "^0.3.2" + tinyglobby "^0.2.11" + tree-kill "^1.2.2" + +type-fest@^4.23.0, type-fest@^4.39.1, type-fest@^4.6.0: + version "4.41.0" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +typescript@^5.7.2, typescript@^5.8.3: + version "5.8.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +ufo@^1.5.4: + version "1.6.1" + resolved "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +unicorn-magic@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz" + integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== + +unicorn-magic@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz" + integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + +util@^0.12.5: + version "0.12.5" + resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validate-npm-package-license@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +viem@2.23.4: + version "2.23.4" + resolved "https://registry.npmjs.org/viem/-/viem-2.23.4.tgz" + integrity sha512-UQquuolKlS1w5H5e0Fd1KKoUlIPJryIEBzY5AUhGyV1ka+9O6+3uYVhUzj6RbvGK0PtsMKn2ddwPZFwjNDVU/A== + dependencies: + "@noble/curves" "1.8.1" + "@noble/hashes" "1.7.1" + "@scure/bip32" "1.6.2" + "@scure/bip39" "1.5.4" + abitype "1.0.8" + isows "1.0.6" + ox "0.6.7" + ws "8.18.0" + +vite@^5.4.8: + version "5.4.14" + resolved "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz" + integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-typed-array@^1.1.16, which-typed-array@^1.1.2: + version "1.1.18" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz" + integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" + for-each "^0.3.3" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +write-json-file@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/write-json-file/-/write-json-file-6.0.0.tgz" + integrity sha512-MNHcU3f9WxnNyR6MxsYSj64Jz0+dwIpisWKWq9gqLj/GwmA9INg3BZ3vt70/HB3GEwrnDQWr4RPrywnhNzmUFA== + dependencies: + detect-indent "^7.0.1" + is-plain-obj "^4.1.0" + sort-keys "^5.0.0" + write-file-atomic "^5.0.1" + +write-package@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/write-package/-/write-package-7.1.0.tgz" + integrity sha512-DqUx8GI3r9BFWwU2DPKddL1E7xWfbFED82mLVhGXKlFEPe8IkBftzO7WfNwHtk7oGDHDeuH/o8VMpzzfMwmLUA== + dependencies: + deepmerge-ts "^7.1.0" + read-pkg "^9.0.1" + sort-keys "^5.0.0" + type-fest "^4.23.0" + write-json-file "^6.0.0" + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@8.18.0: + version "8.18.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +ws@^8.18.0, ws@^8.18.1, ws@^8.18.2, ws@^8.8.1: + version "8.18.2" + resolved "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz" + integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yoctocolors@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz" + integrity sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ== diff --git a/hyperparameters.md b/hyperparameters.md index 31d7261608..2d69a1f378 100644 --- a/hyperparameters.md +++ b/hyperparameters.md @@ -7,7 +7,7 @@ TxRateLimit: u64 = 1; // [1 @ 64,888] ### netuid 1 (text_prompting) ```rust Rho: u16 = 10; -AlphaSigmoidSteepness: u16 = 10.0 +AlphaSigmoidSteepness: i16 = 1000 Kappa: u16 = 32_767; // 0.5 = 65535/2 MaxAllowedUids: u16 = 1024; Issuance: u64 = 0; @@ -48,7 +48,7 @@ WeightsSetRateLimit: u64 = 100; ### netuid 3 (causallmnext) ```rust Rho: u16 = 10; -AlphaSigmoidSteepness: u16 = 10.0 +AlphaSigmoidSteepness: i16 = 1000 Kappa: u16 = 32_767; // 0.5 = 65535/2 MaxAllowedUids: u16 = 4096; Issuance: u64 = 0; diff --git a/node/Cargo.toml b/node/Cargo.toml index 52ccf20de3..0ee30ab9f3 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -67,6 +67,7 @@ pallet-commitments = { path = "../pallets/commitments" } pallet-drand = { workspace = true } sp-crypto-ec-utils = { workspace = true } sp-keystore = { workspace = true, default-features = false } +cumulus-primitives-proof-size-hostfunction = { workspace = true, default-features = false } # These dependencies are used for the subtensor's RPCs @@ -110,6 +111,8 @@ node-subtensor-runtime = { workspace = true, features = ["std"] } subtensor-runtime-common = { workspace = true, features = ["std"] } subtensor-custom-rpc = { workspace = true, features = ["std"] } subtensor-custom-rpc-runtime-api = { workspace = true, features = ["std"] } +pallet-subtensor-swap-rpc = { workspace = true, features = ["std"] } +pallet-subtensor-swap-runtime-api = { workspace = true, features = ["std"] } [build-dependencies] substrate-build-script-utils = { workspace = true } @@ -136,6 +139,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "pallet-commitments/runtime-benchmarks", "pallet-drand/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", ] pow-faucet = [] diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index 40031ac1aa..1590422c08 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -123,7 +123,7 @@ pub fn create_benchmark_extrinsic( .checked_next_power_of_two() .map(|c| c / 2) .unwrap_or(2) as u64; - let extra: runtime::SignedExtra = ( + let extra: runtime::TransactionExtensions = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -135,8 +135,7 @@ pub fn create_benchmark_extrinsic( check_nonce::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - pallet_subtensor::SubtensorSignedExtension::::new(), - pallet_commitments::CommitmentsSignedExtension::::new(), + pallet_subtensor::SubtensorTransactionExtension::::new(), frame_metadata_hash_extension::CheckMetadataHash::::new(true), ); @@ -153,7 +152,6 @@ pub fn create_benchmark_extrinsic( (), (), (), - (), None, ), ); diff --git a/node/src/client.rs b/node/src/client.rs index 1c2503f21b..59f6470a5b 100644 --- a/node/src/client.rs +++ b/node/src/client.rs @@ -1,3 +1,4 @@ +use cumulus_primitives_proof_size_hostfunction::storage_proof_size::HostFunctions as ProofSize; use node_subtensor_runtime::{RuntimeApi, opaque::Block}; use sc_executor::WasmExecutor; @@ -14,5 +15,6 @@ pub type HostFunctions = ( sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions, sp_crypto_ec_utils::bls12_381::host_calls::HostFunctions, + ProofSize, ); pub type RuntimeExecutor = WasmExecutor; diff --git a/node/src/command.rs b/node/src/command.rs index aea800596e..e2df46844f 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -196,11 +196,12 @@ pub fn run() -> sc_cli::Result<()> { let ext_builder = RemarkBuilder::new(client.clone()); cmd.run( - config, + config.chain_spec.name().into(), client, inherent_benchmark_data()?, Vec::new(), &ext_builder, + false, ) } BenchmarkCmd::Extrinsic(cmd) => { diff --git a/node/src/ethereum.rs b/node/src/ethereum.rs index c708efd714..9179f30598 100644 --- a/node/src/ethereum.rs +++ b/node/src/ethereum.rs @@ -17,10 +17,9 @@ use sc_client_api::client::BlockchainEvents; use sc_network_sync::SyncingService; use sc_rpc::SubscriptionTaskExecutor; use sc_service::{Configuration, TaskManager, error::Error as ServiceError}; -use sc_transaction_pool::ChainApi; use sc_transaction_pool_api::TransactionPool; use sp_inherents::CreateInherentDataProviders; -use sp_runtime::traits::Block as BlockT; +use sp_runtime::{OpaqueExtrinsic, traits::BlakeTwo256, traits::Block as BlockT}; use std::path::PathBuf; use std::time::Duration; use std::{ @@ -196,13 +195,18 @@ pub async fn spawn_frontier_tasks( ); } -fn extend_rpc_aet_api( +fn extend_rpc_aet_api( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, CIDP: CreateInherentDataProviders + Send + Clone + 'static, EC: EthConfig, @@ -213,7 +217,7 @@ where } io.merge( - Eth::::new( + Eth::::new( deps.client.clone(), deps.pool.clone(), deps.graph.clone(), @@ -239,13 +243,18 @@ where Ok(()) } -fn extend_rpc_eth_filter( +fn extend_rpc_eth_filter( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, CIDP: CreateInherentDataProviders + Send + Clone + 'static, { @@ -267,9 +276,9 @@ where } // Function for EthPubSub merge -fn extend_rpc_eth_pubsub( +fn extend_rpc_eth_pubsub( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, subscription_task_executor: SubscriptionTaskExecutor, pubsub_notification_sinks: Arc< fc_mapping_sync::EthereumBlockNotificationSinks< @@ -278,8 +287,13 @@ fn extend_rpc_eth_pubsub( >, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, CIDP: CreateInherentDataProviders + Send + 'static, { @@ -297,13 +311,18 @@ where Ok(()) } -fn extend_rpc_net( +fn extend_rpc_net( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, CIDP: CreateInherentDataProviders + Send + 'static, { @@ -318,13 +337,18 @@ where Ok(()) } -fn extend_rpc_web3( +fn extend_rpc_web3( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, CIDP: CreateInherentDataProviders + Send + 'static, { @@ -332,13 +356,18 @@ where Ok(()) } -fn extend_rpc_debug( +fn extend_rpc_debug( io: &mut RpcModule<()>, - deps: &EthDeps, + deps: &EthDeps, ) -> Result<(), Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + 'static, CIDP: CreateInherentDataProviders + Send + 'static, { @@ -355,9 +384,9 @@ where } /// Extend RpcModule with Eth RPCs -pub fn create_eth( +pub fn create_eth( mut io: RpcModule<()>, - deps: EthDeps, + deps: EthDeps, subscription_task_executor: SubscriptionTaskExecutor, pubsub_notification_sinks: Arc< fc_mapping_sync::EthereumBlockNotificationSinks< @@ -366,23 +395,28 @@ pub fn create_eth( >, ) -> Result, Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CT: ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, CIDP: CreateInherentDataProviders + Send + Clone + 'static, EC: EthConfig, { - extend_rpc_aet_api::(&mut io, &deps)?; - extend_rpc_eth_filter::(&mut io, &deps)?; - extend_rpc_eth_pubsub::( + extend_rpc_aet_api::(&mut io, &deps)?; + extend_rpc_eth_filter::(&mut io, &deps)?; + extend_rpc_eth_pubsub::( &mut io, &deps, subscription_task_executor, pubsub_notification_sinks, )?; - extend_rpc_net::(&mut io, &deps)?; - extend_rpc_web3::(&mut io, &deps)?; - extend_rpc_debug::(&mut io, &deps)?; + extend_rpc_net::(&mut io, &deps)?; + extend_rpc_web3::(&mut io, &deps)?; + extend_rpc_debug::(&mut io, &deps)?; Ok(io) } diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 0d4cd355de..7f4f969bec 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -18,11 +18,10 @@ use sc_consensus_manual_seal::EngineCommand; use sc_network::service::traits::NetworkService; use sc_network_sync::SyncingService; use sc_rpc::SubscriptionTaskExecutor; -use sc_transaction_pool::{ChainApi, Pool}; use sc_transaction_pool_api::TransactionPool; use sp_core::H256; use sp_inherents::CreateInherentDataProviders; -use sp_runtime::traits::Block as BlockT; +use sp_runtime::{OpaqueExtrinsic, traits::BlakeTwo256, traits::Block as BlockT}; use subtensor_runtime_common::Hash; use crate::{ @@ -31,13 +30,13 @@ use crate::{ }; /// Extra dependencies for Ethereum compatibility. -pub struct EthDeps { +pub struct EthDeps { /// The client instance to use. pub client: Arc, /// Transaction pool instance. pub pool: Arc

, /// Graph pool instance. - pub graph: Arc>, + pub graph: Arc

, /// Ethereum transaction converter. pub converter: Option, /// The Node authority flag @@ -84,7 +83,7 @@ impl fc_rpc::EthConfig for DefaultEthConfig { } /// Full client dependencies. -pub struct FullDeps { +pub struct FullDeps { /// The client instance to use. pub client: Arc, /// Transaction pool instance. @@ -92,12 +91,12 @@ pub struct FullDeps { /// Manual seal command sink pub command_sink: Option>>, /// Ethereum-compatibility specific dependencies. - pub eth: EthDeps, + pub eth: EthDeps, } /// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, +pub fn create_full( + deps: FullDeps, subscription_task_executor: SubscriptionTaskExecutor, pubsub_notification_sinks: Arc< fc_mapping_sync::EthereumBlockNotificationSinks< @@ -106,11 +105,17 @@ pub fn create_full( >, ) -> Result, Box> where - P: TransactionPool + 'static, - A: ChainApi + 'static, + P: TransactionPool< + Block = Block, + Hash = , + OpaqueExtrinsic, + > as BlockT>::Hash, + > + 'static, CIDP: CreateInherentDataProviders + Send + Clone + 'static, CT: fp_rpc::ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, { + use pallet_subtensor_swap_rpc::{Swap, SwapRpcApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; use substrate_frame_rpc_system::{System, SystemApiServer}; @@ -127,6 +132,9 @@ where // Custom RPC methods for Paratensor module.merge(SubtensorCustom::new(client.clone()).into_rpc())?; + // Swap RPC + module.merge(Swap::new(client.clone()).into_rpc())?; + module.merge(System::new(client.clone(), pool.clone()).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; @@ -144,7 +152,7 @@ where } // Ethereum compatibility RPCs - let module = create_eth::<_, _, _, _, DefaultEthConfig>( + let module = create_eth::<_, _, _, DefaultEthConfig>( module, eth, subscription_task_executor, diff --git a/node/src/service.rs b/node/src/service.rs index 4ce041b0a4..26071c6d0c 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -13,7 +13,7 @@ use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; use sc_network_sync::strategy::warp::{WarpSyncConfig, WarpSyncProvider}; use sc_service::{Configuration, PartialComponents, TaskManager, error::Error as ServiceError}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, log}; -use sc_transaction_pool::FullPool; +use sc_transaction_pool::TransactionPoolHandle; use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder as BlockBuilderApi; @@ -51,7 +51,7 @@ pub fn new_partial( FullBackend, FullSelectChain, BasicQueue, - FullPool, + TransactionPoolHandle, ( Option, BoxBlockImport, @@ -148,12 +148,15 @@ where grandpa_block_import, )?; - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), + let transaction_pool = Arc::from( + sc_transaction_pool::Builder::new( + task_manager.spawn_essential_handle(), + client.clone(), + config.role.is_authority().into(), + ) + .with_options(config.transaction_pool.clone()) + .with_prometheus(config.prometheus_registry()) + .build(), ); Ok(PartialComponents { @@ -461,7 +464,7 @@ where network_provider: Arc::new(network.clone()), enable_http_requests: true, custom_extensions: |_| vec![], - }) + })? .run(client.clone(), task_manager.spawn_handle()) .boxed(), ); @@ -536,7 +539,7 @@ where let eth_deps = crate::rpc::EthDeps { client: client.clone(), pool: pool.clone(), - graph: pool.pool().clone(), + graph: pool.clone(), converter: Some(TransactionConverter::::default()), is_authority, enable_dev_signer, @@ -726,10 +729,14 @@ pub async fn build_full( sealing: Option, ) -> Result { match config.network.network_backend { - sc_network::config::NetworkBackendType::Libp2p => { + Some(sc_network::config::NetworkBackendType::Libp2p) => { new_full::>(config, eth_config, sealing).await } - sc_network::config::NetworkBackendType::Litep2p => { + Some(sc_network::config::NetworkBackendType::Litep2p) => { + new_full::(config, eth_config, sealing).await + } + _ => { + log::debug!("no network backend selected, falling back to libp2p"); new_full::>(config, eth_config, sealing).await } } @@ -764,7 +771,7 @@ pub fn new_chain_ops( fn run_manual_seal_authorship( sealing: Sealing, client: Arc, - transaction_pool: Arc>, + transaction_pool: Arc>, select_chain: FullSelectChain, block_import: BoxBlockImport, task_manager: &TaskManager, diff --git a/pallets/admin-utils/Cargo.toml b/pallets/admin-utils/Cargo.toml index b3c1410cca..1090c7e002 100644 --- a/pallets/admin-utils/Cargo.toml +++ b/pallets/admin-utils/Cargo.toml @@ -32,6 +32,8 @@ substrate-fixed = { workspace = true } pallet-evm-chain-id = { workspace = true } pallet-drand = { workspace = true, default-features = false } sp-consensus-grandpa = { workspace = true } +subtensor-swap-interface = { workspace = true } +subtensor-runtime-common = { workspace = true } [dev-dependencies] sp-core = { workspace = true } @@ -42,6 +44,7 @@ pallet-balances = { workspace = true, features = ["std"] } pallet-scheduler = { workspace = true } pallet-grandpa = { workspace = true } sp-std = { workspace = true } +pallet-subtensor-swap = { workspace = true } [features] default = ["std"] @@ -56,6 +59,7 @@ std = [ "pallet-evm-chain-id/std", "pallet-grandpa/std", "pallet-scheduler/std", + "pallet-subtensor-swap/std", "pallet-subtensor/std", "scale-info/std", "sp-consensus-aura/std", @@ -67,6 +71,8 @@ std = [ "sp-tracing/std", "sp-weights/std", "substrate-fixed/std", + "subtensor-swap-interface/std", + "subtensor-runtime-common/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -77,6 +83,7 @@ runtime-benchmarks = [ "pallet-grandpa/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-subtensor/runtime-benchmarks", + "pallet-subtensor-swap/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/pallets/admin-utils/src/benchmarking.rs b/pallets/admin-utils/src/benchmarking.rs index 022ea815f9..917d9008ba 100644 --- a/pallets/admin-utils/src/benchmarking.rs +++ b/pallets/admin-utils/src/benchmarking.rs @@ -57,183 +57,243 @@ mod benchmarks { #[benchmark] fn sudo_set_serving_rate_limit() { #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u64/*serving_rate_limit*/)/*sudo_set_serving_rate_limit*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u64/*serving_rate_limit*/)/*sudo_set_serving_rate_limit*/; } #[benchmark] fn sudo_set_max_difficulty() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 10000u64/*max_difficulty*/)/*sudo_set_max_difficulty*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 10000u64/*max_difficulty*/)/*sudo_set_max_difficulty*/; } #[benchmark] fn sudo_set_min_difficulty() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 1000u64/*min_difficulty*/)/*sudo_set_min_difficulty*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 1000u64/*min_difficulty*/)/*sudo_set_min_difficulty*/; } #[benchmark] fn sudo_set_weights_set_rate_limit() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 3u64/*rate_limit*/)/*sudo_set_weights_set_rate_limit*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 3u64/*rate_limit*/)/*sudo_set_weights_set_rate_limit*/; } #[benchmark] fn sudo_set_weights_version_key() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 1u64/*version_key*/)/*sudo_set_weights_version_key*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 1u64/*version_key*/)/*sudo_set_weights_version_key*/; } #[benchmark] fn sudo_set_bonds_moving_average() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u64/*bonds_moving_average*/)/*sudo_set_bonds_moving_average*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u64/*bonds_moving_average*/)/*sudo_set_bonds_moving_average*/; } #[benchmark] fn sudo_set_bonds_penalty() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u16/*bonds_penalty*/)/*sudo_set_bonds_penalty*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u16/*bonds_penalty*/)/*sudo_set_bonds_penalty*/; } #[benchmark] fn sudo_set_max_allowed_validators() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 10u16/*max_allowed_validators*/)/*sudo_set_max_allowed_validators*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 10u16/*max_allowed_validators*/)/*sudo_set_max_allowed_validators*/; } #[benchmark] fn sudo_set_difficulty() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 1200000u64/*difficulty*/)/*sudo_set_difficulty*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 1200000u64/*difficulty*/)/*sudo_set_difficulty*/; } #[benchmark] fn sudo_set_adjustment_interval() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 12u16/*adjustment_interval*/)/*sudo_set_adjustment_interval*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 12u16/*adjustment_interval*/)/*sudo_set_adjustment_interval*/; } #[benchmark] fn sudo_set_target_registrations_per_interval() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 300u16/*target_registrations*/)/*sudo_set_target_registrations_per_interval*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 300u16/*target_registrations*/)/*sudo_set_target_registrations_per_interval*/; } #[benchmark] fn sudo_set_activity_cutoff() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 361u16/*activity_cutoff*/)/*sudo_set_activity_cutoff*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 361u16/*activity_cutoff*/)/*sudo_set_activity_cutoff*/; } #[benchmark] fn sudo_set_rho() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 300u16/*rho*/)/*sudo_set_rho*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 300u16/*rho*/)/*sudo_set_rho*/; } #[benchmark] fn sudo_set_kappa() { pallet_subtensor::Pallet::::init_new_network( - 1u16, /*netuid*/ - 1u16, /*sudo_tempo*/ + 1u16.into(), /*netuid*/ + 1u16, /*sudo_tempo*/ ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 3u16/*kappa*/)/*set_kappa*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 3u16/*kappa*/)/*set_kappa*/; } #[benchmark] fn sudo_set_max_allowed_uids() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 4097u16/*max_allowed_uids*/)/*sudo_set_max_allowed_uids*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 4097u16/*max_allowed_uids*/)/*sudo_set_max_allowed_uids*/; } #[benchmark] fn sudo_set_min_allowed_weights() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 10u16/*max_allowed_uids*/)/*sudo_set_min_allowed_weights*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 10u16/*max_allowed_uids*/)/*sudo_set_min_allowed_weights*/; } #[benchmark] fn sudo_set_immunity_period() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u16/*immunity_period*/)/*sudo_set_immunity_period*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u16/*immunity_period*/)/*sudo_set_immunity_period*/; } #[benchmark] fn sudo_set_max_weight_limit() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u16/*max_weight_limit*/)/*sudo_set_max_weight_limit*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u16/*max_weight_limit*/)/*sudo_set_max_weight_limit*/; } #[benchmark] fn sudo_set_max_registrations_per_block() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 100u16/*max_registrations*/)/*sudo_set_max_registrations_per_block*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 100u16/*max_registrations*/)/*sudo_set_max_registrations_per_block*/; } #[benchmark] fn sudo_set_max_burn() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 10u64/*max_burn*/)/*sudo_set_max_burn*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 10u64/*max_burn*/)/*sudo_set_max_burn*/; } #[benchmark] fn sudo_set_min_burn() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 10u64/*min_burn*/)/*sudo_set_min_burn*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 10u64/*min_burn*/)/*sudo_set_min_burn*/; } #[benchmark] fn sudo_set_network_registration_allowed() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, true/*registration_allowed*/)/*sudo_set_network_registration_allowed*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, true/*registration_allowed*/)/*sudo_set_network_registration_allowed*/; } /* benchmark_sudo_set_tempo { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo_default: u16 = 1; <------- unused? let tempo: u16 = 15; let modality: u16 = 0; @@ -244,32 +304,35 @@ mod benchmarks { */ #[benchmark] fn sudo_set_tempo() { - pallet_subtensor::Pallet::::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/); + pallet_subtensor::Pallet::::init_new_network( + 1u16.into(), /*netuid*/ + 1u16, /*tempo*/ + ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 1u16/*tempo*/)/*sudo_set_tempo*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 1u16/*tempo*/)/*sudo_set_tempo*/; } #[benchmark] fn sudo_set_commit_reveal_weights_interval() { pallet_subtensor::Pallet::::init_new_network( - 1u16, /*netuid*/ - 1u16, /*sudo_tempo*/ + 1u16.into(), /*netuid*/ + 1u16, /*sudo_tempo*/ ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, 3u64/*interval*/)/*sudo_set_commit_reveal_weights_interval()*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 3u64/*interval*/)/*sudo_set_commit_reveal_weights_interval()*/; } #[benchmark] fn sudo_set_commit_reveal_weights_enabled() { pallet_subtensor::Pallet::::init_new_network( - 1u16, /*netuid*/ - 1u16, /*sudo_tempo*/ + 1u16.into(), /*netuid*/ + 1u16, /*sudo_tempo*/ ); #[extrinsic_call] - _(RawOrigin::Root, 1u16/*netuid*/, true/*enabled*/)/*set_commit_reveal_weights_enabled*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, true/*enabled*/)/*set_commit_reveal_weights_enabled*/; } //impl_benchmark_test_suite!(AdminUtils, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 2b41539816..b8859e66a9 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -31,6 +31,7 @@ pub mod pallet { use pallet_subtensor::utils::rate_limiting::TransactionType; use sp_runtime::BoundedVec; use substrate_fixed::types::I96F32; + use subtensor_runtime_common::NetUid; /// The main data structure of the module. #[pallet::pallet] @@ -80,10 +81,17 @@ pub mod pallet { /// Event emitted when the Yuma3 enable is toggled. Yuma3EnableToggled { /// The network identifier. - netuid: u16, + netuid: NetUid, /// Indicates if the Yuma3 enable was enabled or disabled. enabled: bool, }, + /// Event emitted when Bonds Reset is toggled. + BondsResetToggled { + /// The network identifier. + netuid: NetUid, + /// Indicates if the Bonds Reset was enabled or disabled. + enabled: bool, + }, } // Errors inform users that something went wrong. @@ -97,6 +105,8 @@ pub mod pallet { MaxAllowedUIdsLessThanCurrentUIds, /// The maximum value for bonds moving average is reached BondsMovingAverageMaxReached, + /// Only root can set negative sigmoid steepness values + NegativeSigmoidSteepness, } /// Enum for specifying the type of precompile operation. #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, Copy)] @@ -113,6 +123,8 @@ pub mod pallet { Neuron, /// Enum for UID lookup precompile UidLookup, + /// Enum for alpha precompile + Alpha, } #[pallet::type_value] @@ -139,9 +151,9 @@ pub mod pallet { /// It is only callable by the root account. /// The extrinsic will call the Aura pallet to change the authorities. #[pallet::call_index(0)] - #[pallet::weight(Weight::from_parts(6_265_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)))] + #[pallet::weight(Weight::from_parts(5_062_000, 0) + .saturating_add(::DbWeight::get().reads(0_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn swap_authorities( origin: OriginFor, new_authorities: BoundedVec<::AuthorityId, T::MaxAuthorities>, @@ -160,9 +172,9 @@ pub mod pallet { /// It is only callable by the root account. /// The extrinsic will call the Subtensor pallet to set the default take. #[pallet::call_index(1)] - #[pallet::weight(Weight::from_parts(6_942_000, 0) - .saturating_add(T::DbWeight::get().reads(0_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + #[pallet::weight(Weight::from_parts(5_831_000, 0) + .saturating_add(::DbWeight::get().reads(0_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_default_take(origin: OriginFor, default_take: u16) -> DispatchResult { ensure_root(origin)?; pallet_subtensor::Pallet::::set_max_delegate_take(default_take); @@ -187,11 +199,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the serving rate limit. #[pallet::call_index(3)] #[pallet::weight(Weight::from_parts(7_815_000, 0) - .saturating_add(T::DbWeight::get().reads(0_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(0_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_serving_rate_limit( origin: OriginFor, - netuid: u16, + netuid: NetUid, serving_rate_limit: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -209,11 +221,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the minimum difficulty. #[pallet::call_index(4)] #[pallet::weight(Weight::from_parts(19_780_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_min_difficulty( origin: OriginFor, - netuid: u16, + netuid: NetUid, min_difficulty: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -236,11 +248,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the maximum difficulty. #[pallet::call_index(5)] #[pallet::weight(Weight::from_parts(20_050_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_difficulty( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_difficulty: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -263,11 +275,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the weights version key. #[pallet::call_index(6)] #[pallet::weight(Weight::from_parts(19_990_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_weights_version_key( origin: OriginFor, - netuid: u16, + netuid: NetUid, weights_version_key: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin.clone(), netuid)?; @@ -313,11 +325,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the weights set rate limit. #[pallet::call_index(7)] #[pallet::weight(Weight::from_parts(20_050_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_weights_set_rate_limit( origin: OriginFor, - netuid: u16, + netuid: NetUid, weights_set_rate_limit: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -343,11 +355,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the adjustment interval. #[pallet::call_index(8)] #[pallet::weight(Weight::from_parts(20_010_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_adjustment_interval( origin: OriginFor, - netuid: u16, + netuid: NetUid, adjustment_interval: u16, ) -> DispatchResult { ensure_root(origin)?; @@ -371,14 +383,14 @@ pub mod pallet { #[pallet::call_index(9)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().reads(1)), + .saturating_add(::DbWeight::get().writes(1)) + .saturating_add(::DbWeight::get().reads(1)), DispatchClass::Operational, Pays::No ))] pub fn sudo_set_adjustment_alpha( origin: OriginFor, - netuid: u16, + netuid: NetUid, adjustment_alpha: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -400,11 +412,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the adjustment beta. #[pallet::call_index(12)] #[pallet::weight(Weight::from_parts(19_240_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_weight_limit( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_weight_limit: u16, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -427,11 +439,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the immunity period. #[pallet::call_index(13)] #[pallet::weight(Weight::from_parts(19_380_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_immunity_period( origin: OriginFor, - netuid: u16, + netuid: NetUid, immunity_period: u16, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -454,11 +466,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the minimum allowed weights. #[pallet::call_index(14)] #[pallet::weight(Weight::from_parts(19_770_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_min_allowed_weights( origin: OriginFor, - netuid: u16, + netuid: NetUid, min_allowed_weights: u16, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -481,11 +493,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the maximum allowed UIDs for a subnet. #[pallet::call_index(15)] #[pallet::weight(Weight::from_parts(23_820_000, 0) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(2_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_allowed_uids( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_allowed_uids: u16, ) -> DispatchResult { ensure_root(origin)?; @@ -511,9 +523,9 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the kappa. #[pallet::call_index(16)] #[pallet::weight(Weight::from_parts(19_590_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] - pub fn sudo_set_kappa(origin: OriginFor, netuid: u16, kappa: u16) -> DispatchResult { + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] + pub fn sudo_set_kappa(origin: OriginFor, netuid: NetUid, kappa: u16) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; ensure!( @@ -530,9 +542,9 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the rho. #[pallet::call_index(17)] #[pallet::weight(Weight::from_parts(16_420_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] - pub fn sudo_set_rho(origin: OriginFor, netuid: u16, rho: u16) -> DispatchResult { + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] + pub fn sudo_set_rho(origin: OriginFor, netuid: NetUid, rho: u16) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; ensure!( @@ -549,11 +561,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the activity cutoff. #[pallet::call_index(18)] #[pallet::weight(Weight::from_parts(22_600_000, 0) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(2_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_activity_cutoff( origin: OriginFor, - netuid: u16, + netuid: NetUid, activity_cutoff: u16, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -583,14 +595,14 @@ pub mod pallet { #[pallet::call_index(19)] #[pallet::weight(( Weight::from_parts(8_696_000, 0) - .saturating_add(T::DbWeight::get().reads(0)) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().reads(0)) + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] pub fn sudo_set_network_registration_allowed( origin: OriginFor, - netuid: u16, + netuid: NetUid, registration_allowed: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -612,13 +624,13 @@ pub mod pallet { #[pallet::call_index(20)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] pub fn sudo_set_network_pow_registration_allowed( origin: OriginFor, - netuid: u16, + netuid: NetUid, registration_allowed: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -639,11 +651,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the target registrations per interval. #[pallet::call_index(21)] #[pallet::weight(Weight::from_parts(19_830_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_target_registrations_per_interval( origin: OriginFor, - netuid: u16, + netuid: NetUid, target_registrations_per_interval: u16, ) -> DispatchResult { ensure_root(origin)?; @@ -669,11 +681,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the minimum burn. #[pallet::call_index(22)] #[pallet::weight(Weight::from_parts(19_840_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_min_burn( origin: OriginFor, - netuid: u16, + netuid: NetUid, min_burn: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -696,11 +708,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the maximum burn. #[pallet::call_index(23)] #[pallet::weight(Weight::from_parts(19_740_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_burn( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_burn: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -723,11 +735,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the difficulty. #[pallet::call_index(24)] #[pallet::weight(Weight::from_parts(20_280_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_difficulty( origin: OriginFor, - netuid: u16, + netuid: NetUid, difficulty: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -749,11 +761,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the maximum allowed validators. #[pallet::call_index(25)] #[pallet::weight(Weight::from_parts(25_210_000, 0) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(2_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_allowed_validators( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_allowed_validators: u16, ) -> DispatchResult { ensure_root(origin)?; @@ -784,11 +796,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the bonds moving average. #[pallet::call_index(26)] #[pallet::weight(Weight::from_parts(20_270_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_bonds_moving_average( origin: OriginFor, - netuid: u16, + netuid: NetUid, bonds_moving_average: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin.clone(), netuid)?; @@ -818,11 +830,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the bonds penalty. #[pallet::call_index(60)] #[pallet::weight(Weight::from_parts(20_030_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_bonds_penalty( origin: OriginFor, - netuid: u16, + netuid: NetUid, bonds_penalty: u16, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -845,11 +857,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the maximum registrations per block. #[pallet::call_index(27)] #[pallet::weight(Weight::from_parts(19_680_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_registrations_per_block( origin: OriginFor, - netuid: u16, + netuid: NetUid, max_registrations_per_block: u16, ) -> DispatchResult { ensure_root(origin)?; @@ -876,7 +888,7 @@ pub mod pallet { #[pallet::call_index(28)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -899,7 +911,7 @@ pub mod pallet { #[pallet::call_index(29)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -918,9 +930,9 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the tempo. #[pallet::call_index(30)] #[pallet::weight(Weight::from_parts(19_900_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] - pub fn sudo_set_tempo(origin: OriginFor, netuid: u16, tempo: u16) -> DispatchResult { + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] + pub fn sudo_set_tempo(origin: OriginFor, netuid: NetUid, tempo: u16) -> DispatchResult { ensure_root(origin)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -953,7 +965,7 @@ pub mod pallet { #[pallet::call_index(35)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -976,7 +988,7 @@ pub mod pallet { #[pallet::call_index(36)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -999,7 +1011,7 @@ pub mod pallet { #[pallet::call_index(37)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -1014,7 +1026,7 @@ pub mod pallet { #[pallet::call_index(38)] #[pallet::weight(( Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)), + .saturating_add(::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No ))] @@ -1038,7 +1050,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_rao_recycled( origin: OriginFor, - netuid: u16, + netuid: NetUid, rao_recycled: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -1076,7 +1088,7 @@ pub mod pallet { log::trace!("Setting minimum stake to: {}", min_stake); pallet_subtensor::Pallet::::set_nominator_min_required_stake(min_stake); if min_stake > prev_min_stake { - log::trace!("Clearing small nominations"); + log::trace!("Clearing small nominations if possible"); pallet_subtensor::Pallet::::clear_small_nominations(); log::trace!("Small nominations cleared"); } @@ -1138,11 +1150,11 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the value. #[pallet::call_index(49)] #[pallet::weight(Weight::from_parts(19_480_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_commit_reveal_weights_enabled( origin: OriginFor, - netuid: u16, + netuid: NetUid, enabled: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -1170,7 +1182,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_liquid_alpha_enabled( origin: OriginFor, - netuid: u16, + netuid: NetUid, enabled: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -1188,7 +1200,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_alpha_values( origin: OriginFor, - netuid: u16, + netuid: NetUid, alpha_low: u16, alpha_high: u16, ) -> DispatchResult { @@ -1246,7 +1258,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_network_max_stake( origin: OriginFor, - _netuid: u16, + _netuid: NetUid, _max_stake: u64, ) -> DispatchResult { // Ensure the call is made by the root account @@ -1339,11 +1351,11 @@ pub mod pallet { /// Weight is handled by the `#[pallet::weight]` attribute. #[pallet::call_index(57)] #[pallet::weight(Weight::from_parts(20_490_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_commit_reveal_weights_interval( origin: OriginFor, - netuid: u16, + netuid: NetUid, interval: u64, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -1375,8 +1387,8 @@ pub mod pallet { /// Weight is handled by the `#[pallet::weight]` attribute. #[pallet::call_index(58)] #[pallet::weight(Weight::from_parts(27_199_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_evm_chain_id(origin: OriginFor, chain_id: u64) -> DispatchResult { // Ensure the call is made by the root account ensure_root(origin)?; @@ -1401,9 +1413,9 @@ pub mod pallet { /// No change should be signaled while any change is pending. Returns an error if a change /// is already pending. #[pallet::call_index(59)] - #[pallet::weight(Weight::from_parts(11_550_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)))] + #[pallet::weight(Weight::from_parts(9_060_000, 0) + .saturating_add(::DbWeight::get().reads(1_u64)) + .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn schedule_grandpa_change( origin: OriginFor, // grandpa ID is always the same type, so we don't need to parametrize it via `Config` @@ -1415,7 +1427,7 @@ pub mod pallet { T::Grandpa::schedule_change(next_authorities, in_blocks, forced) } - /// Enables or disables Liquid Alpha for a given subnet. + /// Enable or disable atomic alpha transfers for a given subnet. /// /// # Parameters /// - `origin`: The origin of the call, which must be the root account or subnet owner. @@ -1428,7 +1440,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_toggle_transfer( origin: OriginFor, - netuid: u16, + netuid: NetUid, toggle: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -1502,8 +1514,8 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_subnet_owner_hotkey( origin: OriginFor, - netuid: u16, - hotkey: T::AccountId, + netuid: NetUid, + hotkey: ::AccountId, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner(origin.clone(), netuid)?; pallet_subtensor::Pallet::::set_subnet_owner_hotkey(netuid, &hotkey); @@ -1531,7 +1543,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_ema_price_halving_period( origin: OriginFor, - netuid: u16, + netuid: NetUid, ema_halving: u64, ) -> DispatchResult { ensure_root(origin)?; @@ -1550,20 +1562,36 @@ pub mod pallet { /// # Arguments /// * `origin` - The origin of the call, which must be the root account. /// * `netuid` - The unique identifier for the subnet. - /// * `steepness` - The new steepness for the alpha sigmoid function. + /// * `steepness` - The Steepness for the alpha sigmoid function. (range is 0-int16::MAX, + /// negative values are reserved for future use) /// /// # Errors /// * `BadOrigin` - If the caller is not the root account. + /// * `SubnetDoesNotExist` - If the specified subnet does not exist. + /// * `NegativeSigmoidSteepness` - If the steepness is negative and the caller is + /// root. /// # Weight /// Weight is handled by the `#[pallet::weight]` attribute. #[pallet::call_index(68)] #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_alpha_sigmoid_steepness( origin: OriginFor, - netuid: u16, - steepness: u16, + netuid: NetUid, + steepness: i16, ) -> DispatchResult { - ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin.clone(), netuid)?; + + ensure!( + pallet_subtensor::Pallet::::if_subnet_exist(netuid), + Error::::SubnetDoesNotExist + ); + + let is_root = ensure_root(origin).is_ok(); + ensure!( + is_root || steepness >= 0, + Error::::NegativeSigmoidSteepness + ); + pallet_subtensor::Pallet::::set_alpha_sigmoid_steepness(netuid, steepness); log::debug!( @@ -1587,7 +1615,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_yuma3_enabled( origin: OriginFor, - netuid: u16, + netuid: NetUid, enabled: bool, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; @@ -1602,6 +1630,34 @@ pub mod pallet { Ok(()) } + /// Enables or disables Bonds Reset for a given subnet. + /// + /// # Parameters + /// - `origin`: The origin of the call, which must be the root account or subnet owner. + /// - `netuid`: The unique identifier for the subnet. + /// - `enabled`: A boolean flag to enable or disable Bonds Reset. + /// + /// # Weight + /// This function has a fixed weight of 0 and is classified as an operational transaction that does not incur any fees. + #[pallet::call_index(70)] + #[pallet::weight((0, DispatchClass::Operational, Pays::No))] + pub fn sudo_set_bonds_reset_enabled( + origin: OriginFor, + netuid: NetUid, + enabled: bool, + ) -> DispatchResult { + pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; + pallet_subtensor::Pallet::::set_bonds_reset(netuid, enabled); + + Self::deposit_event(Event::BondsResetToggled { netuid, enabled }); + log::debug!( + "BondsResetToggled( netuid: {:?} bonds_reset: {:?} ) ", + netuid, + enabled + ); + Ok(()) + } + /// Sets or updates the hotkey account associated with the owner of a specific subnet. /// /// This function allows either the root origin or the current subnet owner to set or update @@ -1636,8 +1692,8 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_sn_owner_hotkey( origin: OriginFor, - netuid: u16, - hotkey: T::AccountId, + netuid: NetUid, + hotkey: ::AccountId, ) -> DispatchResult { pallet_subtensor::Pallet::::do_set_sn_owner_hotkey(origin, netuid, &hotkey) } @@ -1658,7 +1714,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_subtoken_enabled( origin: OriginFor, - netuid: u16, + netuid: NetUid, subtoken_enabled: bool, ) -> DispatchResult { ensure_root(origin)?; diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index f8b3e6a9b6..cfcee6de91 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -1,11 +1,12 @@ #![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] +use core::num::NonZeroU64; + use frame_support::{ - assert_ok, derive_impl, parameter_types, - traits::{Everything, Hooks, PrivilegeCmp}, - weights, + PalletId, assert_ok, derive_impl, parameter_types, + traits::{Everything, Hooks, InherentBuilder, PrivilegeCmp}, }; -use frame_system as system; +use frame_system::{self as system, offchain::CreateTransactionBase}; use frame_system::{EnsureNever, EnsureRoot, limits}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityList as GrandpaAuthorityList; @@ -18,6 +19,7 @@ use sp_runtime::{ }; use sp_std::cmp::Ordering; use sp_weights::Weight; +use subtensor_runtime_common::NetUid; type Block = frame_system::mocking::MockBlock; @@ -32,6 +34,7 @@ frame_support::construct_runtime!( Drand: pallet_drand::{Pallet, Call, Storage, Event} = 6, Grandpa: pallet_grandpa = 7, EVMChainId: pallet_evm_chain_id = 8, + Swap: pallet_subtensor_swap::{Pallet, Call, Storage, Event} = 9, } ); @@ -68,19 +71,21 @@ pub type Balance = u64; pub type BlockNumber = u64; pub type TestAuthId = test_crypto::TestAuthId; -pub type Index = u64; pub type UncheckedExtrinsic = TestXt; parameter_types! { pub const InitialMinAllowedWeights: u16 = 0; pub const InitialEmissionValue: u16 = 0; pub const InitialMaxWeightsLimit: u16 = u16::MAX; - pub BlockWeights: limits::BlockWeights = limits::BlockWeights::simple_max(weights::Weight::from_parts(1024, 0)); + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::with_sensible_defaults( + Weight::from_parts(2_000_000_000_000, u64::MAX), + Perbill::from_percent(75), + ); pub const ExistentialDeposit: Balance = 1; pub const TransactionByteFee: Balance = 100; pub const SDebug:u64 = 1; pub const InitialRho: u16 = 30; - pub const InitialAlphaSigmoidSteepness: u16 = 10; + pub const InitialAlphaSigmoidSteepness: i16 = 1000; pub const InitialKappa: u16 = 32_767; pub const InitialTempo: u16 = 0; pub const SelfOwnership: u64 = 2; @@ -140,6 +145,8 @@ parameter_types! { pub const InitialTaoWeight: u64 = u64::MAX/10; // 10% global weight. pub const InitialEmaPriceHalvingPeriod: u64 = 201_600_u64; // 4 weeks pub const DurationOfStartCall: u64 = 7 * 24 * 60 * 60 / 12; // 7 days + pub const InitialKeySwapOnSubnetCost: u64 = 10_000_000; + pub const HotkeySwapOnSubnetInterval: u64 = 7 * 24 * 60 * 60 / 12; // 7 days } impl pallet_subtensor::Config for Test { @@ -209,6 +216,9 @@ impl pallet_subtensor::Config for Test { type InitialTaoWeight = InitialTaoWeight; type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod; type DurationOfStartCall = DurationOfStartCall; + type SwapInterface = Swap; + type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost; + type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval; } #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] @@ -267,6 +277,27 @@ impl pallet_balances::Config for Test { type RuntimeHoldReason = (); } +// Swap-related parameter types +parameter_types! { + pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap"); + pub const SwapMaxFeeRate: u16 = 10000; // 15.26% + pub const SwapMaxPositions: u32 = 100; + pub const SwapMinimumLiquidity: u64 = 1_000; + pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(1_000_000).unwrap(); +} + +impl pallet_subtensor_swap::Config for Test { + type RuntimeEvent = RuntimeEvent; + type SubnetInfo = SubtensorModule; + type BalanceOps = SubtensorModule; + type ProtocolId = SwapProtocolId; + type MaxFeeRate = SwapMaxFeeRate; + type MaxPositions = SwapMaxPositions; + type MinimumLiquidity = SwapMinimumLiquidity; + type MinimumReserve = SwapMinimumReserve; + type WeightInfo = (); +} + pub struct OriginPrivilegeCmp; impl PrivilegeCmp for OriginPrivilegeCmp { @@ -361,26 +392,37 @@ mod test_crypto { } } -impl frame_system::offchain::CreateSignedTransaction> for Test { - fn create_transaction>( - call: RuntimeCall, - _public: Self::Public, - _account: Self::AccountId, - nonce: Index, - ) -> Option<( - RuntimeCall, - ::SignaturePayload, - )> { - Some((call, (nonce, ()))) +impl frame_system::offchain::CreateTransactionBase for Test +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateInherent for Test +where + RuntimeCall: From, +{ + fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic { + UncheckedExtrinsic::new_inherent(call) } } -impl frame_system::offchain::SendTransactionTypes for Test +impl frame_system::offchain::CreateSignedTransaction for Test where - RuntimeCall: From, + RuntimeCall: From, { - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; + fn create_signed_transaction< + C: frame_system::offchain::AppCrypto, + >( + call: >::RuntimeCall, + _public: Self::Public, + _account: Self::AccountId, + nonce: Self::Nonce, + ) -> Option { + Some(UncheckedExtrinsic::new_signed(call, nonce, (), ())) + } } // Build genesis storage according to the mock runtime. @@ -408,7 +450,7 @@ pub(crate) fn run_to_block(n: u64) { #[allow(dead_code)] pub fn register_ok_neuron( - netuid: u16, + netuid: NetUid, hotkey_account_id: U256, coldkey_account_id: U256, start_nonce: u64, @@ -439,7 +481,7 @@ pub fn register_ok_neuron( } #[allow(dead_code)] -pub fn add_network(netuid: u16, tempo: u16) { +pub fn add_network(netuid: NetUid, tempo: u16) { SubtensorModule::init_new_network(netuid, tempo); SubtensorModule::set_network_registration_allowed(netuid, true); SubtensorModule::set_network_pow_registration_allowed(netuid, true); diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index bb813ce117..260dc9f7c3 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -11,6 +11,7 @@ use pallet_subtensor::Event; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{Pair, U256, ed25519}; use substrate_fixed::types::I96F32; +use subtensor_runtime_common::NetUid; use crate::Error; use crate::pallet::PrecompileEnable; @@ -42,7 +43,7 @@ fn test_sudo_set_default_take() { #[test] fn test_sudo_set_serving_rate_limit() { new_test_ext().execute_with(|| { - let netuid: u16 = 3; + let netuid = NetUid::from(3); let to_be_set: u64 = 10; let init_value: u64 = SubtensorModule::get_serving_rate_limit(netuid); assert_eq!( @@ -66,7 +67,7 @@ fn test_sudo_set_serving_rate_limit() { #[test] fn test_sudo_set_min_difficulty() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_min_difficulty(netuid); @@ -81,7 +82,7 @@ fn test_sudo_set_min_difficulty() { assert_eq!( AdminUtils::sudo_set_min_difficulty( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -99,7 +100,7 @@ fn test_sudo_set_min_difficulty() { #[test] fn test_sudo_set_max_difficulty() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_max_difficulty(netuid); @@ -114,7 +115,7 @@ fn test_sudo_set_max_difficulty() { assert_eq!( AdminUtils::sudo_set_max_difficulty( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -132,7 +133,7 @@ fn test_sudo_set_max_difficulty() { #[test] fn test_sudo_set_weights_version_key() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_weights_version_key(netuid); @@ -147,7 +148,7 @@ fn test_sudo_set_weights_version_key() { assert_eq!( AdminUtils::sudo_set_weights_version_key( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -165,7 +166,7 @@ fn test_sudo_set_weights_version_key() { #[test] fn test_sudo_set_weights_version_key_rate_limit() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; let sn_owner = U256::from(1); @@ -228,7 +229,7 @@ fn test_sudo_set_weights_version_key_rate_limit() { fn test_sudo_set_weights_version_key_rate_limit_root() { // root should not be effected by rate limit new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; let sn_owner = U256::from(1); @@ -266,7 +267,7 @@ fn test_sudo_set_weights_version_key_rate_limit_root() { #[test] fn test_sudo_set_weights_set_rate_limit() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_weights_set_rate_limit(netuid); @@ -281,7 +282,7 @@ fn test_sudo_set_weights_set_rate_limit() { assert_eq!( AdminUtils::sudo_set_weights_set_rate_limit( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -305,7 +306,7 @@ fn test_sudo_set_weights_set_rate_limit() { #[test] fn test_sudo_set_adjustment_interval() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_adjustment_interval(netuid); @@ -320,7 +321,7 @@ fn test_sudo_set_adjustment_interval() { assert_eq!( AdminUtils::sudo_set_adjustment_interval( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -338,7 +339,7 @@ fn test_sudo_set_adjustment_interval() { #[test] fn test_sudo_set_adjustment_alpha() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_adjustment_alpha(netuid); @@ -353,7 +354,7 @@ fn test_sudo_set_adjustment_alpha() { assert_eq!( AdminUtils::sudo_set_adjustment_alpha( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -392,7 +393,7 @@ fn test_sudo_subnet_owner_cut() { #[test] fn test_sudo_set_max_weight_limit() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_max_weight_limit(netuid); @@ -407,7 +408,7 @@ fn test_sudo_set_max_weight_limit() { assert_eq!( AdminUtils::sudo_set_max_weight_limit( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -444,7 +445,7 @@ fn test_sudo_set_issuance() { #[test] fn test_sudo_set_immunity_period() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_immunity_period(netuid); @@ -459,7 +460,7 @@ fn test_sudo_set_immunity_period() { assert_eq!( AdminUtils::sudo_set_immunity_period( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -477,7 +478,7 @@ fn test_sudo_set_immunity_period() { #[test] fn test_sudo_set_min_allowed_weights() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_min_allowed_weights(netuid); @@ -492,7 +493,7 @@ fn test_sudo_set_min_allowed_weights() { assert_eq!( AdminUtils::sudo_set_min_allowed_weights( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -510,7 +511,7 @@ fn test_sudo_set_min_allowed_weights() { #[test] fn test_sudo_set_max_allowed_uids() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); @@ -525,7 +526,7 @@ fn test_sudo_set_max_allowed_uids() { assert_eq!( AdminUtils::sudo_set_max_allowed_uids( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -543,7 +544,7 @@ fn test_sudo_set_max_allowed_uids() { #[test] fn test_sudo_set_and_decrease_max_allowed_uids() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); @@ -558,7 +559,7 @@ fn test_sudo_set_and_decrease_max_allowed_uids() { assert_eq!( AdminUtils::sudo_set_max_allowed_uids( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -580,7 +581,7 @@ fn test_sudo_set_and_decrease_max_allowed_uids() { #[test] fn test_sudo_set_kappa() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_kappa(netuid); @@ -595,7 +596,7 @@ fn test_sudo_set_kappa() { assert_eq!( AdminUtils::sudo_set_kappa( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -613,7 +614,7 @@ fn test_sudo_set_kappa() { #[test] fn test_sudo_set_rho() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_rho(netuid); @@ -628,7 +629,7 @@ fn test_sudo_set_rho() { assert_eq!( AdminUtils::sudo_set_rho( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -646,7 +647,7 @@ fn test_sudo_set_rho() { #[test] fn test_sudo_set_activity_cutoff() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = pallet_subtensor::MinActivityCutoff::::get(); add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_activity_cutoff(netuid); @@ -661,7 +662,7 @@ fn test_sudo_set_activity_cutoff() { assert_eq!( AdminUtils::sudo_set_activity_cutoff( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -679,7 +680,7 @@ fn test_sudo_set_activity_cutoff() { #[test] fn test_sudo_set_target_registrations_per_interval() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_target_registrations_per_interval(netuid); @@ -694,7 +695,7 @@ fn test_sudo_set_target_registrations_per_interval() { assert_eq!( AdminUtils::sudo_set_target_registrations_per_interval( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -718,7 +719,7 @@ fn test_sudo_set_target_registrations_per_interval() { #[test] fn test_sudo_set_difficulty() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_difficulty_as_u64(netuid); @@ -733,7 +734,7 @@ fn test_sudo_set_difficulty() { assert_eq!( AdminUtils::sudo_set_difficulty( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -763,7 +764,7 @@ fn test_sudo_set_difficulty() { #[test] fn test_sudo_set_max_allowed_validators() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_max_allowed_validators(netuid); @@ -778,7 +779,7 @@ fn test_sudo_set_max_allowed_validators() { assert_eq!( AdminUtils::sudo_set_max_allowed_validators( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -823,7 +824,7 @@ fn test_sudo_set_stake_threshold() { #[test] fn test_sudo_set_bonds_moving_average() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_bonds_moving_average(netuid); @@ -838,7 +839,7 @@ fn test_sudo_set_bonds_moving_average() { assert_eq!( AdminUtils::sudo_set_bonds_moving_average( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -859,7 +860,7 @@ fn test_sudo_set_bonds_moving_average() { #[test] fn test_sudo_set_bonds_penalty() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u16 = 10; add_network(netuid, 10); let init_value: u16 = SubtensorModule::get_bonds_penalty(netuid); @@ -874,7 +875,7 @@ fn test_sudo_set_bonds_penalty() { assert_eq!( AdminUtils::sudo_set_bonds_penalty( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -892,7 +893,7 @@ fn test_sudo_set_bonds_penalty() { #[test] fn test_sudo_set_rao_recycled() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); let init_value: u64 = SubtensorModule::get_rao_recycled(netuid); @@ -911,7 +912,7 @@ fn test_sudo_set_rao_recycled() { assert_eq!( AdminUtils::sudo_set_rao_recycled( <::RuntimeOrigin>::root(), - netuid + 1, + netuid.next(), to_be_set ), Err(Error::::SubnetDoesNotExist.into()) @@ -954,7 +955,7 @@ fn test_sudo_set_rao_recycled() { #[test] fn test_sudo_set_network_lock_reduction_interval() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 7200; add_network(netuid, 10); @@ -978,7 +979,7 @@ fn test_sudo_set_network_lock_reduction_interval() { #[test] fn test_sudo_set_network_pow_registration_allowed() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: bool = true; add_network(netuid, 10); @@ -1108,7 +1109,7 @@ fn test_sudo_set_min_delegate_take() { #[test] fn test_sudo_set_commit_reveal_weights_enabled() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 10); let to_be_set: bool = true; @@ -1131,7 +1132,7 @@ fn test_sudo_set_commit_reveal_weights_enabled() { #[test] fn test_sudo_set_liquid_alpha_enabled() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let enabled: bool = true; assert_eq!(!enabled, SubtensorModule::get_liquid_alpha_enabled(netuid)); @@ -1145,11 +1146,70 @@ fn test_sudo_set_liquid_alpha_enabled() { }); } +#[test] +fn test_sudo_set_alpha_sigmoid_steepness() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let to_be_set: i16 = 5000; + add_network(netuid, 10); + let init_value = SubtensorModule::get_alpha_sigmoid_steepness(netuid); + assert_eq!( + AdminUtils::sudo_set_alpha_sigmoid_steepness( + <::RuntimeOrigin>::signed(U256::from(1)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin) + ); + assert_eq!( + AdminUtils::sudo_set_alpha_sigmoid_steepness( + <::RuntimeOrigin>::root(), + netuid.next(), + to_be_set + ), + Err(Error::::SubnetDoesNotExist.into()) + ); + + let owner = U256::from(10); + pallet_subtensor::SubnetOwner::::insert(netuid, owner); + assert_eq!( + AdminUtils::sudo_set_alpha_sigmoid_steepness( + <::RuntimeOrigin>::signed(owner), + netuid, + -to_be_set + ), + Err(Error::::NegativeSigmoidSteepness.into()) + ); + assert_eq!( + SubtensorModule::get_alpha_sigmoid_steepness(netuid), + init_value + ); + assert_ok!(AdminUtils::sudo_set_alpha_sigmoid_steepness( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_alpha_sigmoid_steepness(netuid), + to_be_set + ); + assert_ok!(AdminUtils::sudo_set_alpha_sigmoid_steepness( + <::RuntimeOrigin>::root(), + netuid, + -to_be_set + )); + assert_eq!( + SubtensorModule::get_alpha_sigmoid_steepness(netuid), + -to_be_set + ); + }); +} + #[test] fn test_set_alpha_values_dispatch_info_ok() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; - let alpha_low: u16 = 12_u16; + let netuid = NetUid::from(1); + let alpha_low: u16 = 1638_u16; let alpha_high: u16 = u16::MAX - 10; let call = RuntimeCall::AdminUtils(crate::Call::sudo_set_alpha_values { netuid, @@ -1167,8 +1227,8 @@ fn test_set_alpha_values_dispatch_info_ok() { #[test] fn test_sudo_get_set_alpha() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; - let alpha_low: u16 = 12_u16; + let netuid = NetUid::from(1); + let alpha_low: u16 = 1638_u16; let alpha_high: u16 = u16::MAX - 10; let hotkey: U256 = U256::from(1); @@ -1251,7 +1311,7 @@ fn test_sudo_get_set_alpha() { )); // 2. Alpha high too low - let alpha_high_too_low = (u16::MAX as u32 * 4 / 5) as u16 - 1; // One less than the minimum acceptable value + let alpha_high_too_low = (u16::MAX as u32 / 40) as u16 - 1; // One less than the minimum acceptable value assert_err!( AdminUtils::sudo_set_alpha_values( signer.clone(), @@ -1288,7 +1348,7 @@ fn test_sudo_get_set_alpha() { alpha_high )); - let alpha_low_too_high = (u16::MAX as u32 * 4 / 5) as u16 + 1; // One more than the maximum acceptable value + let alpha_low_too_high = alpha_high + 1; assert_err!( AdminUtils::sudo_set_alpha_values( signer.clone(), @@ -1385,7 +1445,7 @@ fn test_sudo_set_dissolve_network_schedule_duration() { #[test] fn sudo_set_commit_reveal_weights_interval() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 10); let to_be_set = 55; @@ -1565,7 +1625,7 @@ fn test_sets_a_lower_value_clears_small_nominations() { assert!(to_stake < nominator_min_required_stake_1); // Should be removed when set // Create network - let netuid = 2; + let netuid = NetUid::from(2); add_network(netuid, 10); // Register a neuron @@ -1630,7 +1690,7 @@ fn test_sets_a_lower_value_clears_small_nominations() { #[test] fn test_sudo_set_subnet_owner_hotkey() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey: U256 = U256::from(1); let hotkey: U256 = U256::from(2); @@ -1674,7 +1734,7 @@ fn test_sudo_set_subnet_owner_hotkey() { #[test] fn test_sudo_set_ema_halving() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let to_be_set: u64 = 10; add_network(netuid, 10); @@ -1716,7 +1776,7 @@ fn test_sudo_set_ema_halving() { #[test] fn test_set_sn_owner_hotkey_owner() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: U256 = U256::from(3); let bad_origin_coldkey: U256 = U256::from(4); add_network(netuid, 10); @@ -1761,7 +1821,7 @@ fn test_set_sn_owner_hotkey_owner() { #[test] fn test_set_sn_owner_hotkey_root() { new_test_ext().execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: U256 = U256::from(3); add_network(netuid, 10); @@ -1780,3 +1840,77 @@ fn test_set_sn_owner_hotkey_root() { assert_eq!(actual_hotkey, hotkey); }); } + +#[test] +fn test_sudo_set_bonds_reset_enabled() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let to_be_set: bool = true; + let sn_owner = U256::from(1); + add_network(netuid, 10); + let init_value: bool = SubtensorModule::get_bonds_reset(netuid); + + assert_eq!( + AdminUtils::sudo_set_bonds_reset_enabled( + <::RuntimeOrigin>::signed(U256::from(1)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin) + ); + + assert_ok!(AdminUtils::sudo_set_bonds_reset_enabled( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_bonds_reset(netuid), to_be_set); + assert_ne!(SubtensorModule::get_bonds_reset(netuid), init_value); + + pallet_subtensor::SubnetOwner::::insert(netuid, sn_owner); + + assert_ok!(AdminUtils::sudo_set_bonds_reset_enabled( + <::RuntimeOrigin>::signed(sn_owner), + netuid, + !to_be_set + )); + assert_eq!(SubtensorModule::get_bonds_reset(netuid), !to_be_set); + }); +} + +#[test] +fn test_sudo_set_yuma3_enabled() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let to_be_set: bool = true; + let sn_owner = U256::from(1); + add_network(netuid, 10); + let init_value: bool = SubtensorModule::get_yuma3_enabled(netuid); + + assert_eq!( + AdminUtils::sudo_set_yuma3_enabled( + <::RuntimeOrigin>::signed(U256::from(1)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin) + ); + + assert_ok!(AdminUtils::sudo_set_yuma3_enabled( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_yuma3_enabled(netuid), to_be_set); + assert_ne!(SubtensorModule::get_yuma3_enabled(netuid), init_value); + + pallet_subtensor::SubnetOwner::::insert(netuid, sn_owner); + + assert_ok!(AdminUtils::sudo_set_yuma3_enabled( + <::RuntimeOrigin>::signed(sn_owner), + netuid, + !to_be_set + )); + assert_eq!(SubtensorModule::get_yuma3_enabled(netuid), !to_be_set); + }); +} diff --git a/pallets/collective/src/lib.rs b/pallets/collective/src/lib.rs index 03d84b063e..baea090307 100644 --- a/pallets/collective/src/lib.rs +++ b/pallets/collective/src/lib.rs @@ -475,7 +475,7 @@ pub mod pallet { T::WeightInfo::execute( *length_bound, // B T::MaxMembers::get(), // M - ).saturating_add(proposal.get_dispatch_info().weight), // P + ).saturating_add(proposal.get_dispatch_info().call_weight), // P DispatchClass::Operational ))] pub fn execute( @@ -934,7 +934,7 @@ impl, I: 'static> Pallet { Error::::ProposalLengthBoundLessThanProposalLength ); let proposal = ProposalOf::::get(hash).ok_or(Error::::ProposalNotExists)?; - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; ensure!( proposal_weight.all_lte(weight_bound), Error::::ProposalWeightLessThanDispatchCallWeight @@ -964,7 +964,7 @@ impl, I: 'static> Pallet { ) -> (Weight, u32) { Self::deposit_event(Event::Approved { proposal_hash }); - let dispatch_weight = proposal.get_dispatch_info().weight; + let dispatch_weight = proposal.get_dispatch_info().call_weight; let origin = RawOrigin::Members(yes_votes, seats).into(); let result = proposal.dispatch(origin); Self::deposit_event(Event::Executed { diff --git a/pallets/collective/src/tests.rs b/pallets/collective/src/tests.rs index ae3ad69c8d..46c10f52e2 100644 --- a/pallets/collective/src/tests.rs +++ b/pallets/collective/src/tests.rs @@ -26,12 +26,12 @@ use frame_system::{EnsureRoot, EventRecord, Phase}; use sp_core::H256; use sp_runtime::{ BuildStorage, - testing::Header, + testing::{Header, TestXt}, traits::{BlakeTwo256, IdentityLookup}, }; pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = TestXt; frame_support::construct_runtime!( pub enum Test @@ -285,7 +285,7 @@ fn close_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Collective::propose( @@ -355,7 +355,7 @@ fn proposal_weight_limit_works_on_approve() { old_count: ::get(), }); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); // Set 1 as prime voter Prime::::set(Some(1)); @@ -397,7 +397,7 @@ fn proposal_weight_limit_ignored_on_disapprove() { old_count: ::get(), }); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Collective::propose( @@ -423,7 +423,7 @@ fn close_with_prime_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Collective::set_members( RuntimeOrigin::root(), @@ -483,7 +483,7 @@ fn close_with_voting_prime_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Collective::set_members( RuntimeOrigin::root(), @@ -547,7 +547,7 @@ fn close_with_no_prime_but_majority_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(CollectiveMajority::set_members( RuntimeOrigin::root(), @@ -883,7 +883,7 @@ fn correct_validate_and_get_proposal() { )); let hash = BlakeTwo256::hash_of(&proposal); - let weight = proposal.get_dispatch_info().weight; + let weight = proposal.get_dispatch_info().call_weight; assert_noop!( Collective::validate_and_get_proposal( &BlakeTwo256::hash_of(&vec![3; 4]), @@ -1107,7 +1107,7 @@ fn motions_all_first_vote_free_works() { // Test close() Extrincis | Check DispatchResultWithPostInfo with Pay Info - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let close_rval: DispatchResultWithPostInfo = Collective::close( RuntimeOrigin::root(), hash, @@ -1135,7 +1135,7 @@ fn motions_reproposing_disapproved_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose( RuntimeOrigin::signed(1), @@ -1170,7 +1170,7 @@ fn motions_approval_with_enough_votes_and_lower_voting_threshold_works() { new_test_ext().execute_with(|| { let proposal = RuntimeCall::Democracy(mock_democracy::Call::external_propose_majority {}); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash: H256 = proposal.blake2_256().into(); // The voting threshold is 2, but the required votes for `ExternalMajorityOrigin` is 3. // The proposal will be executed regardless of the voting threshold @@ -1304,7 +1304,7 @@ fn motions_disapproval_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose( RuntimeOrigin::signed(1), @@ -1363,7 +1363,7 @@ fn motions_approval_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose( RuntimeOrigin::signed(1), @@ -1426,7 +1426,7 @@ fn motion_with_no_votes_closes_with_disapproval() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose( RuntimeOrigin::signed(1), diff --git a/pallets/commitments/Cargo.toml b/pallets/commitments/Cargo.toml index 7b2f49ace8..efc1a216db 100644 --- a/pallets/commitments/Cargo.toml +++ b/pallets/commitments/Cargo.toml @@ -40,6 +40,7 @@ sha2 = { workspace = true } log = { workspace = true } pallet-subtensor = { path = "../subtensor", default-features = false } +subtensor-runtime-common = { workspace = true } [dev-dependencies] sp-core = { workspace = true } @@ -49,26 +50,27 @@ pallet-balances = { workspace = true } [features] default = ["std"] std = [ + "ark-serialize/std", "codec/std", + "enumflags2/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "scale-info/std", - "sp-std/std", - "sp-runtime/std", - "enumflags2/std", + "hex/std", + "log/std", "pallet-balances/std", + "pallet-drand/std", + "pallet-subtensor/std", + "rand_chacha/std", + "scale-info/std", + "sha2/std", "sp-core/std", "sp-io/std", - "ark-serialize/std", - "log/std", - "pallet-drand/std", + "sp-runtime/std", + "sp-std/std", + "subtensor-runtime-common/std", "tle/std", "w3f-bls/std", - "hex/std", - "rand_chacha/std", - "sha2/std", - "pallet-subtensor/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/pallets/commitments/src/benchmarking.rs b/pallets/commitments/src/benchmarking.rs index e66f2a07e8..e8efcc42a7 100644 --- a/pallets/commitments/src/benchmarking.rs +++ b/pallets/commitments/src/benchmarking.rs @@ -35,7 +35,7 @@ mod benchmarks { #[benchmark] fn set_commitment() { - let netuid = 1; + let netuid = NetUid::from(1); let caller: T::AccountId = whitelisted_caller(); let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 5b1ff7f3a8..527a00b13a 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -11,7 +11,6 @@ pub mod types; pub mod weights; pub use pallet::*; -use subtensor_macros::freeze_struct; pub use types::*; pub use weights::WeightInfo; @@ -21,6 +20,7 @@ use scale_info::prelude::collections::BTreeSet; use sp_runtime::SaturatedConversion; use sp_runtime::{Saturating, traits::Zero}; use sp_std::{boxed::Box, vec::Vec}; +use subtensor_runtime_common::NetUid; use tle::{ curves::drand::TinyBLS381, stream_ciphers::AESGCMStreamCipherProvider, @@ -78,7 +78,7 @@ pub mod pallet { /// Used to retrieve the given subnet's tempo pub trait GetTempoInterface { /// Used to retreive the epoch index for the given subnet. - fn get_epoch_index(netuid: u16, cur_block: u64) -> u64; + fn get_epoch_index(netuid: NetUid, cur_block: u64) -> u64; } #[pallet::event] @@ -87,14 +87,14 @@ pub mod pallet { /// A commitment was set Commitment { /// The netuid of the commitment - netuid: u16, + netuid: NetUid, /// The account who: T::AccountId, }, /// A timelock-encrypted commitment was set TimelockCommitment { /// The netuid of the commitment - netuid: u16, + netuid: NetUid, /// The account who: T::AccountId, /// The drand round to reveal @@ -103,7 +103,7 @@ pub mod pallet { /// A timelock-encrypted commitment was auto-revealed CommitmentRevealed { /// The netuid of the commitment - netuid: u16, + netuid: NetUid, /// The account who: T::AccountId, }, @@ -125,7 +125,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn timelocked_index)] pub type TimelockedIndex = - StorageValue<_, BTreeSet<(u16, T::AccountId)>, ValueQuery>; + StorageValue<_, BTreeSet<(NetUid, T::AccountId)>, ValueQuery>; /// Identity data by account #[pallet::storage] @@ -133,7 +133,7 @@ pub mod pallet { pub(super) type CommitmentOf = StorageDoubleMap< _, Identity, - u16, + NetUid, Twox64Concat, T::AccountId, Registration, T::MaxFields, BlockNumberFor>, @@ -145,7 +145,7 @@ pub mod pallet { pub(super) type LastCommitment = StorageDoubleMap< _, Identity, - u16, + NetUid, Twox64Concat, T::AccountId, BlockNumberFor, @@ -157,7 +157,7 @@ pub mod pallet { pub(super) type LastBondsReset = StorageDoubleMap< _, Identity, - u16, + NetUid, Twox64Concat, T::AccountId, BlockNumberFor, @@ -169,7 +169,7 @@ pub mod pallet { pub(super) type RevealedCommitments = StorageDoubleMap< _, Identity, - u16, + NetUid, Twox64Concat, T::AccountId, Vec<(Vec, u64)>, // Reveals<(Data, RevealBlock)> @@ -180,8 +180,15 @@ pub mod pallet { /// in the RateLimit window #[pallet::storage] #[pallet::getter(fn used_space_of)] - pub type UsedSpaceOf = - StorageDoubleMap<_, Identity, u16, Twox64Concat, T::AccountId, UsageTracker, OptionQuery>; + pub type UsedSpaceOf = StorageDoubleMap< + _, + Identity, + NetUid, + Twox64Concat, + T::AccountId, + UsageTracker, + OptionQuery, + >; #[pallet::type_value] /// The default Maximum Space @@ -206,7 +213,7 @@ pub mod pallet { ))] pub fn set_commitment( origin: OriginFor, - netuid: u16, + netuid: NetUid, info: Box>, ) -> DispatchResult { let who = ensure_signed(origin.clone())?; @@ -336,7 +343,7 @@ pub mod pallet { /// Sudo-set MaxSpace #[pallet::call_index(2)] #[pallet::weight(( - Weight::from_parts(3_556_000, 0) + Weight::from_parts(2_965_000, 0) .saturating_add(T::DbWeight::get().reads(0_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)), DispatchClass::Operational, @@ -366,21 +373,21 @@ pub mod pallet { // Interfaces to interact with other pallets pub trait CanCommit { - fn can_commit(netuid: u16, who: &AccountId) -> bool; + fn can_commit(netuid: NetUid, who: &AccountId) -> bool; } impl CanCommit for () { - fn can_commit(_: u16, _: &A) -> bool { + fn can_commit(_: NetUid, _: &A) -> bool { false } } pub trait OnMetadataCommitment { - fn on_metadata_commitment(netuid: u16, account: &AccountId); + fn on_metadata_commitment(netuid: NetUid, account: &AccountId); } impl OnMetadataCommitment for () { - fn on_metadata_commitment(_: u16, _: &A) {} + fn on_metadata_commitment(_: NetUid, _: &A) {} } /************************************************************ @@ -393,114 +400,7 @@ pub enum CallType { Other, } -use { - frame_support::{ - dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo}, - pallet_prelude::{Decode, Encode, PhantomData, TypeInfo}, - traits::IsSubType, - }, - sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, - transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, - }, -}; - -#[freeze_struct("6a00398e14a8a984")] -#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct CommitmentsSignedExtension(pub PhantomData); - -impl Default for CommitmentsSignedExtension -where - T::RuntimeCall: Dispatchable, - ::RuntimeCall: IsSubType>, -{ - fn default() -> Self { - Self::new() - } -} - -impl CommitmentsSignedExtension -where - T::RuntimeCall: Dispatchable, - ::RuntimeCall: IsSubType>, -{ - pub fn new() -> Self { - Self(Default::default()) - } - - pub fn get_priority_vanilla() -> u64 { - // Return high priority so that every extrinsic except set_weights function will - // have a higher priority than the set_weights call - u64::MAX - } -} - -impl sp_std::fmt::Debug for CommitmentsSignedExtension { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "SignedExtension") - } -} - -impl SignedExtension for CommitmentsSignedExtension -where - T::RuntimeCall: Dispatchable, - ::RuntimeCall: IsSubType>, -{ - const IDENTIFIER: &'static str = "CommitmentsSignedExtension"; - - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); - type Pre = (CallType, u64, Self::AccountId); - - fn additional_signed(&self) -> Result { - Ok(()) - } - - fn validate( - &self, - _: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - call.is_sub_type(); - Ok(ValidTransaction { - priority: Self::get_priority_vanilla(), - ..Default::default() - }) - } - - // NOTE: Add later when we put in a pre and post dispatch step. - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - match call.is_sub_type() { - Some(Call::set_commitment { .. }) => { - let transaction_fee = 0; - Ok((CallType::SetCommitment, transaction_fee, who.clone())) - } - _ => { - let transaction_fee = 0; - Ok((CallType::Other, transaction_fee, who.clone())) - } - } - } - - fn post_dispatch( - _maybe_pre: Option, - _info: &DispatchInfoOf, - _post_info: &PostDispatchInfoOf, - _len: usize, - _result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - Ok(()) - } -} +use frame_support::{dispatch::DispatchResult, pallet_prelude::TypeInfo}; impl Pallet { pub fn reveal_timelocked_commitments() -> DispatchResult { diff --git a/pallets/commitments/src/mock.rs b/pallets/commitments/src/mock.rs index 4e6aa123bd..19e0e726da 100644 --- a/pallets/commitments/src/mock.rs +++ b/pallets/commitments/src/mock.rs @@ -2,8 +2,9 @@ use crate as pallet_commitments; use frame_support::{ derive_impl, pallet_prelude::{Get, TypeInfo}, - traits::{ConstU32, ConstU64}, + traits::{ConstU32, ConstU64, InherentBuilder}, }; +use frame_system::offchain::CreateTransactionBase; use sp_core::H256; use sp_runtime::{ BuildStorage, @@ -87,7 +88,7 @@ impl TypeInfo for TestMaxFields { pub struct TestCanCommit; impl pallet_commitments::CanCommit for TestCanCommit { - fn can_commit(_netuid: u16, _who: &u64) -> bool { + fn can_commit(_netuid: NetUid, _who: &u64) -> bool { true } } @@ -106,10 +107,10 @@ impl pallet_commitments::Config for Test { pub struct MockTempoInterface; impl pallet_commitments::GetTempoInterface for MockTempoInterface { - fn get_epoch_index(netuid: u16, cur_block: u64) -> u64 { + fn get_epoch_index(netuid: NetUid, cur_block: u64) -> u64 { let tempo = 360; // TODO: configure SubtensorModule in this mock let tempo_plus_one: u64 = tempo.saturating_add(1); - let netuid_plus_one: u64 = (netuid as u64).saturating_add(1); + let netuid_plus_one: u64 = (u16::from(netuid) as u64).saturating_add(1); let block_with_offset: u64 = cur_block.saturating_add(netuid_plus_one); block_with_offset.checked_div(tempo_plus_one).unwrap_or(0) @@ -159,32 +160,48 @@ impl frame_system::offchain::SigningTypes for Test { type Signature = test_crypto::Signature; } -impl frame_system::offchain::CreateSignedTransaction> for Test { - fn create_transaction>( - call: RuntimeCall, +impl frame_system::offchain::CreateTransactionBase for Test +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateInherent for Test +where + RuntimeCall: From, +{ + fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic { + UncheckedExtrinsic::new_inherent(call) + } +} + +impl frame_system::offchain::CreateSignedTransaction for Test +where + RuntimeCall: From, +{ + fn create_signed_transaction< + C: frame_system::offchain::AppCrypto, + >( + call: >::RuntimeCall, _public: Self::Public, - account: Self::AccountId, - _nonce: u32, - ) -> Option<( - RuntimeCall, - ::SignaturePayload, - )> { + _account: Self::AccountId, + nonce: Self::Nonce, + ) -> Option { // Create a dummy sr25519 signature from a raw byte array let dummy_raw = [0u8; 64]; let dummy_signature = sp_core::sr25519::Signature::from(dummy_raw); let signature = test_crypto::Signature::from(dummy_signature); - Some((call, (account, signature, ()))) + Some(UncheckedExtrinsic::new_signed( + call, + nonce.into(), + signature, + (), + )) } } -impl frame_system::offchain::SendTransactionTypes for Test -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; -} - pub fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::::default() .build_storage() diff --git a/pallets/commitments/src/tests.rs b/pallets/commitments/src/tests.rs index 62e9444b76..431d5e521b 100644 --- a/pallets/commitments/src/tests.rs +++ b/pallets/commitments/src/tests.rs @@ -1,5 +1,6 @@ use codec::Encode; use sp_std::prelude::*; +use subtensor_runtime_common::NetUid; #[cfg(test)] use crate::{ @@ -126,15 +127,16 @@ fn set_commitment_works() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(1), - 1, + 1.into(), info.clone() )); - let commitment = Pallet::::commitment_of(1, 1).expect("Expected not to panic"); + let commitment = + Pallet::::commitment_of(NetUid::from(1), 1).expect("Expected not to panic"); let initial_deposit: u64 = ::InitialDeposit::get(); assert_eq!(commitment.deposit, initial_deposit); assert_eq!(commitment.block, 1); - assert_eq!(Pallet::::last_commitment(1, 1), Some(1)); + assert_eq!(Pallet::::last_commitment(NetUid::from(1), 1), Some(1)); }); } @@ -151,7 +153,11 @@ fn set_commitment_too_many_fields_panics() { }); // We never get here, because the constructor panics above. - let _ = Pallet::::set_commitment(frame_system::RawOrigin::Signed(1).into(), 1, info); + let _ = Pallet::::set_commitment( + frame_system::RawOrigin::Signed(1).into(), + 1.into(), + info, + ); }); } @@ -170,14 +176,14 @@ fn set_commitment_updates_deposit() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(1), - 1, + 1.into(), info1 )); let initial_deposit: u64 = ::InitialDeposit::get(); let field_deposit: u64 = ::FieldDeposit::get(); let expected_deposit1: u64 = initial_deposit + 2u64 * field_deposit; assert_eq!( - Pallet::::commitment_of(1, 1) + Pallet::::commitment_of(NetUid::from(1), 1) .expect("Expected not to panic") .deposit, expected_deposit1 @@ -185,12 +191,12 @@ fn set_commitment_updates_deposit() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(1), - 1, + 1.into(), info2 )); let expected_deposit2: u64 = initial_deposit + 3u64 * field_deposit; assert_eq!( - Pallet::::commitment_of(1, 1) + Pallet::::commitment_of(NetUid::from(1), 1) .expect("Expected not to panic") .deposit, expected_deposit2 @@ -208,15 +214,16 @@ fn event_emission_works() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(1), - 1, + 1.into(), info )); let events = System::::events(); - assert!(events.iter().any(|e| matches!( - &e.event, - RuntimeEvent::Commitments(Event::Commitment { netuid: 1, who: 1 }) - ))); + let expected_event = RuntimeEvent::Commitments(Event::Commitment { + netuid: 1.into(), + who: 1, + }); + assert!(events.iter().any(|e| e.event == expected_event)); }); } @@ -256,7 +263,7 @@ fn happy_path_timelock_commitments() { }; let who = 123; - let netuid = 42; + let netuid = NetUid::from(42); System::::set_block_number(1); assert_ok!(Pallet::::set_commitment( @@ -293,7 +300,7 @@ fn happy_path_timelock_commitments() { fn reveal_timelocked_commitment_missing_round_does_nothing() { new_test_ext().execute_with(|| { let who = 1; - let netuid = 2; + let netuid = NetUid::from(2); System::::set_block_number(5); let ciphertext = produce_ciphertext(b"My plaintext", 1000); let data = Data::TimelockEncrypted { @@ -320,7 +327,7 @@ fn reveal_timelocked_commitment_missing_round_does_nothing() { fn reveal_timelocked_commitment_cant_deserialize_ciphertext() { new_test_ext().execute_with(|| { let who = 42; - let netuid = 9; + let netuid = NetUid::from(9); System::::set_block_number(10); let good_ct = produce_ciphertext(b"Some data", 1000); let mut corrupted = good_ct.into_inner(); @@ -352,7 +359,7 @@ fn reveal_timelocked_commitment_cant_deserialize_ciphertext() { fn reveal_timelocked_commitment_bad_signature_skips_decryption() { new_test_ext().execute_with(|| { let who = 10; - let netuid = 11; + let netuid = NetUid::from(11); System::::set_block_number(15); let real_ct = produce_ciphertext(b"A valid plaintext", 1000); let data = Data::TimelockEncrypted { @@ -380,7 +387,7 @@ fn reveal_timelocked_commitment_bad_signature_skips_decryption() { fn reveal_timelocked_commitment_empty_decrypted_data_is_skipped() { new_test_ext().execute_with(|| { let who = 2; - let netuid = 3; + let netuid = NetUid::from(3); let commit_block = 100u64; System::::set_block_number(commit_block); let reveal_round = 1000; @@ -439,7 +446,7 @@ fn reveal_timelocked_commitment_single_field_entry_is_removed_after_reveal() { }; let who = 555; - let netuid = 777; + let netuid = NetUid::from(777); System::::set_block_number(1); assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(who), @@ -539,7 +546,7 @@ fn reveal_timelocked_multiple_fields_only_correct_ones_removed() { // 5) Insert the commitment let who = 123; - let netuid = 999; + let netuid = NetUid::from(999); System::::set_block_number(1); assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(who), @@ -602,7 +609,7 @@ fn reveal_timelocked_multiple_fields_only_correct_ones_removed() { #[test] fn test_index_lifecycle_no_timelocks_updates_in_out() { new_test_ext().execute_with(|| { - let netuid = 100; + let netuid = NetUid::from(100); let who = 999; // @@ -667,7 +674,7 @@ fn test_index_lifecycle_no_timelocks_updates_in_out() { #[test] fn two_timelocks_partial_then_full_reveal() { new_test_ext().execute_with(|| { - let netuid_a = 1; + let netuid_a = NetUid::from(1); let who_a = 10; let round_1000 = 1000; let round_2000 = 2000; @@ -769,7 +776,7 @@ fn two_timelocks_partial_then_full_reveal() { #[test] fn single_timelock_reveal_later_round() { new_test_ext().execute_with(|| { - let netuid_b = 2; + let netuid_b = NetUid::from(2); let who_b = 20; let round_2000 = 2000; @@ -841,7 +848,7 @@ fn single_timelock_reveal_later_round() { #[test] fn tempo_based_space_limit_accumulates_in_same_window() { new_test_ext().execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let who = 100; let space_limit = 150; MaxSpace::::set(space_limit); @@ -874,7 +881,7 @@ fn tempo_based_space_limit_accumulates_in_same_window() { #[test] fn tempo_based_space_limit_resets_after_tempo() { new_test_ext().execute_with(|| { - let netuid = 2; + let netuid = NetUid::from(2); let who = 101; MaxSpace::::set(250); @@ -932,8 +939,8 @@ fn tempo_based_space_limit_resets_after_tempo() { #[test] fn tempo_based_space_limit_does_not_affect_different_netuid() { new_test_ext().execute_with(|| { - let netuid_a = 10; - let netuid_b = 20; + let netuid_a = NetUid::from(10); + let netuid_b = NetUid::from(20); let who = 111; let space_limit = 199; MaxSpace::::set(space_limit); @@ -982,7 +989,7 @@ fn tempo_based_space_limit_does_not_affect_different_netuid() { #[test] fn tempo_based_space_limit_does_not_affect_different_user() { new_test_ext().execute_with(|| { - let netuid = 10; + let netuid = NetUid::from(10); let user1 = 123; let user2 = 456; let space_limit = 199; @@ -1032,7 +1039,7 @@ fn tempo_based_space_limit_does_not_affect_different_user() { #[test] fn tempo_based_space_limit_sudo_set_max_space() { new_test_ext().execute_with(|| { - let netuid = 3; + let netuid = NetUid::from(3); let who = 15; MaxSpace::::set(100); @@ -1069,7 +1076,7 @@ fn tempo_based_space_limit_sudo_set_max_space() { fn on_initialize_reveals_matured_timelocks() { new_test_ext().execute_with(|| { let who = 42; - let netuid = 7; + let netuid = NetUid::from(7); let reveal_round = 1000; let message_text = b"Timelock test via on_initialize"; @@ -1159,7 +1166,7 @@ fn set_commitment_unreserve_leftover_fails() { new_test_ext().execute_with(|| { use frame_system::RawOrigin; - let netuid = 999; + let netuid = NetUid::from(999); let who = 99; Balances::make_free_balance_be(&who, 10_000); @@ -1198,7 +1205,7 @@ fn timelocked_index_complex_scenario_works() { new_test_ext().execute_with(|| { System::::set_block_number(1); - let netuid = 42; + let netuid = NetUid::from(42); let user_a = 1000; let user_b = 2000; let user_c = 3000; @@ -1457,7 +1464,7 @@ fn reveal_timelocked_bad_timelocks_are_removed() { // 3) Insert the commitment // let who = 123; - let netuid = 777; + let netuid = NetUid::from(777); System::::set_block_number(1); assert_ok!(Pallet::::set_commitment( RawOrigin::Signed(who).into(), @@ -1531,7 +1538,7 @@ fn reveal_timelocked_bad_timelocks_are_removed() { #[test] fn revealed_commitments_keeps_only_10_items() { new_test_ext().execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let who = 2; let reveal_round = 1000; @@ -1599,7 +1606,7 @@ fn revealed_commitments_keeps_only_10_items() { #[test] fn revealed_commitments_keeps_only_10_newest_with_individual_single_field_commits() { new_test_ext().execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let who = 2; let reveal_round = 1000; @@ -1678,7 +1685,7 @@ fn usage_respects_minimum_of_100_bytes() { new_test_ext().execute_with(|| { MaxSpace::::set(1000); - let netuid = 1; + let netuid = NetUid::from(1); let who = 99; System::::set_block_number(1); @@ -1767,12 +1774,12 @@ fn set_commitment_works_with_multiple_raw_fields() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(12345), - 99, + 99.into(), Box::new(info_multiple) )); let expected_deposit: BalanceOf = initial_deposit + 3u64 * field_deposit; - let stored = CommitmentOf::::get(99, 12345).expect("Should be stored"); + let stored = CommitmentOf::::get(NetUid::from(99), 12345).expect("Should be stored"); assert_eq!( stored.deposit, expected_deposit, "Deposit must equal initial + 3 * field_deposit" @@ -1780,7 +1787,8 @@ fn set_commitment_works_with_multiple_raw_fields() { assert_eq!(stored.block, cur_block, "Stored block must match cur_block"); - let usage = UsedSpaceOf::::get(99, 12345).expect("Expected to not panic"); + let usage = + UsedSpaceOf::::get(NetUid::from(99), 12345).expect("Expected to not panic"); assert_eq!( usage.used_space, 100, "Usage is clamped to 100 when sum of fields is < 100" @@ -1796,18 +1804,19 @@ fn set_commitment_works_with_multiple_raw_fields() { assert_ok!(Pallet::::set_commitment( RuntimeOrigin::signed(12345), - 99, + 99.into(), Box::new(info_two_fields) )); let expected_deposit2: BalanceOf = initial_deposit + 2u64 * field_deposit; - let stored2 = CommitmentOf::::get(99, 12345).expect("Should be stored"); + let stored2 = CommitmentOf::::get(NetUid::from(99), 12345).expect("Should be stored"); assert_eq!( stored2.deposit, expected_deposit2, "Deposit must have decreased after removing one field" ); - let usage2 = UsedSpaceOf::::get(99, 12345).expect("Expected to not panic"); + let usage2 = + UsedSpaceOf::::get(NetUid::from(99), 12345).expect("Expected to not panic"); let expected_usage2 = 200u64; assert_eq!( usage2.used_space, expected_usage2, @@ -1815,15 +1824,11 @@ fn set_commitment_works_with_multiple_raw_fields() { ); let events = System::::events(); - let found_commitment_event = events.iter().any(|e| { - matches!( - e.event, - RuntimeEvent::Commitments(Event::Commitment { - netuid: 99, - who: 12345 - }) - ) + let expected_event = RuntimeEvent::Commitments(Event::Commitment { + netuid: 99.into(), + who: 12345, }); + let found_commitment_event = events.iter().any(|e| e.event == expected_event); assert!( found_commitment_event, "Expected at least one Event::Commitment to be emitted" @@ -1842,10 +1847,10 @@ fn multiple_timelocked_commitments_reveal_works() { System::::set_block_number(cur_block); let who = 123; - let netuid = 999; + let netuid = NetUid::from(999); // ------------------------------------------- - // 2) Create multiple TLE fields referencing + // 2) Create multiple TLE fields referencing // two known valid Drand rounds: 1000, 2000 // ------------------------------------------- @@ -2022,7 +2027,7 @@ fn mixed_timelocked_and_raw_fields_works() { System::::set_block_number(cur_block); let who = 77; - let netuid = 501; + let netuid = NetUid::from(501); // ------------------------------------------- // 2) Create raw fields and timelocked fields diff --git a/pallets/crowdloan/src/lib.rs b/pallets/crowdloan/src/lib.rs index 1d4ed4e263..f068a9e2b0 100644 --- a/pallets/crowdloan/src/lib.rs +++ b/pallets/crowdloan/src/lib.rs @@ -309,7 +309,7 @@ pub mod pallet { #[pallet::weight({ let di = call.as_ref().map(|c| c.get_dispatch_info()); let inner_call_weight = match di { - Some(di) => di.weight, + Some(di) => di.call_weight, None => Weight::zero(), }; let base_weight = T::WeightInfo::create(); diff --git a/pallets/drand/src/lib.rs b/pallets/drand/src/lib.rs index 08d728daa3..762aa65238 100644 --- a/pallets/drand/src/lib.rs +++ b/pallets/drand/src/lib.rs @@ -43,8 +43,8 @@ use codec::Encode; use frame_support::{pallet_prelude::*, traits::Randomness}; use frame_system::{ offchain::{ - AppCrypto, CreateSignedTransaction, SendUnsignedTransaction, SignedPayload, Signer, - SigningTypes, + AppCrypto, CreateInherent, CreateSignedTransaction, SendUnsignedTransaction, SignedPayload, + Signer, SigningTypes, }, pallet_prelude::BlockNumberFor, }; @@ -155,7 +155,9 @@ pub mod pallet { pub struct Pallet(_); #[pallet::config] - pub trait Config: CreateSignedTransaction> + frame_system::Config { + pub trait Config: + CreateSignedTransaction> + CreateInherent> + frame_system::Config + { /// The identifier type for an offchain worker. type AuthorityId: AppCrypto; /// The overarching runtime event type. @@ -288,10 +290,6 @@ pub mod pallet { pulses_payload: payload, signature, } => { - // Blacklist stale pulses in the txpool that can stall finalization. - if payload.block_number < BlockNumberFor::::from(5612500u32) { - return InvalidTransaction::Stale.into(); - } let signature = signature.as_ref().ok_or(InvalidTransaction::BadSigner)?; Self::validate_signature_and_parameters( payload, diff --git a/pallets/drand/src/mock.rs b/pallets/drand/src/mock.rs index 6ef1f2bf8a..f8c0d9ab4d 100644 --- a/pallets/drand/src/mock.rs +++ b/pallets/drand/src/mock.rs @@ -3,14 +3,14 @@ use crate::verifier::*; use crate::*; use frame_support::{ derive_impl, parameter_types, - traits::{ConstU16, ConstU64}, + traits::{ConstU16, ConstU64, InherentBuilder}, }; use sp_core::{H256, sr25519::Signature}; use sp_keystore::{KeystoreExt, testing::MemoryKeystore}; use sp_runtime::{ BuildStorage, testing::TestXt, - traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify}, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, }; type Block = frame_system::mocking::MockBlock; @@ -59,25 +59,36 @@ impl frame_system::offchain::SigningTypes for Test { type Signature = Signature; } -impl frame_system::offchain::SendTransactionTypes for Test +impl frame_system::offchain::CreateTransactionBase for Test where RuntimeCall: From, { - type OverarchingCall = RuntimeCall; + type RuntimeCall = RuntimeCall; type Extrinsic = Extrinsic; } +impl frame_system::offchain::CreateInherent for Test +where + RuntimeCall: From, +{ + fn create_inherent(call: RuntimeCall) -> Self::Extrinsic { + Extrinsic::new_inherent(call) + } +} + impl frame_system::offchain::CreateSignedTransaction for Test where RuntimeCall: From, { - fn create_transaction>( + fn create_signed_transaction< + C: frame_system::offchain::AppCrypto, + >( call: RuntimeCall, _public: ::Signer, _account: AccountId, nonce: u64, - ) -> Option<(RuntimeCall, ::SignaturePayload)> { - Some((call, (nonce, ()))) + ) -> Option { + Some(Extrinsic::new_signed(call, nonce, (), ())) } } diff --git a/pallets/proxy/src/lib.rs b/pallets/proxy/src/lib.rs index 3f45951190..3ae6b6f8cb 100644 --- a/pallets/proxy/src/lib.rs +++ b/pallets/proxy/src/lib.rs @@ -197,7 +197,7 @@ pub mod pallet { #[pallet::weight({ let di = call.get_dispatch_info(); let inner_call_weight = match di.pays_fee { - Pays::Yes => di.weight, + Pays::Yes => di.call_weight, Pays::No => Weight::zero(), }; let base_weight = T::WeightInfo::proxy(T::MaxProxies::get()) @@ -503,7 +503,7 @@ pub mod pallet { (T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get()) // AccountData for inner call origin accountdata. .saturating_add(T::DbWeight::get().reads_writes(1, 1)) - .saturating_add(di.weight), + .saturating_add(di.call_weight), di.class) })] pub fn proxy_announced( diff --git a/pallets/subtensor/Cargo.toml b/pallets/subtensor/Cargo.toml index ab17cf5bdc..93f88139ef 100644 --- a/pallets/subtensor/Cargo.toml +++ b/pallets/subtensor/Cargo.toml @@ -44,12 +44,16 @@ hex = { workspace = true } share-pool = { default-features = false, path = "../../primitives/share-pool" } safe-math = { default-features = false, path = "../../primitives/safe-math" } approx = { workspace = true } +subtensor-swap-interface = { workspace = true } +subtensor-runtime-common = { workspace = true } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../collective" } pallet-drand = { path = "../drand", default-features = false } pallet-membership = { workspace = true } hex-literal = { workspace = true } -num-traits = { version = "0.2.19", default-features = false, features = ["libm"] } +num-traits = { version = "0.2.19", default-features = false, features = [ + "libm", +] } tle = { workspace = true, default-features = false } ark-bls12-381 = { workspace = true, default-features = false } ark-serialize = { workspace = true, default-features = false } @@ -60,6 +64,7 @@ rand_chacha = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true, features = ["std"] } pallet-scheduler = { workspace = true } +pallet-subtensor-swap = { workspace = true } sp-version = { workspace = true } # Substrate sp-tracing = { workspace = true } @@ -70,59 +75,64 @@ sp-std = { workspace = true } pallet-preimage = { workspace = true } [features] -default = ["std"] std = [ + "ark-bls12-381/std", + "ark-serialize/std", "codec/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "scale-info/std", + "hex/std", + "libsecp256k1/std", + "log/std", + "ndarray/std", + "num-traits/std", + "pallet-balances/std", "pallet-collective/std", + "pallet-drand/std", "pallet-membership/std", - "substrate-fixed/std", - "pallet-balances/std", "pallet-preimage/std", "pallet-scheduler/std", + "pallet-subtensor-swap/std", "pallet-transaction-payment/std", "pallet-utility/std", + "rand_chacha/std", + "safe-math/std", + "scale-info/std", + "serde/std", + "serde_bytes/std", + "serde_json/std", + "serde_with/std", + "sha2/std", + "share-pool/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-tracing/std", "sp-version/std", - "hex/std", - "libsecp256k1/std", - "log/std", - "ndarray/std", - "serde/std", - "serde_bytes/std", - "serde_with/std", "substrate-fixed/std", - "num-traits/std", - "serde_json/std", + "substrate-fixed/std", + "subtensor-runtime-common/std", + "subtensor-swap-interface/std", "tle/std", - "pallet-drand/std", - "ark-bls12-381/std", - "ark-serialize/std", "w3f-bls/std", - "rand_chacha/std", - "safe-math/std", - "sha2/std", - "share-pool/std" ] +default = ["std"] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-membership/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "pallet-collective/runtime-benchmarks", + "pallet-drand/runtime-benchmarks", + "pallet-membership/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", - "pallet-drand/runtime-benchmarks" + "pallet-subtensor-swap/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -135,7 +145,7 @@ try-runtime = [ "pallet-utility/try-runtime", "sp-runtime/try-runtime", "pallet-collective/try-runtime", - "pallet-drand/try-runtime" + "pallet-drand/try-runtime", ] pow-faucet = [] fast-blocks = [] diff --git a/pallets/subtensor/rpc/Cargo.toml b/pallets/subtensor/rpc/Cargo.toml index 6a2807268d..47b63b9067 100644 --- a/pallets/subtensor/rpc/Cargo.toml +++ b/pallets/subtensor/rpc/Cargo.toml @@ -23,18 +23,19 @@ sp-rpc = { workspace = true } sp-runtime = { workspace = true } # local packages - +subtensor-runtime-common = { workspace = true } subtensor-custom-rpc-runtime-api = { path = "../runtime-api", default-features = false } pallet-subtensor = { path = "../../subtensor", default-features = false } [features] default = ["std"] std = [ + "codec/std", + "pallet-subtensor/std", + "serde/std", "sp-api/std", "sp-runtime/std", "subtensor-custom-rpc-runtime-api/std", - "pallet-subtensor/std", - "codec/std", - "serde/std" + "subtensor-runtime-common/std", ] pow-faucet = [] diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index b3b60206dd..eb3c7b11ca 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -9,6 +9,7 @@ use jsonrpsee::{ use sp_blockchain::HeaderBackend; use sp_runtime::{AccountId32, traits::Block as BlockT}; use std::sync::Arc; +use subtensor_runtime_common::NetUid; use sp_api::ProvideRuntimeApi; @@ -35,39 +36,50 @@ pub trait SubtensorCustomApi { ) -> RpcResult>; #[method(name = "neuronInfo_getNeuronsLite")] - fn get_neurons_lite(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_neurons_lite(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "neuronInfo_getNeuronLite")] - fn get_neuron_lite(&self, netuid: u16, uid: u16, at: Option) -> RpcResult>; + fn get_neuron_lite( + &self, + netuid: NetUid, + uid: u16, + at: Option, + ) -> RpcResult>; #[method(name = "neuronInfo_getNeurons")] - fn get_neurons(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_neurons(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "neuronInfo_getNeuron")] - fn get_neuron(&self, netuid: u16, uid: u16, at: Option) -> RpcResult>; + fn get_neuron(&self, netuid: NetUid, uid: u16, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetInfo")] - fn get_subnet_info(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_subnet_info(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetsInfo")] fn get_subnets_info(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetInfo_v2")] - fn get_subnet_info_v2(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_subnet_info_v2(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetsInf_v2")] fn get_subnets_info_v2(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetHyperparams")] - fn get_subnet_hyperparams(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_subnet_hyperparams(&self, netuid: NetUid, at: Option) -> RpcResult>; + #[method(name = "subnetInfo_getSubnetHyperparamsV2")] + fn get_subnet_hyperparams_v2( + &self, + netuid: NetUid, + at: Option, + ) -> RpcResult>; #[method(name = "subnetInfo_getAllDynamicInfo")] fn get_all_dynamic_info(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getDynamicInfo")] - fn get_dynamic_info(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_dynamic_info(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getAllMetagraphs")] fn get_all_metagraphs(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getMetagraph")] - fn get_metagraph(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_metagraph(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetState")] - fn get_subnet_state(&self, netuid: u16, at: Option) -> RpcResult>; + fn get_subnet_state(&self, netuid: NetUid, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getLockCost")] fn get_network_lock_cost(&self, at: Option) -> RpcResult; #[method(name = "subnetInfo_getSelectiveMetagraph")] fn get_selective_metagraph( &self, - netuid: u16, + netuid: NetUid, metagraph_index: Vec, at: Option, ) -> RpcResult>; @@ -182,7 +194,7 @@ where fn get_neurons_lite( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -198,7 +210,7 @@ where fn get_neuron_lite( &self, - netuid: u16, + netuid: NetUid, uid: u16, at: Option<::Hash>, ) -> RpcResult> { @@ -213,7 +225,11 @@ where } } - fn get_neurons(&self, netuid: u16, at: Option<::Hash>) -> RpcResult> { + fn get_neurons( + &self, + netuid: NetUid, + at: Option<::Hash>, + ) -> RpcResult> { let api = self.client.runtime_api(); let at = at.unwrap_or_else(|| self.client.info().best_hash); @@ -227,7 +243,7 @@ where fn get_neuron( &self, - netuid: u16, + netuid: NetUid, uid: u16, at: Option<::Hash>, ) -> RpcResult> { @@ -244,7 +260,7 @@ where fn get_subnet_info( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -260,7 +276,7 @@ where fn get_subnet_hyperparams( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -274,6 +290,22 @@ where } } + fn get_subnet_hyperparams_v2( + &self, + netuid: NetUid, + at: Option<::Hash>, + ) -> RpcResult> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + match api.get_subnet_hyperparams_v2(at, netuid) { + Ok(result) => Ok(result.encode()), + Err(e) => { + Err(Error::RuntimeError(format!("Unable to get subnet info: {:?}", e)).into()) + } + } + } + fn get_all_dynamic_info(&self, at: Option<::Hash>) -> RpcResult> { let api = self.client.runtime_api(); let at = at.unwrap_or_else(|| self.client.info().best_hash); @@ -300,7 +332,7 @@ where fn get_dynamic_info( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -318,7 +350,7 @@ where fn get_metagraph( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -335,7 +367,7 @@ where fn get_subnet_state( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -363,7 +395,7 @@ where fn get_subnet_info_v2( &self, - netuid: u16, + netuid: NetUid, at: Option<::Hash>, ) -> RpcResult> { let api = self.client.runtime_api(); @@ -400,7 +432,7 @@ where fn get_selective_metagraph( &self, - netuid: u16, + netuid: NetUid, metagraph_index: Vec, at: Option<::Hash>, ) -> RpcResult> { diff --git a/pallets/subtensor/runtime-api/Cargo.toml b/pallets/subtensor/runtime-api/Cargo.toml index 0812d076d3..1a95b75d16 100644 --- a/pallets/subtensor/runtime-api/Cargo.toml +++ b/pallets/subtensor/runtime-api/Cargo.toml @@ -17,17 +17,19 @@ sp-runtime = { workspace = true } frame-support = { workspace = true } serde = { workspace = true, features = ["derive"] } codec = { workspace = true } +subtensor-runtime-common = { workspace = true } # local pallet-subtensor = { version = "4.0.0-dev", path = "../../subtensor", default-features = false } [features] default = ["std"] std = [ - "sp-api/std", - "sp-runtime/std", + "codec/std", "frame-support/std", "pallet-subtensor/std", "serde/std", - "codec/std" + "sp-api/std", + "sp-runtime/std", + "subtensor-runtime-common/std", ] pow-faucet = [] diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index 1a2f34aa9e..e482a01251 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -9,9 +9,10 @@ use pallet_subtensor::rpc_info::{ neuron_info::{NeuronInfo, NeuronInfoLite}, show_subnet::SubnetState, stake_info::StakeInfo, - subnet_info::{SubnetHyperparams, SubnetInfo, SubnetInfov2}, + subnet_info::{SubnetHyperparams, SubnetHyperparamsV2, SubnetInfo, SubnetInfov2}, }; use sp_runtime::AccountId32; +use subtensor_runtime_common::NetUid; // Here we declare the runtime API. It is implemented it the `impl` block in // src/neuron_info.rs, src/subnet_info.rs, and src/delegate_info.rs @@ -19,35 +20,36 @@ sp_api::decl_runtime_apis! { pub trait DelegateInfoRuntimeApi { fn get_delegates() -> Vec>; fn get_delegate( delegate_account: AccountId32 ) -> Option>; - fn get_delegated( delegatee_account: AccountId32 ) -> Vec<(DelegateInfo, (Compact, Compact))>; + fn get_delegated( delegatee_account: AccountId32 ) -> Vec<(DelegateInfo, (Compact, Compact))>; } pub trait NeuronInfoRuntimeApi { - fn get_neurons(netuid: u16) -> Vec>; - fn get_neuron(netuid: u16, uid: u16) -> Option>; - fn get_neurons_lite(netuid: u16) -> Vec>; - fn get_neuron_lite(netuid: u16, uid: u16) -> Option>; + fn get_neurons(netuid: NetUid) -> Vec>; + fn get_neuron(netuid: NetUid, uid: u16) -> Option>; + fn get_neurons_lite(netuid: NetUid) -> Vec>; + fn get_neuron_lite(netuid: NetUid, uid: u16) -> Option>; } pub trait SubnetInfoRuntimeApi { - fn get_subnet_info(netuid: u16) -> Option>; + fn get_subnet_info(netuid: NetUid) -> Option>; fn get_subnets_info() -> Vec>>; - fn get_subnet_info_v2(netuid: u16) -> Option>; + fn get_subnet_info_v2(netuid: NetUid) -> Option>; fn get_subnets_info_v2() -> Vec>>; - fn get_subnet_hyperparams(netuid: u16) -> Option; + fn get_subnet_hyperparams(netuid: NetUid) -> Option; + fn get_subnet_hyperparams_v2(netuid: NetUid) -> Option; fn get_all_dynamic_info() -> Vec>>; fn get_all_metagraphs() -> Vec>>; - fn get_metagraph(netuid: u16) -> Option>; - fn get_dynamic_info(netuid: u16) -> Option>; - fn get_subnet_state(netuid: u16) -> Option>; - fn get_selective_metagraph(netuid: u16, metagraph_indexes: Vec) -> Option>; + fn get_metagraph(netuid: NetUid) -> Option>; + fn get_dynamic_info(netuid: NetUid) -> Option>; + fn get_subnet_state(netuid: NetUid) -> Option>; + fn get_selective_metagraph(netuid: NetUid, metagraph_indexes: Vec) -> Option>; } pub trait StakeInfoRuntimeApi { fn get_stake_info_for_coldkey( coldkey_account: AccountId32 ) -> Vec>; fn get_stake_info_for_coldkeys( coldkey_accounts: Vec ) -> Vec<(AccountId32, Vec>)>; - fn get_stake_info_for_hotkey_coldkey_netuid( hotkey_account: AccountId32, coldkey_account: AccountId32, netuid: u16 ) -> Option>; - fn get_stake_fee( origin: Option<(AccountId32, u16)>, origin_coldkey_account: AccountId32, destination: Option<(AccountId32, u16)>, destination_coldkey_account: AccountId32, amount: u64 ) -> u64; + fn get_stake_info_for_hotkey_coldkey_netuid( hotkey_account: AccountId32, coldkey_account: AccountId32, netuid: NetUid ) -> Option>; + fn get_stake_fee( origin: Option<(AccountId32, NetUid)>, origin_coldkey_account: AccountId32, destination: Option<(AccountId32, NetUid)>, destination_coldkey_account: AccountId32, amount: u64 ) -> u64; } pub trait SubnetRegistrationRuntimeApi { diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index a7cd03e652..c62d1dcecc 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -22,7 +22,7 @@ mod pallet_benchmarks { #[benchmark] fn register() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let hotkey: T::AccountId = account("Alice", 0, 1); let coldkey: T::AccountId = account("Test", 0, 2); @@ -49,7 +49,7 @@ mod pallet_benchmarks { #[benchmark] fn set_weights() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 1; let tempo: u16 = 1; @@ -98,7 +98,7 @@ mod pallet_benchmarks { #[benchmark] fn become_delegate() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; Subtensor::::init_new_network(netuid, tempo); @@ -125,7 +125,7 @@ mod pallet_benchmarks { #[benchmark] fn add_stake() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; Subtensor::::init_new_network(netuid, tempo); @@ -156,177 +156,9 @@ mod pallet_benchmarks { ); } - // #[benchmark] - // fn add_stake_aggregate() { - // let netuid: u16 = 1; - // let tempo: u16 = 1; - // - // Subtensor::::init_new_network(netuid, tempo); - // SubtokenEnabled::::insert(netuid, true); - // Subtensor::::set_burn(netuid, 1); - // Subtensor::::set_network_registration_allowed(netuid, true); - // Subtensor::::set_max_allowed_uids(netuid, 4096); - // - // let seed: u32 = 1; - // let coldkey: T::AccountId = account("Test", 0, seed); - // let hotkey: T::AccountId = account("Alice", 0, seed); - // let total_stake: u64 = 1_000_000_000; - // let amount: u64 = 600_000; - // - // Subtensor::::add_balance_to_coldkey_account(&coldkey, total_stake); - // assert_ok!(Subtensor::::do_burned_registration( - // RawOrigin::Signed(coldkey.clone()).into(), - // netuid, - // hotkey.clone() - // )); - // - // #[extrinsic_call] - // _( - // RawOrigin::Signed(coldkey.clone()), - // hotkey.clone(), - // netuid, - // amount, - // ); - // } - // - // #[benchmark] - // fn remove_stake_limit_aggregate() { - // let netuid: u16 = 1; - // - // Subtensor::::increase_total_stake(1_000_000_000_000); - // Subtensor::::init_new_network(netuid, 1); - // Subtensor::::set_network_registration_allowed(netuid, true); - // SubtokenEnabled::::insert(netuid, true); - // Subtensor::::set_max_allowed_uids(netuid, 4096); - // - // let seed: u32 = 1; - // let coldkey: T::AccountId = account("Test", 0, seed); - // let hotkey: T::AccountId = account("Alice", 0, seed); - // Subtensor::::set_burn(netuid, 1); - // - // let limit: u64 = 1_000_000_000; - // let tao_reserve: u64 = 150_000_000_000; - // let alpha_in: u64 = 100_000_000_000; - // SubnetTAO::::insert(netuid, tao_reserve); - // SubnetAlphaIn::::insert(netuid, alpha_in); - // - // let wallet_bal: u64 = 1_000_000; - // Subtensor::::add_balance_to_coldkey_account(&coldkey, wallet_bal); - // - // assert_ok!(Subtensor::::do_burned_registration( - // RawOrigin::Signed(coldkey.clone()).into(), - // netuid, - // hotkey.clone() - // )); - // - // Subtensor::::add_balance_to_coldkey_account(&coldkey, 100_000_000_000u64); - // assert_ok!(Subtensor::::add_stake( - // RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // 100_000_000_000u64 - // )); - // - // let amount_unstaked: u64 = 30_000_000_000; - // - // #[extrinsic_call] - // _( - // RawOrigin::Signed(coldkey.clone()), - // hotkey.clone(), - // netuid, - // amount_unstaked, - // limit, - // false, - // ); - // } - // - // #[benchmark] - // fn remove_stake_aggregate() { - // let netuid: u16 = 1; - // - // Subtensor::::increase_total_stake(1_000_000_000_000); - // Subtensor::::init_new_network(netuid, 1); - // Subtensor::::set_network_registration_allowed(netuid, true); - // SubtokenEnabled::::insert(netuid, true); - // Subtensor::::set_max_allowed_uids(netuid, 4096); - // - // let seed: u32 = 1; - // let coldkey: T::AccountId = account("Test", 0, seed); - // let hotkey: T::AccountId = account("Alice", 0, seed); - // Subtensor::::set_burn(netuid, 1); - // - // let wallet_bal: u64 = 1_000_000; - // Subtensor::::add_balance_to_coldkey_account(&coldkey, wallet_bal); - // - // assert_ok!(Subtensor::::do_burned_registration( - // RawOrigin::Signed(coldkey.clone()).into(), - // netuid, - // hotkey.clone() - // )); - // - // Subtensor::::add_balance_to_coldkey_account(&coldkey, 100_000_000_000u64); - // assert_ok!(Subtensor::::add_stake( - // RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // 100_000_000_000u64 - // )); - // - // let amount_unstaked: u64 = 600_000; - // - // #[extrinsic_call] - // _( - // RawOrigin::Signed(coldkey.clone()), - // hotkey.clone(), - // netuid, - // amount_unstaked, - // ); - // } - // - // #[benchmark] - // fn add_stake_limit_aggregate() { - // let netuid: u16 = 1; - // - // Subtensor::::init_new_network(netuid, 1); - // SubtokenEnabled::::insert(netuid, true); - // Subtensor::::set_burn(netuid, 1); - // Subtensor::::set_network_registration_allowed(netuid, true); - // Subtensor::::set_max_allowed_uids(netuid, 4096); - // - // let seed: u32 = 1; - // let coldkey: T::AccountId = account("Test", 0, seed); - // let hotkey: T::AccountId = account("Alice", 0, seed); - // - // let amount: u64 = 900_000_000_000; - // let limit: u64 = 6_000_000_000; - // let stake_amt: u64 = 440_000_000_000; - // Subtensor::::add_balance_to_coldkey_account(&coldkey, amount); - // - // let tao_reserve: u64 = 150_000_000_000; - // let alpha_in: u64 = 100_000_000_000; - // SubnetTAO::::insert(netuid, tao_reserve); - // SubnetAlphaIn::::insert(netuid, alpha_in); - // - // assert_ok!(Subtensor::::do_burned_registration( - // RawOrigin::Signed(coldkey.clone()).into(), - // netuid, - // hotkey.clone() - // )); - // - // #[extrinsic_call] - // _( - // RawOrigin::Signed(coldkey.clone()), - // hotkey.clone(), - // netuid, - // stake_amt, - // limit, - // false, - // ); - // } - #[benchmark] fn serve_axon() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let caller: T::AccountId = whitelisted_caller(); let version: u32 = 2; let ip: u128 = 1676056785; @@ -367,7 +199,7 @@ mod pallet_benchmarks { #[benchmark] fn serve_prometheus() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let caller: T::AccountId = whitelisted_caller(); let version: u32 = 2; let ip: u128 = 1676056785; @@ -402,7 +234,7 @@ mod pallet_benchmarks { #[benchmark] fn burned_register() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let seed: u32 = 1; let hotkey: T::AccountId = account("Alice", 0, seed); let coldkey: T::AccountId = account("Test", 0, seed); @@ -420,7 +252,7 @@ mod pallet_benchmarks { #[benchmark] fn root_register() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let seed: u32 = 1; let coldkey: T::AccountId = account("Test", 0, seed); let hotkey: T::AccountId = account("Alice", 0, seed); @@ -462,7 +294,7 @@ mod pallet_benchmarks { #[benchmark] fn commit_weights() { let tempo: u16 = 1; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let uids: Vec = vec![0]; let weight_values: Vec = vec![10]; @@ -507,7 +339,7 @@ mod pallet_benchmarks { #[benchmark] fn reveal_weights() { let tempo: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let uids: Vec = vec![0]; let weight_values: Vec = vec![10]; @@ -582,7 +414,7 @@ mod pallet_benchmarks { #[benchmark] fn set_childkey_take() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey: T::AccountId = account("Cold", 0, 1); let hotkey: T::AccountId = account("Hot", 0, 1); let take: u16 = 1000; @@ -615,7 +447,7 @@ mod pallet_benchmarks { let old_coldkey: T::AccountId = account("old_coldkey", 0, 0); let new_coldkey: T::AccountId = account("new_coldkey", 0, 0); let hotkey1: T::AccountId = account("hotkey1", 0, 0); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let swap_cost: u64 = Subtensor::::get_key_swap_cost(); let free_balance_old: u64 = 12345 + swap_cost; @@ -660,7 +492,7 @@ mod pallet_benchmarks { #[benchmark] fn batch_reveal_weights() { let tempo: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let num_commits: usize = 10; let hotkey: T::AccountId = account("hot", 0, 1); @@ -732,7 +564,7 @@ mod pallet_benchmarks { #[benchmark] fn recycle_alpha() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey: T::AccountId = account("Test", 0, 1); let hotkey: T::AccountId = account("Alice", 0, 1); @@ -773,7 +605,7 @@ mod pallet_benchmarks { #[benchmark] fn burn_alpha() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey: T::AccountId = account("Test", 0, 1); let hotkey: T::AccountId = account("Alice", 0, 1); @@ -811,7 +643,7 @@ mod pallet_benchmarks { #[benchmark] fn start_call() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey: T::AccountId = account("Test", 0, 1); let hotkey: T::AccountId = account("Alice", 0, 1); @@ -848,10 +680,9 @@ mod pallet_benchmarks { fn adjust_senate() { let coldkey: T::AccountId = whitelisted_caller(); let hotkey: T::AccountId = account("Alice", 0, 1); - let root: u16 = Subtensor::::get_root_netuid(); - Subtensor::::init_new_network(root, 1); - Uids::::insert(root, &hotkey, 0u16); + Subtensor::::init_new_network(NetUid::ROOT, 1); + Uids::::insert(NetUid::ROOT, &hotkey, 0u16); #[extrinsic_call] _(RawOrigin::Signed(coldkey.clone()), hotkey.clone()); @@ -859,7 +690,7 @@ mod pallet_benchmarks { #[benchmark] fn add_stake_limit() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let seed: u32 = 1; @@ -874,7 +705,7 @@ mod pallet_benchmarks { let amount = 900_000_000_000; let limit: u64 = 6_000_000_000; - let amount_to_be_staked = 440_000_000_000; + let amount_to_be_staked = 44_000_000_000; Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount); let tao_reserve = 150_000_000_000_u64; @@ -904,7 +735,7 @@ mod pallet_benchmarks { let coldkey: T::AccountId = whitelisted_caller(); let origin: T::AccountId = account("A", 0, 1); let destination: T::AccountId = account("B", 0, 2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); SubtokenEnabled::::insert(netuid, true); Subtensor::::init_new_network(netuid, 1); @@ -951,7 +782,7 @@ mod pallet_benchmarks { #[benchmark] fn remove_stake_limit() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let seed: u32 = 1; @@ -1011,8 +842,8 @@ mod pallet_benchmarks { fn swap_stake_limit() { let coldkey: T::AccountId = whitelisted_caller::>(); let hot: T::AccountId = account("A", 0, 1); - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let allow: bool = true; SubtokenEnabled::::insert(netuid1, true); @@ -1073,7 +904,7 @@ mod pallet_benchmarks { let coldkey: T::AccountId = whitelisted_caller(); let dest: T::AccountId = account("B", 0, 2); let hot: T::AccountId = account("A", 0, 1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); SubtokenEnabled::::insert(netuid, true); Subtensor::::init_new_network(netuid, 1); @@ -1122,8 +953,8 @@ mod pallet_benchmarks { fn swap_stake() { let coldkey: T::AccountId = whitelisted_caller(); let hot: T::AccountId = account("A", 0, 9); - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); SubtokenEnabled::::insert(netuid1, true); Subtensor::::init_new_network(netuid1, 1); @@ -1172,9 +1003,9 @@ mod pallet_benchmarks { #[benchmark] fn batch_commit_weights() { let hotkey: T::AccountId = whitelisted_caller(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let count: usize = 3; - let mut netuids: Vec> = Vec::new(); + let mut netuids: Vec> = Vec::new(); let mut hashes: Vec = Vec::new(); Subtensor::::init_new_network(netuid, 1); @@ -1209,10 +1040,10 @@ mod pallet_benchmarks { #[benchmark] fn batch_set_weights() { let hotkey: T::AccountId = whitelisted_caller(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version: u64 = 1; let entries: Vec<(Compact, Compact)> = vec![(Compact(0u16), Compact(0u16))]; - let netuids: Vec> = vec![Compact(netuid)]; + let netuids: Vec> = vec![Compact(netuid)]; let weights: Vec, Compact)>> = vec![entries.clone()]; let keys: Vec> = vec![Compact(version)]; @@ -1241,7 +1072,7 @@ mod pallet_benchmarks { #[benchmark] fn commit_crv3_weights() { let hotkey: T::AccountId = whitelisted_caller(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let vec_commit: Vec = vec![0; MAX_CRV3_COMMIT_SIZE_BYTES as usize]; let commit: BoundedVec<_, _> = vec_commit.try_into().unwrap(); let round: u64 = 0; @@ -1300,9 +1131,9 @@ mod pallet_benchmarks { fn register_network_with_identity() { let coldkey: T::AccountId = whitelisted_caller(); let hotkey: T::AccountId = account("Alice", 0, 1); - let identity: Option = None; + let identity: Option = None; - Subtensor::::set_network_registration_allowed(1, true); + Subtensor::::set_network_registration_allowed(1.into(), true); Subtensor::::set_network_rate_limit(1); let amount: u64 = 9_999_999_999_999; Subtensor::::add_balance_to_coldkey_account(&coldkey, amount); @@ -1318,7 +1149,7 @@ mod pallet_benchmarks { #[benchmark] fn serve_axon_tls() { let caller: T::AccountId = whitelisted_caller(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version: u32 = 1; let ip: u128 = 0xC0A8_0001; let port: u16 = 30333; @@ -1370,14 +1201,14 @@ mod pallet_benchmarks { let add = vec![]; Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); - Subtensor::::init_new_network(1, 1); + Subtensor::::init_new_network(1.into(), 1); let deposit: u64 = 1_000_000_000u64.saturating_mul(2); Subtensor::::add_balance_to_coldkey_account(&coldkey, deposit); - SubtokenEnabled::::insert(1, true); + SubtokenEnabled::::insert(NetUid::from(1), true); assert_ok!(Subtensor::::burned_register( RawOrigin::Signed(coldkey.clone()).into(), - 1, + 1.into(), hotkey.clone() )); @@ -1397,13 +1228,14 @@ mod pallet_benchmarks { #[benchmark] fn set_subnet_identity() { let coldkey: T::AccountId = whitelisted_caller(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let name = b"n".to_vec(); let repo = vec![]; let contact = vec![]; let url = vec![]; let disc = vec![]; let descr = vec![]; + let logo_url = vec![]; let add = vec![]; SubnetOwner::::insert(netuid, coldkey.clone()); @@ -1419,13 +1251,14 @@ mod pallet_benchmarks { url.clone(), disc.clone(), descr.clone(), + logo_url.clone(), add.clone(), ); } #[benchmark] fn set_tao_weights() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: T::AccountId = account("A", 0, 6); let dests = vec![0u16]; let weights = vec![0u16]; @@ -1454,7 +1287,12 @@ mod pallet_benchmarks { Subtensor::::add_balance_to_coldkey_account(&coldkey, cost); #[extrinsic_call] - _(RawOrigin::Signed(coldkey.clone()), old.clone(), new.clone()); + _( + RawOrigin::Signed(coldkey.clone()), + old.clone(), + new.clone(), + None, + ); } #[benchmark] @@ -1478,11 +1316,43 @@ mod pallet_benchmarks { #[benchmark] fn unstake_all_alpha() { - let coldkey: T::AccountId = whitelisted_caller(); - let hotkey: T::AccountId = account("A", 0, 15); - Subtensor::::create_account_if_non_existent(&coldkey, &hotkey); + let netuid = NetUid::from(1); + let tempo: u16 = 1; + let seed: u32 = 1; + + Subtensor::::init_new_network(netuid, tempo); + Subtensor::::set_network_registration_allowed(netuid, true); + SubtokenEnabled::::insert(netuid, true); + + Subtensor::::set_max_allowed_uids(netuid, 4096); + assert_eq!(Subtensor::::get_max_allowed_uids(netuid), 4096); + + let coldkey: T::AccountId = account("Test", 0, seed); + let hotkey: T::AccountId = account("Alice", 0, seed); + Subtensor::::set_burn(netuid, 1); + + SubnetTAO::::insert(netuid, 150_000_000_000); + SubnetAlphaIn::::insert(netuid, 100_000_000_000); + + Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 1000000u32.into()); + + assert_ok!(Subtensor::::do_burned_registration( + RawOrigin::Signed(coldkey.clone()).into(), + netuid, + hotkey.clone() + )); + + let staked_amt = 100_000_000_000; + Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), staked_amt); + + assert_ok!(Subtensor::::add_stake( + RawOrigin::Signed(coldkey.clone()).into(), + hotkey.clone(), + netuid, + staked_amt + )); #[extrinsic_call] - _(RawOrigin::Signed(coldkey.clone()), hotkey.clone()); + _(RawOrigin::Signed(coldkey), hotkey); } } diff --git a/pallets/subtensor/src/coinbase/block_emission.rs b/pallets/subtensor/src/coinbase/block_emission.rs index cd9d778b8a..4f6fb9d95f 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -5,6 +5,8 @@ use substrate_fixed::{ transcendental::log2, types::{I96F32, U96F32}, }; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; impl Pallet { /// Calculates the dynamic TAO emission for a given subnet. @@ -29,7 +31,7 @@ impl Pallet { /// It also ensures that the total amount of alpha_in_emission + alpha_out_emission sum to 2 * alpha_block_emission /// It also ensures that 1 < alpha_out_emission < 2 * alpha_block_emission and 0 < alpha_in_emission < alpha_block_emission. pub fn get_dynamic_tao_emission( - netuid: u16, + netuid: NetUid, tao_emission: u64, alpha_block_emission: u64, ) -> (u64, u64, u64) { @@ -38,7 +40,7 @@ impl Pallet { let float_alpha_block_emission: U96F32 = U96F32::saturating_from_num(alpha_block_emission); // Get alpha price for subnet. - let alpha_price: U96F32 = Self::get_alpha_price(netuid); + let alpha_price = T::SwapInterface::current_alpha_price(netuid.into()); log::debug!("{:?} - alpha_price: {:?}", netuid, alpha_price); // Get initial alpha_in diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index a7e658e89a..d003a698e3 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -1,7 +1,7 @@ use super::*; -use frame_support::storage::IterableStorageMap; use safe_math::*; use substrate_fixed::types::{U96F32, U110F18}; +use subtensor_runtime_common::NetUid; impl Pallet { /// Executes the necessary operations for each block. @@ -23,8 +23,7 @@ impl Pallet { } fn try_set_pending_children(block_number: u64) { - let subnets: Vec = Self::get_all_subnet_netuids(); - for &netuid in subnets.iter() { + for netuid in Self::get_all_subnet_netuids() { if Self::should_run_epoch(netuid, block_number) { // Set pending children on the epoch. Self::do_set_pending_children(netuid); @@ -38,7 +37,7 @@ impl Pallet { log::debug!("adjust_registration_terms_for_networks"); // --- 1. Iterate through each network. - for (netuid, _) in as IterableStorageMap>::iter() { + for (netuid, _) in NetworksAdded::::iter() { // --- 2. Pull counters for network difficulty. let last_adjustment_block: u64 = Self::get_last_adjustment_block(netuid); let adjustment_interval: u16 = Self::get_adjustment_interval(netuid); @@ -194,7 +193,7 @@ impl Pallet { /// We use U110F18 to avoid any overflows on u64. Also min_difficulty and max_difficulty bound the range. /// pub fn upgraded_difficulty( - netuid: u16, + netuid: NetUid, current_difficulty: u64, registrations_this_interval: u16, target_registrations_per_interval: u16, @@ -228,7 +227,7 @@ impl Pallet { /// We use U110F18 to avoid any overflows on u64. Also min_burn and max_burn bound the range. /// pub fn upgraded_burn( - netuid: u16, + netuid: NetUid, current_burn: u64, registrations_this_interval: u16, target_registrations_per_interval: u16, diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index 1f3a91b339..add7ae3d8f 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -21,8 +21,8 @@ use frame_support::storage::IterableStorageDoubleMap; use frame_support::weights::Weight; use safe_math::*; use sp_core::Get; -use sp_std::vec; use substrate_fixed::types::I64F64; +use subtensor_runtime_common::NetUid; impl Pallet { /// Fetches the total count of root network validators @@ -33,7 +33,7 @@ impl Pallet { /// * 'u16': The total number of root network validators /// pub fn get_num_root_validators() -> u16 { - Self::get_subnetwork_n(Self::get_root_netuid()) + Self::get_subnetwork_n(NetUid::ROOT) } /// Fetches the max validators count of root network. @@ -44,7 +44,7 @@ impl Pallet { /// * 'u16': The max validators count of root network. /// pub fn get_max_root_validators() -> u16 { - Self::get_max_allowed_uids(Self::get_root_netuid()) + Self::get_max_allowed_uids(NetUid::ROOT) } /// Checks for any UIDs in the given list that are either equal to the root netuid or exceed the total number of subnets. @@ -57,7 +57,7 @@ impl Pallet { /// # Returns: /// * 'bool': 'true' if any of the UIDs are invalid, 'false' otherwise. /// - pub fn contains_invalid_root_uids(netuids: &[u16]) -> bool { + pub fn contains_invalid_root_uids(netuids: &[NetUid]) -> bool { for netuid in netuids { if !Self::if_subnet_exist(*netuid) { log::debug!( @@ -70,56 +70,6 @@ impl Pallet { false } - /// Retrieves weight matrix associated with the root network. - /// Weights represent the preferences for each subnetwork. - /// - /// # Returns: - /// A 2D vector ('Vec>') where each entry [i][j] represents the weight of subnetwork - /// 'j' with according to the preferences of key. Validator 'i' within the root network. - /// - pub fn get_root_weights() -> Vec> { - // --- 0. The number of validators on the root network. - let n: usize = Self::get_num_root_validators() as usize; - - // --- 1 The number of subnets to validate. - log::debug!("subnet size before cast: {:?}", Self::get_num_subnets()); - let k: usize = Self::get_num_subnets() as usize; - log::debug!("n: {:?} k: {:?}", n, k); - - // --- 2. Initialize a 2D vector with zeros to store the weights. The dimensions are determined - // by `n` (number of validators) and `k` (total number of subnets). - let mut weights: Vec> = vec![vec![I64F64::saturating_from_num(0.0); k]; n]; - log::debug!("weights:\n{:?}\n", weights); - - let subnet_list = Self::get_all_subnet_netuids(); - - // --- 3. Iterate over stored weights and fill the matrix. - for (uid_i, weights_i) in - as IterableStorageDoubleMap>>::iter_prefix( - Self::get_root_netuid(), - ) - { - // --- 4. Iterate over each weight entry in `weights_i` to update the corresponding value in the - // initialized `weights` 2D vector. Here, `uid_j` represents a subnet, and `weight_ij` is the - // weight of `uid_i` with respect to `uid_j`. - for (netuid, weight_ij) in &weights_i { - let idx = uid_i as usize; - if let Some(weight) = weights.get_mut(idx) { - if let Some((w, _)) = weight - .iter_mut() - .zip(&subnet_list) - .find(|(_, subnet)| *subnet == netuid) - { - *w = I64F64::saturating_from_num(*weight_ij); - } - } - } - } - - // --- 5. Return the filled weights matrix. - weights - } - /// Registers a user's hotkey to the root network. /// /// This function is responsible for registering the hotkey of a user. @@ -134,10 +84,9 @@ impl Pallet { /// pub fn do_root_register(origin: T::RuntimeOrigin, hotkey: T::AccountId) -> DispatchResult { // --- 0. Get the unique identifier (UID) for the root network. - let root_netuid: u16 = Self::get_root_netuid(); let current_block_number: u64 = Self::get_current_block_as_u64(); ensure!( - Self::if_subnet_exist(root_netuid), + Self::if_subnet_exist(NetUid::ROOT), Error::::RootNetworkDoesNotExist ); @@ -151,21 +100,21 @@ impl Pallet { // --- 2. Ensure that the number of registrations in this block doesn't exceed the allowed limit. ensure!( - Self::get_registrations_this_block(root_netuid) - < Self::get_max_registrations_per_block(root_netuid), + Self::get_registrations_this_block(NetUid::ROOT) + < Self::get_max_registrations_per_block(NetUid::ROOT), Error::::TooManyRegistrationsThisBlock ); // --- 3. Ensure that the number of registrations in this interval doesn't exceed thrice the target limit. ensure!( - Self::get_registrations_this_interval(root_netuid) - < Self::get_target_registrations_per_interval(root_netuid).saturating_mul(3), + Self::get_registrations_this_interval(NetUid::ROOT) + < Self::get_target_registrations_per_interval(NetUid::ROOT).saturating_mul(3), Error::::TooManyRegistrationsThisInterval ); // --- 4. Check if the hotkey is already registered. If so, error out. ensure!( - !Uids::::contains_key(root_netuid, &hotkey), + !Uids::::contains_key(NetUid::ROOT, &hotkey), Error::::HotKeyAlreadyRegisteredInSubNet ); @@ -185,7 +134,7 @@ impl Pallet { subnetwork_uid = current_num_root_validators; // --- 12.1.2 Add the new account and make them a member of the Senate. - Self::append_neuron(root_netuid, &hotkey, current_block_number); + Self::append_neuron(NetUid::ROOT, &hotkey, current_block_number); log::debug!("add new neuron: {:?} on uid {:?}", hotkey, subnetwork_uid); } else { // --- 13.1.1 The network is full. Perform replacement. @@ -194,12 +143,8 @@ impl Pallet { let mut lowest_uid: u16 = 0; // Iterate over all keys in the root network to find the neuron with the lowest stake. - for (uid_i, hotkey_i) in - as IterableStorageDoubleMap>::iter_prefix( - root_netuid, - ) - { - let stake_i: u64 = Self::get_stake_for_hotkey_on_subnet(&hotkey_i, 0); + for (uid_i, hotkey_i) in Keys::::iter_prefix(NetUid::ROOT) { + let stake_i = Self::get_stake_for_hotkey_on_subnet(&hotkey_i, NetUid::ROOT); if stake_i < lowest_stake { lowest_stake = stake_i; lowest_uid = uid_i; @@ -207,17 +152,17 @@ impl Pallet { } subnetwork_uid = lowest_uid; let replaced_hotkey: T::AccountId = - Self::get_hotkey_for_net_and_uid(root_netuid, subnetwork_uid)?; + Self::get_hotkey_for_net_and_uid(NetUid::ROOT, subnetwork_uid)?; // --- 13.1.2 The new account has a higher stake than the one being replaced. ensure!( - lowest_stake < Self::get_stake_for_hotkey_on_subnet(&hotkey, 0), + lowest_stake < Self::get_stake_for_hotkey_on_subnet(&hotkey, NetUid::ROOT), Error::::StakeTooLowForRoot ); // --- 13.1.3 The new account has a higher stake than the one being replaced. // Replace the neuron account with new information. - Self::replace_neuron(root_netuid, lowest_uid, &hotkey, current_block_number); + Self::replace_neuron(NetUid::ROOT, lowest_uid, &hotkey, current_block_number); log::debug!( "replace neuron: {:?} with {:?} on uid {:?}", @@ -239,19 +184,23 @@ impl Pallet { // --- 15. Update the registration counters for both the block and interval. #[allow(clippy::arithmetic_side_effects)] // note this RA + clippy false positive is a known substrate issue - RegistrationsThisInterval::::mutate(root_netuid, |val| *val += 1); + RegistrationsThisInterval::::mutate(NetUid::ROOT, |val| *val += 1); #[allow(clippy::arithmetic_side_effects)] // note this RA + clippy false positive is a known substrate issue - RegistrationsThisBlock::::mutate(root_netuid, |val| *val += 1); + RegistrationsThisBlock::::mutate(NetUid::ROOT, |val| *val += 1); // --- 16. Log and announce the successful registration. log::debug!( "RootRegistered(netuid:{:?} uid:{:?} hotkey:{:?})", - root_netuid, + NetUid::ROOT, subnetwork_uid, hotkey ); - Self::deposit_event(Event::NeuronRegistered(root_netuid, subnetwork_uid, hotkey)); + Self::deposit_event(Event::NeuronRegistered( + NetUid::ROOT, + subnetwork_uid, + hotkey, + )); // --- 17. Finish and return success. Ok(()) @@ -270,10 +219,8 @@ impl Pallet { // * 'DispatchResult': A result type indicating success or failure of the registration. // pub fn do_adjust_senate(origin: T::RuntimeOrigin, hotkey: T::AccountId) -> DispatchResult { - // --- 0. Get the unique identifier (UID) for the root network. - let root_netuid: u16 = Self::get_root_netuid(); ensure!( - Self::if_subnet_exist(root_netuid), + Self::if_subnet_exist(NetUid::ROOT), Error::::RootNetworkDoesNotExist ); @@ -287,7 +234,7 @@ impl Pallet { // --- 2. Check if the hotkey is already registered to the root network. If not, error out. ensure!( - Uids::::contains_key(root_netuid, &hotkey), + Uids::::contains_key(NetUid::ROOT, &hotkey), Error::::HotKeyNotRegisteredInSubNet ); @@ -332,12 +279,9 @@ impl Pallet { // * 'Result, Error>': A result containing the replaced member, if any. // fn join_senate_if_eligible(hotkey: &T::AccountId) -> Result, Error> { - // Get the root network UID. - let root_netuid: u16 = Self::get_root_netuid(); - // --- 1. Check the hotkey is registered in the root network. ensure!( - Uids::::contains_key(root_netuid, hotkey), + Uids::::contains_key(NetUid::ROOT, hotkey), Error::::HotKeyNotRegisteredInSubNet ); @@ -348,7 +292,7 @@ impl Pallet { ); // --- 3. Grab the hotkey's stake. - let current_stake = Self::get_stake_for_hotkey_on_subnet(hotkey, Self::get_root_netuid()); + let current_stake = Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT); // Add the hotkey to the Senate. // If we're full, we'll swap out the lowest stake member. @@ -357,15 +301,14 @@ impl Pallet { if (members.len() as u32) == T::SenateMembers::max_members() { let mut sorted_members = members.clone(); sorted_members.sort_by(|a, b| { - let a_stake = Self::get_stake_for_hotkey_on_subnet(a, Self::get_root_netuid()); - let b_stake = Self::get_stake_for_hotkey_on_subnet(b, Self::get_root_netuid()); + let a_stake = Self::get_stake_for_hotkey_on_subnet(a, NetUid::ROOT); + let b_stake = Self::get_stake_for_hotkey_on_subnet(b, NetUid::ROOT); b_stake.cmp(&a_stake) }); if let Some(last) = sorted_members.last() { - let last_stake = - Self::get_stake_for_hotkey_on_subnet(last, Self::get_root_netuid()); + let last_stake = Self::get_stake_for_hotkey_on_subnet(last, NetUid::ROOT); if last_stake < current_stake { // Swap the member with the lowest stake. @@ -440,7 +383,7 @@ impl Pallet { /// * 'SubNetworkDoesNotExist': If the specified network does not exist. /// * 'NotSubnetOwner': If the caller does not own the specified subnet. /// - pub fn user_remove_network(coldkey: T::AccountId, netuid: u16) -> dispatch::DispatchResult { + pub fn user_remove_network(coldkey: T::AccountId, netuid: NetUid) -> dispatch::DispatchResult { // --- 1. Ensure this subnet exists. ensure!( Self::if_subnet_exist(netuid), @@ -454,7 +397,7 @@ impl Pallet { ); // --- 4. Remove the subnet identity if it exists. - if SubnetIdentitiesV2::::take(netuid).is_some() { + if SubnetIdentitiesV3::::take(netuid).is_some() { Self::deposit_event(Event::SubnetIdentityRemoved(netuid)); } @@ -481,7 +424,7 @@ impl Pallet { /// # Note: /// This function does not emit any events, nor does it raise any errors. It silently /// returns if any internal checks fail. - pub fn remove_network(netuid: u16) { + pub fn remove_network(netuid: NetUid) { // --- 1. Return balance to subnet owner. let owner_coldkey: T::AccountId = SubnetOwner::::get(netuid); let reserved_amount: u64 = Self::get_subnet_locked_balance(netuid); @@ -512,20 +455,20 @@ impl Pallet { // --- 9. Iterate over stored weights and fill the matrix. for (uid_i, weights_i) in - as IterableStorageDoubleMap>>::iter_prefix( - Self::get_root_netuid(), + as IterableStorageDoubleMap>>::iter_prefix( + NetUid::ROOT, ) { // Create a new vector to hold modified weights. - let mut modified_weights: Vec<(u16, u16)> = weights_i.clone(); + let mut modified_weights = weights_i.clone(); // Iterate over each weight entry to potentially update it. for (subnet_id, weight) in modified_weights.iter_mut() { - if subnet_id == &netuid { + if subnet_id == &u16::from(netuid) { // If the condition matches, modify the weight *weight = 0; // Set weight to 0 for the matching subnet_id. } } - Weights::::insert(Self::get_root_netuid(), uid_i, modified_weights); + Weights::::insert(NetUid::ROOT, uid_i, modified_weights); } // --- 10. Remove various network-related parameters. @@ -564,8 +507,8 @@ impl Pallet { SubnetOwner::::remove(netuid); // --- 13. Remove subnet identity if it exists. - if SubnetIdentitiesV2::::contains_key(netuid) { - SubnetIdentitiesV2::::remove(netuid); + if SubnetIdentitiesV3::::contains_key(netuid) { + SubnetIdentitiesV3::::remove(netuid); Self::deposit_event(Event::SubnetIdentityRemoved(netuid)); } } @@ -621,7 +564,7 @@ impl Pallet { lock_cost } - pub fn get_network_registered_block(netuid: u16) -> u64 { + pub fn get_network_registered_block(netuid: NetUid) -> u64 { NetworkRegisteredAt::::get(netuid) } pub fn get_network_immunity_period() -> u64 { diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 00b0c2fa55..0dc8440980 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -2,6 +2,8 @@ use super::*; use alloc::collections::BTreeMap; use safe_math::*; use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; use tle::stream_ciphers::AESGCMStreamCipherProvider; use tle::tlock::tld; @@ -38,13 +40,13 @@ impl Pallet { log::debug!("Current block: {:?}", current_block); // --- 1. Get all netuids (filter out root) - let subnets: Vec = Self::get_all_subnet_netuids() + let subnets: Vec = Self::get_all_subnet_netuids() .into_iter() - .filter(|netuid| *netuid != 0) + .filter(|netuid| *netuid != NetUid::ROOT) .collect(); log::debug!("All subnet netuids: {:?}", subnets); // Filter out subnets with no first emission block number. - let subnets_to_emit_to: Vec = subnets + let subnets_to_emit_to: Vec = subnets .clone() .into_iter() .filter(|netuid| FirstEmissionBlockNumber::::get(*netuid).is_some()) @@ -52,7 +54,7 @@ impl Pallet { log::debug!("Subnets to emit to: {:?}", subnets_to_emit_to); // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) - let mut total_moving_prices: U96F32 = U96F32::saturating_from_num(0.0); + let mut total_moving_prices = U96F32::saturating_from_num(0.0); // Only get price EMA for subnets that we emit to. for netuid_i in subnets_to_emit_to.iter() { // Get and update the moving price of each subnet adding the total together. @@ -63,13 +65,13 @@ impl Pallet { // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) // Computation is described in detail in the dtao whitepaper. - let mut tao_in: BTreeMap = BTreeMap::new(); - let mut alpha_in: BTreeMap = BTreeMap::new(); - let mut alpha_out: BTreeMap = BTreeMap::new(); + let mut tao_in: BTreeMap = BTreeMap::new(); + let mut alpha_in: BTreeMap = BTreeMap::new(); + let mut alpha_out: BTreeMap = BTreeMap::new(); // Only calculate for subnets that we are emitting to. for netuid_i in subnets_to_emit_to.iter() { // Get subnet price. - let price_i: U96F32 = Self::get_alpha_price(*netuid_i); + let price_i = T::SwapInterface::current_alpha_price((*netuid_i).into()); log::debug!("price_i: {:?}", price_i); // Get subnet TAO. let moving_price_i: U96F32 = Self::get_moving_alpha_price(*netuid_i); @@ -137,13 +139,15 @@ impl Pallet { TotalIssuance::::mutate(|total| { *total = total.saturating_add(tao_in_i); }); + // Adjust protocol liquidity based on new reserves + T::SwapInterface::adjust_protocol_liquidity(*netuid_i, tao_in_i, alpha_in_i); } // --- 5. Compute owner cuts and remove them from alpha_out remaining. // Remove owner cuts here so that we can properly seperate root dividends in the next step. // Owner cuts are accumulated and then fed to the drain at the end of this func. let cut_percent: U96F32 = Self::get_float_subnet_owner_cut(); - let mut owner_cuts: BTreeMap = BTreeMap::new(); + let mut owner_cuts: BTreeMap = BTreeMap::new(); for netuid_i in subnets_to_emit_to.iter() { // Get alpha out. let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); @@ -168,7 +172,7 @@ impl Pallet { let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0)); log::debug!("alpha_out_i: {:?}", alpha_out_i); // Get total TAO on root. - let root_tao: U96F32 = asfloat!(SubnetTAO::::get(0)); + let root_tao: U96F32 = asfloat!(SubnetTAO::::get(NetUid::ROOT)); log::debug!("root_tao: {:?}", root_tao); // Get total ALPHA on subnet. let alpha_issuance: U96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i)); @@ -191,20 +195,28 @@ impl Pallet { let pending_alpha: U96F32 = alpha_out_i.saturating_sub(root_alpha); log::debug!("pending_alpha: {:?}", pending_alpha); // Sell root emission through the pool. - let root_tao: u64 = Self::swap_alpha_for_tao(*netuid_i, tou64!(root_alpha)); - log::debug!("root_tao: {:?}", root_tao); - // Accumulate alpha emission in pending. - PendingAlphaSwapped::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(root_alpha)); - }); - // Accumulate alpha emission in pending. - PendingEmission::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(pending_alpha)); - }); - // Accumulate root divs for subnet. - PendingRootDivs::::mutate(*netuid_i, |total| { - *total = total.saturating_add(root_tao); - }); + let swap_result = Self::swap_alpha_for_tao( + *netuid_i, + tou64!(root_alpha), + T::SwapInterface::min_price(), + ); + if let Ok(ok_result) = swap_result { + let root_tao: u64 = ok_result.amount_paid_out; + + log::debug!("root_tao: {:?}", root_tao); + // Accumulate alpha emission in pending. + PendingAlphaSwapped::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(root_alpha)); + }); + // Accumulate alpha emission in pending. + PendingEmission::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(pending_alpha)); + }); + // Accumulate root divs for subnet. + PendingRootDivs::::mutate(*netuid_i, |total| { + *total = total.saturating_add(root_tao); + }); + } } // --- 7 Update moving prices after using them in the emission calculation. @@ -263,7 +275,7 @@ impl Pallet { } pub fn calculate_dividends_and_incentives( - netuid: u16, + netuid: NetUid, hotkey_emission: Vec<(T::AccountId, u64, u64)>, ) -> (BTreeMap, BTreeMap) { // Accumulate emission of dividends and incentive per hotkey. @@ -394,7 +406,7 @@ impl Pallet { } pub fn distribute_dividends_and_incentives( - netuid: u16, + netuid: NetUid, owner_cut: u64, incentives: BTreeMap, alpha_dividends: BTreeMap, @@ -483,16 +495,12 @@ impl Pallet { Self::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &Owner::::get(hotkey.clone()), - Self::get_root_netuid(), + NetUid::ROOT, tou64!(tao_take), ); // Give rest to nominators. log::debug!("hotkey: {:?} root_tao: {:?}", hotkey, root_tao); - Self::increase_stake_for_hotkey_on_subnet( - &hotkey, - Self::get_root_netuid(), - tou64!(root_tao), - ); + Self::increase_stake_for_hotkey_on_subnet(&hotkey, NetUid::ROOT, tou64!(root_tao)); // Record root dividends for this validator on this subnet. TaoDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { *divs = divs.saturating_add(tou64!(root_tao)); @@ -501,7 +509,7 @@ impl Pallet { } pub fn get_stake_map( - netuid: u16, + netuid: NetUid, hotkeys: Vec<&T::AccountId>, ) -> BTreeMap { let mut stake_map: BTreeMap = BTreeMap::new(); @@ -509,15 +517,14 @@ impl Pallet { // Get hotkey ALPHA on subnet. let alpha_stake: u64 = Self::get_stake_for_hotkey_on_subnet(hotkey, netuid); // Get hotkey TAO on root. - let root_stake: u64 = - Self::get_stake_for_hotkey_on_subnet(hotkey, Self::get_root_netuid()); + let root_stake: u64 = Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT); stake_map.insert(hotkey.clone(), (alpha_stake, root_stake)); } stake_map } pub fn calculate_dividend_and_incentive_distribution( - netuid: u16, + netuid: NetUid, pending_tao: u64, pending_validator_alpha: u64, hotkey_emission: Vec<(T::AccountId, u64, u64)>, @@ -547,7 +554,7 @@ impl Pallet { } pub fn drain_pending_emission( - netuid: u16, + netuid: NetUid, pending_alpha: u64, pending_tao: u64, pending_swapped: u64, @@ -610,7 +617,7 @@ impl Pallet { /// Returns the self contribution of a hotkey on a subnet. /// This is the portion of the hotkey's stake that is provided by itself, and not delegated to other hotkeys. - pub fn get_self_contribution(hotkey: &T::AccountId, netuid: u16) -> u64 { + pub fn get_self_contribution(hotkey: &T::AccountId, netuid: NetUid) -> u64 { // Get all childkeys for this hotkey. let childkeys = Self::get_children(hotkey, netuid); let mut remaining_proportion: U96F32 = U96F32::saturating_from_num(1.0); @@ -625,10 +632,8 @@ impl Pallet { let tao_weight: U96F32 = Self::get_tao_weight(); // Get the hotkey's stake including weight - let root_stake: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet( - hotkey, - Self::get_root_netuid(), - )); + let root_stake: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT)); let alpha_stake: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); @@ -658,7 +663,7 @@ impl Pallet { /// pub fn get_parent_child_dividends_distribution( hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, dividends: u64, ) -> Vec<(T::AccountId, u64)> { // hotkey dividends. @@ -711,7 +716,7 @@ impl Pallet { // Get the parent's root and subnet-specific (alpha) stakes let parent_root: U96F32 = U96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(&parent, Self::get_root_netuid()), + Self::get_stake_for_hotkey_on_subnet(&parent, NetUid::ROOT), ); let parent_alpha: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(&parent, netuid)); @@ -813,7 +818,7 @@ impl Pallet { /// /// # Returns /// * `bool` - True if the epoch should run, false otherwise. - pub fn should_run_epoch(netuid: u16, current_block: u64) -> bool { + pub fn should_run_epoch(netuid: NetUid, current_block: u64) -> bool { Self::blocks_until_next_epoch(netuid, Self::get_tempo(netuid), current_block) == 0 } @@ -828,11 +833,11 @@ impl Pallet { /// 100 1 98 /// Special case: tempo = 0, the network never runs. /// - pub fn blocks_until_next_epoch(netuid: u16, tempo: u16, block_number: u64) -> u64 { + pub fn blocks_until_next_epoch(netuid: NetUid, tempo: u16, block_number: u64) -> u64 { if tempo == 0 { return u64::MAX; } - let netuid_plus_one = (netuid as u64).saturating_add(1); + let netuid_plus_one = (u16::from(netuid) as u64).saturating_add(1); let tempo_plus_one = (tempo as u64).saturating_add(1); let adjusted_block = block_number.wrapping_add(netuid_plus_one); let remainder = adjusted_block.checked_rem(tempo_plus_one).unwrap_or(0); @@ -840,7 +845,7 @@ impl Pallet { } /// The `reveal_crv3_commits` function is run at the very beginning of epoch `n`, - pub fn reveal_crv3_commits(netuid: u16) -> dispatch::DispatchResult { + pub fn reveal_crv3_commits(netuid: NetUid) -> dispatch::DispatchResult { use ark_serialize::CanonicalDeserialize; use frame_support::traits::OriginTrait; use tle::curves::drand::TinyBLS381; diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index c550135123..a636cdd9a1 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -4,12 +4,13 @@ use frame_support::IterableStorageDoubleMap; use safe_math::*; use sp_std::vec; use substrate_fixed::types::{I32F32, I64F64, I96F32}; +use subtensor_runtime_common::NetUid; impl Pallet { /// Calculates reward consensus and returns the emissions for uids/hotkeys in a given `netuid`. /// (Dense version used only for testing purposes.) #[allow(clippy::indexing_slicing)] - pub fn epoch_dense(netuid: u16, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { + pub fn epoch_dense(netuid: NetUid, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { // Get subnetwork size. let n: u16 = Self::get_subnetwork_n(netuid); log::trace!("n: {:?}", n); @@ -75,7 +76,7 @@ impl Pallet { // =========== let hotkeys: Vec<(u16, T::AccountId)> = - as IterableStorageDoubleMap>::iter_prefix(netuid) + as IterableStorageDoubleMap>::iter_prefix(netuid) .collect(); log::trace!("hotkeys: {:?}", &hotkeys); @@ -438,7 +439,7 @@ impl Pallet { /// - Print debugging outputs. /// #[allow(clippy::indexing_slicing)] - pub fn epoch(netuid: u16, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { + pub fn epoch(netuid: NetUid, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { // Get subnetwork size. let n: u16 = Self::get_subnetwork_n(netuid); log::trace!("Number of Neurons in Network: {:?}", n); @@ -482,7 +483,7 @@ impl Pallet { // =========== let hotkeys: Vec<(u16, T::AccountId)> = - as IterableStorageDoubleMap>::iter_prefix(netuid) + as IterableStorageDoubleMap>::iter_prefix(netuid) .collect(); log::debug!("hotkeys: {:?}", &hotkeys); @@ -879,19 +880,19 @@ impl Pallet { .collect() } - pub fn get_float_rho(netuid: u16) -> I32F32 { + pub fn get_float_rho(netuid: NetUid) -> I32F32 { I32F32::saturating_from_num(Self::get_rho(netuid)) } - pub fn get_float_kappa(netuid: u16) -> I32F32 { + pub fn get_float_kappa(netuid: NetUid) -> I32F32 { I32F32::saturating_from_num(Self::get_kappa(netuid)) .safe_div(I32F32::saturating_from_num(u16::MAX)) } - pub fn get_float_bonds_penalty(netuid: u16) -> I32F32 { + pub fn get_float_bonds_penalty(netuid: NetUid) -> I32F32 { I32F32::saturating_from_num(Self::get_bonds_penalty(netuid)) .safe_div(I32F32::saturating_from_num(u16::MAX)) } - pub fn get_block_at_registration(netuid: u16) -> Vec { + pub fn get_block_at_registration(netuid: NetUid) -> Vec { let n = Self::get_subnetwork_n(netuid); let block_at_registration: Vec = (0..n) .map(|neuron_uid| { @@ -906,12 +907,14 @@ impl Pallet { } /// Output unnormalized sparse weights, input weights are assumed to be row max-upscaled in u16. - pub fn get_weights_sparse(netuid: u16) -> Vec> { - let n: usize = Self::get_subnetwork_n(netuid) as usize; + pub fn get_weights_sparse(netuid: NetUid) -> Vec> { + let n = Self::get_subnetwork_n(netuid) as usize; let mut weights: Vec> = vec![vec![]; n]; for (uid_i, weights_i) in - as IterableStorageDoubleMap>>::iter_prefix(netuid) - .filter(|(uid_i, _)| *uid_i < n as u16) + as IterableStorageDoubleMap>>::iter_prefix( + netuid, + ) + .filter(|(uid_i, _)| *uid_i < n as u16) { for (uid_j, weight_ij) in weights_i.iter().filter(|(uid_j, _)| *uid_j < n as u16) { weights @@ -924,12 +927,14 @@ impl Pallet { } /// Output unnormalized weights in [n, n] matrix, input weights are assumed to be row max-upscaled in u16. - pub fn get_weights(netuid: u16) -> Vec> { - let n: usize = Self::get_subnetwork_n(netuid) as usize; + pub fn get_weights(netuid: NetUid) -> Vec> { + let n = Self::get_subnetwork_n(netuid) as usize; let mut weights: Vec> = vec![vec![I32F32::saturating_from_num(0.0); n]; n]; for (uid_i, weights_vec) in - as IterableStorageDoubleMap>>::iter_prefix(netuid) - .filter(|(uid_i, _)| *uid_i < n as u16) + as IterableStorageDoubleMap>>::iter_prefix( + netuid, + ) + .filter(|(uid_i, _)| *uid_i < n as u16) { for (uid_j, weight_ij) in weights_vec .into_iter() @@ -947,12 +952,14 @@ impl Pallet { } /// Output unnormalized sparse bonds, input bonds are assumed to be column max-upscaled in u16. - pub fn get_bonds_sparse(netuid: u16) -> Vec> { - let n: usize = Self::get_subnetwork_n(netuid) as usize; + pub fn get_bonds_sparse(netuid: NetUid) -> Vec> { + let n = Self::get_subnetwork_n(netuid) as usize; let mut bonds: Vec> = vec![vec![]; n]; for (uid_i, bonds_vec) in - as IterableStorageDoubleMap>>::iter_prefix(netuid) - .filter(|(uid_i, _)| *uid_i < n as u16) + as IterableStorageDoubleMap>>::iter_prefix( + netuid, + ) + .filter(|(uid_i, _)| *uid_i < n as u16) { for (uid_j, bonds_ij) in bonds_vec { bonds @@ -965,12 +972,14 @@ impl Pallet { } /// Output unnormalized bonds in [n, n] matrix, input bonds are assumed to be column max-upscaled in u16. - pub fn get_bonds(netuid: u16) -> Vec> { + pub fn get_bonds(netuid: NetUid) -> Vec> { let n: usize = Self::get_subnetwork_n(netuid) as usize; let mut bonds: Vec> = vec![vec![I32F32::saturating_from_num(0.0); n]; n]; for (uid_i, bonds_vec) in - as IterableStorageDoubleMap>>::iter_prefix(netuid) - .filter(|(uid_i, _)| *uid_i < n as u16) + as IterableStorageDoubleMap>>::iter_prefix( + netuid, + ) + .filter(|(uid_i, _)| *uid_i < n as u16) { for (uid_j, bonds_ij) in bonds_vec.into_iter().filter(|(uid_j, _)| *uid_j < n as u16) { *bonds @@ -984,7 +993,7 @@ impl Pallet { bonds } - pub fn get_bonds_fixed_proportion(netuid: u16) -> Vec> { + pub fn get_bonds_fixed_proportion(netuid: NetUid) -> Vec> { let mut bonds = Self::get_bonds(netuid); bonds.iter_mut().for_each(|bonds_row| { bonds_row @@ -994,7 +1003,7 @@ impl Pallet { bonds } - pub fn get_bonds_sparse_fixed_proportion(netuid: u16) -> Vec> { + pub fn get_bonds_sparse_fixed_proportion(netuid: NetUid) -> Vec> { let mut bonds = Self::get_bonds_sparse(netuid); bonds.iter_mut().for_each(|bonds_row| { bonds_row @@ -1016,7 +1025,7 @@ impl Pallet { pub fn compute_ema_bonds_normal_sparse( bonds_delta: &[Vec<(u16, I32F32)>], bonds: &[Vec<(u16, I32F32)>], - netuid: u16, + netuid: NetUid, ) -> Vec> { // Retrieve the bonds moving average for the given network ID and scale it down. let bonds_moving_average: I64F64 = @@ -1050,7 +1059,7 @@ impl Pallet { pub fn compute_ema_bonds_normal( bonds_delta: &[Vec], bonds: &[Vec], - netuid: u16, + netuid: NetUid, ) -> Vec> { // Retrieve the bonds moving average for the given network ID and scale it down. let bonds_moving_average: I64F64 = @@ -1084,7 +1093,7 @@ impl Pallet { /// # Returns: /// A vector of EMA bonds. pub fn compute_bonds( - netuid: u16, + netuid: NetUid, weights: &[Vec], // weights_for_bonds bonds: &[Vec], consensus: &[I32F32], @@ -1124,7 +1133,7 @@ impl Pallet { /// # Returns: /// A vector of EMA bonds. pub fn compute_bonds_sparse( - netuid: u16, + netuid: NetUid, weights: &[Vec<(u16, I32F32)>], bonds: &[Vec<(u16, I32F32)>], consensus: &[I32F32], @@ -1164,7 +1173,7 @@ impl Pallet { /// # Returns: /// A matrix of alphas pub fn compute_liquid_alpha_values( - netuid: u16, + netuid: NetUid, weights: &[Vec], // current epoch weights bonds: &[Vec], // previous epoch bonds consensus: &[I32F32], // previous epoch consensus weights @@ -1210,7 +1219,7 @@ impl Pallet { /// # Returns: /// A dense matrix of alphas pub fn compute_liquid_alpha_values_sparse( - netuid: u16, + netuid: NetUid, weights: &[Vec<(u16, I32F32)>], // current epoch weights bonds: &[Vec<(u16, I32F32)>], // previous epoch bonds consensus: &[I32F32], // previous epoch consensus weights @@ -1289,10 +1298,9 @@ impl Pallet { // sigmoid = 1. / (1. + e^(-steepness * (combined_diff - 0.5))) let sigmoid = one.saturating_div( one.saturating_add(safe_exp( - I32F32::from_num(-1).saturating_mul( - alpha_sigmoid_steepness - .saturating_mul(combined_diff.saturating_sub(I32F32::from_num(0.5))), - ), + alpha_sigmoid_steepness + .saturating_div(I32F32::from_num(-100)) + .saturating_mul(combined_diff.saturating_sub(I32F32::from_num(0.5))), )), ); let alpha = @@ -1301,7 +1309,7 @@ impl Pallet { clamp_value(alpha, alpha_low, alpha_high) } - pub fn compute_disabled_liquid_alpha(netuid: u16) -> I32F32 { + pub fn compute_disabled_liquid_alpha(netuid: NetUid) -> I32F32 { // Retrieve the bonds moving average for the given network ID and scale it down. let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid)) .saturating_div(I64F64::from_num(1_000_000)); @@ -1315,7 +1323,7 @@ impl Pallet { pub fn do_set_alpha_values( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, alpha_low: u16, alpha_high: u16, ) -> Result<(), DispatchError> { @@ -1332,14 +1340,15 @@ impl Pallet { ); let max_u16: u32 = u16::MAX as u32; // 65535 - let min_alpha_high: u16 = (max_u16.saturating_mul(4).safe_div(5)) as u16; // 52428 + let min_alpha_low: u16 = (max_u16.safe_div(40)) as u16; // 1638 + let min_alpha_high: u16 = min_alpha_low; // --- 4. Ensure alpha high is greater than the minimum ensure!(alpha_high >= min_alpha_high, Error::::AlphaHighTooLow); // -- 5. Ensure alpha low is within range ensure!( - alpha_low > 0 && alpha_low < min_alpha_high, + alpha_low >= min_alpha_low && alpha_low <= alpha_high, Error::::AlphaLowOutOfRange ); @@ -1354,7 +1363,7 @@ impl Pallet { Ok(()) } - pub fn do_reset_bonds(netuid: u16, account_id: &T::AccountId) -> Result<(), DispatchError> { + pub fn do_reset_bonds(netuid: NetUid, account_id: &T::AccountId) -> Result<(), DispatchError> { // check bonds reset enabled for this subnet let bonds_reset_enabled: bool = Self::get_bonds_reset(netuid); if !bonds_reset_enabled { @@ -1362,11 +1371,7 @@ impl Pallet { } if let Ok(uid) = Self::get_uid_for_net_and_hotkey(netuid, account_id) { - for (i, bonds_vec) in - as IterableStorageDoubleMap>>::iter_prefix( - netuid, - ) - { + for (i, bonds_vec) in Bonds::::iter_prefix(netuid) { Bonds::::insert( netuid, i, diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f4f511e74a..973233bd9e 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -12,10 +12,11 @@ use frame_support::{ dispatch::{self, DispatchInfo, DispatchResult, DispatchResultWithPostInfo, PostDispatchInfo}, ensure, pallet_macros::import_section, + pallet_prelude::*, traits::{IsSubType, tokens::fungible}, }; -use codec::{Decode, Encode}; +use codec::{Decode, DecodeWithMemTracking, Encode}; use frame_support::sp_runtime::transaction_validity::InvalidTransaction; use frame_support::sp_runtime::transaction_validity::ValidTransaction; use pallet_balances::Call as BalancesCall; @@ -24,10 +25,14 @@ use scale_info::TypeInfo; use sp_core::Get; use sp_runtime::{ DispatchError, - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Implication, PostDispatchInfoOf, + TransactionExtension, ValidateResult, + }, transaction_validity::{TransactionValidity, TransactionValidityError}, }; use sp_std::marker::PhantomData; +use subtensor_runtime_common::NetUid; // ============================ // ==== Benchmark Imports ===== @@ -85,6 +90,7 @@ pub mod pallet { use sp_std::vec::Vec; use substrate_fixed::types::{I96F32, U64F64}; use subtensor_macros::freeze_struct; + use subtensor_runtime_common::NetUid; #[cfg(not(feature = "std"))] use alloc::boxed::Box; @@ -248,9 +254,9 @@ pub mod pallet { pub subnet_contact: Vec, } - /// Struct for SubnetIdentitiesV2. + /// Struct for SubnetIdentitiesV2. (DEPRECATED for V3) pub type SubnetIdentityOfV2 = SubnetIdentityV2; - /// Data structure for Subnet Identities + /// Data structure for Subnet Identities (DEPRECATED for V3) #[crate::freeze_struct("e002be4cd05d7b3e")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct SubnetIdentityV2 { @@ -270,77 +276,28 @@ pub mod pallet { pub additional: Vec, } - /// Data structure for stake related jobs. - #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug)] - pub enum StakeJob { - /// Represents a job for "add_stake" operation - AddStake { - /// Hotkey account - hotkey: AccountId, - /// Coldkey account - coldkey: AccountId, - /// Subnet ID - netuid: u16, - /// The amount of stake to be added to the hotkey staking account. - stake_to_be_added: u64, - }, - /// Represents a job for "remove_stake" operation - RemoveStake { - /// Hotkey account - hotkey: AccountId, - /// Coldkey account - coldkey: AccountId, - /// Subnet ID - netuid: u16, - /// Alpha value - alpha_unstaked: u64, - }, - /// Represents a job for "add_stake_limit" operation - AddStakeLimit { - /// Coldkey account - coldkey: AccountId, - /// Hotkey account - hotkey: AccountId, - /// Subnet ID - netuid: u16, - /// The amount of stake to be added to the hotkey staking account. - stake_to_be_added: u64, - /// The limit price expressed in units of RAO per one Alpha. - limit_price: u64, - /// Allows partial execution of the amount. If set to false, this becomes - /// fill or kill type or order. - allow_partial: bool, - }, - /// Represents a job for "remove_stake_limit" operation - RemoveStakeLimit { - /// Coldkey account - coldkey: AccountId, - /// Hotkey account - hotkey: AccountId, - /// Subnet ID - netuid: u16, - /// The amount of stake to be added to the hotkey staking account. - alpha_unstaked: u64, - /// The limit price - limit_price: u64, - /// Allows partial execution of the amount. If set to false, this becomes - /// fill or kill type or order. - allow_partial: bool, - }, - /// Represents a job for "unstake_all" operation - UnstakeAll { - /// Coldkey account - coldkey: AccountId, - /// Hotkey account - hotkey: AccountId, - }, - /// Represents a job for "unstake_all_alpha" operation - UnstakeAllAlpha { - /// Coldkey account - coldkey: AccountId, - /// Hotkey account - hotkey: AccountId, - }, + /// Struct for SubnetIdentitiesV3. + pub type SubnetIdentityOfV3 = SubnetIdentityV3; + /// Data structure for Subnet Identities + #[crate::freeze_struct("3618af6beb882a23")] + #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] + pub struct SubnetIdentityV3 { + /// The name of the subnet + pub subnet_name: Vec, + /// The github repository associated with the subnet + pub github_repo: Vec, + /// The subnet's contact + pub subnet_contact: Vec, + /// The subnet's website + pub subnet_url: Vec, + /// The subnet's discord + pub discord: Vec, + /// The subnet's description + pub description: Vec, + /// The subnet's logo + pub logo_url: Vec, + /// Additional information about the subnet + pub additional: Vec, } /// ============================ @@ -642,7 +599,7 @@ pub mod pallet { } #[pallet::type_value] /// Default value for alpha sigmoid steepness. - pub fn DefaultAlphaSigmoidSteepness() -> u16 { + pub fn DefaultAlphaSigmoidSteepness() -> i16 { T::InitialAlphaSigmoidSteepness::get() } #[pallet::type_value] @@ -847,12 +804,6 @@ pub mod pallet { 500_000 } - #[pallet::type_value] - /// Default staking fee. - pub fn DefaultStakingFee() -> u64 { - 50_000 - } - #[pallet::type_value] /// Default unicode vector for tau symbol. pub fn DefaultUnicodeVecU8() -> Vec { @@ -883,12 +834,6 @@ pub mod pallet { U64F64::saturating_from_num(0) } - #[pallet::type_value] - /// Default value for minimum liquidity in pool - pub fn DefaultMinimumPoolLiquidity() -> I96F32 { - I96F32::saturating_from_num(10_000_000) - } - #[pallet::type_value] /// Default value for minimum activity cutoff pub fn DefaultMinActivityCutoff() -> u16 { @@ -930,14 +875,16 @@ pub mod pallet { StorageValue<_, u64, ValueQuery, DefaultSenateRequiredStakePercentage>; #[pallet::storage] - pub type StakeJobs = StorageDoubleMap< + /// --- DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network. + pub type LastHotkeySwapOnNetuid = StorageDoubleMap< _, + Identity, + NetUid, Blake2_128Concat, - BlockNumberFor, // first key: current block number - Twox64Concat, - u64, // second key: unique job ID - StakeJob, - OptionQuery, + T::AccountId, + u64, + ValueQuery, + DefaultZeroU64, >; #[pallet::storage] @@ -986,8 +933,8 @@ pub mod pallet { Blake2_128Concat, T::AccountId, // First key: hotkey Identity, - u16, // Second key: netuid - u16, // Value: take + NetUid, // Second key: netuid + u16, // Value: take ValueQuery, >; #[pallet::storage] @@ -995,7 +942,7 @@ pub mod pallet { pub type PendingChildKeys = StorageDoubleMap< _, Identity, - u16, + NetUid, Blake2_128Concat, T::AccountId, (Vec<(u64, T::AccountId)>, u64), @@ -1009,7 +956,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, Vec<(u64, T::AccountId)>, ValueQuery, DefaultAccountLinkage, @@ -1021,7 +968,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, Vec<(u64, T::AccountId)>, ValueQuery, DefaultAccountLinkage, @@ -1030,7 +977,7 @@ pub mod pallet { pub type AlphaDividendsPerSubnet = StorageDoubleMap< _, Identity, - u16, + NetUid, Blake2_128Concat, T::AccountId, u64, @@ -1041,7 +988,7 @@ pub mod pallet { pub type TaoDividendsPerSubnet = StorageDoubleMap< _, Identity, - u16, + NetUid, Blake2_128Concat, T::AccountId, u64, @@ -1062,7 +1009,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, u64, ValueQuery, DefaultZeroU64, @@ -1088,28 +1035,35 @@ pub mod pallet { pub type SubnetMovingAlpha = StorageValue<_, I96F32, ValueQuery, DefaultMovingAlpha>; #[pallet::storage] // --- MAP ( netuid ) --> moving_price | The subnet moving price. pub type SubnetMovingPrice = - StorageMap<_, Identity, u16, I96F32, ValueQuery, DefaultMovingPrice>; + StorageMap<_, Identity, NetUid, I96F32, ValueQuery, DefaultMovingPrice>; #[pallet::storage] // --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. pub type SubnetVolume = - StorageMap<_, Identity, u16, u128, ValueQuery, DefaultZeroU128>; + StorageMap<_, Identity, NetUid, u128, ValueQuery, DefaultZeroU128>; #[pallet::storage] // --- MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. pub type SubnetTAO = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + #[pallet::storage] // --- MAP ( netuid ) --> tao_in_user_subnet | Returns the amount of TAO in the subnet reserve provided by users as liquidity. + pub type SubnetTaoProvided = + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> alpha_in_emission | Returns the amount of alph in emission into the pool per block. pub type SubnetAlphaInEmission = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> alpha_out_emission | Returns the amount of alpha out emission into the network per block. pub type SubnetAlphaOutEmission = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> tao_in_emission | Returns the amount of tao emitted into this subent on the last block. pub type SubnetTaoInEmission = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. pub type SubnetAlphaIn = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_user_in_pool | Returns the amount of alpha in the pool provided by users as liquidity. + pub type SubnetAlphaInProvided = + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + #[pallet::storage] + /// --- MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. pub type SubnetAlphaOut = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it pub type StakingHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; @@ -1133,7 +1087,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, u64, ValueQuery, DefaultZeroU64, @@ -1144,7 +1098,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, u64, ValueQuery, DefaultZeroU64, @@ -1156,7 +1110,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, U64F64, ValueQuery, DefaultSharePoolZero, @@ -1167,14 +1121,14 @@ pub mod pallet { ( NMapKey, // hot NMapKey, // cold - NMapKey, // subnet + NMapKey, // subnet ), U64F64, // Shares ValueQuery, >; #[pallet::storage] // --- MAP ( netuid ) --> token_symbol | Returns the token symbol for a subnet. pub type TokenSymbol = - StorageMap<_, Identity, u16, Vec, ValueQuery, DefaultUnicodeVecU8>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, DefaultUnicodeVecU8>; /// ============================ /// ==== Global Parameters ===== @@ -1185,7 +1139,7 @@ pub mod pallet { #[pallet::storage] /// --- ITEM( global_max_registrations_per_block ) pub type MaxRegistrationsPerBlock = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMaxRegistrationsPerBlock>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxRegistrationsPerBlock>; #[pallet::storage] /// --- ITEM( total_number_of_existing_networks ) pub type TotalNetworks = StorageValue<_, u16, ValueQuery>; @@ -1235,40 +1189,42 @@ pub mod pallet { /// ============================ #[pallet::storage] // --- MAP ( netuid ) --> transfer_toggle pub type TransferToggle = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultTrue>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultTrue>; #[pallet::storage] // --- MAP ( netuid ) --> total_subnet_locked pub type SubnetLocked = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> largest_locked pub type LargestLocked = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; /// ================= /// ==== Tempos ===== /// ================= #[pallet::storage] // --- MAP ( netuid ) --> tempo - pub type Tempo = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultTempo>; + pub type Tempo = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTempo>; /// ============================ /// ==== Subnet Parameters ===== /// ============================ /// --- MAP ( netuid ) --> block number of first emission #[pallet::storage] - pub type FirstEmissionBlockNumber = StorageMap<_, Identity, u16, u64, OptionQuery>; + pub type FirstEmissionBlockNumber = + StorageMap<_, Identity, NetUid, u64, OptionQuery>; /// --- MAP ( netuid ) --> subnet mechanism #[pallet::storage] pub type SubnetMechanism = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultZeroU16>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultZeroU16>; #[pallet::storage] /// --- MAP ( netuid ) --> subnetwork_n (Number of UIDs in the network). - pub type SubnetworkN = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultN>; + pub type SubnetworkN = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultN>; #[pallet::storage] /// --- MAP ( netuid ) --> modality TEXT: 0, IMAGE: 1, TENSOR: 2 - pub type NetworkModality = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultModality>; + pub type NetworkModality = + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultModality>; #[pallet::storage] /// --- MAP ( netuid ) --> network_is_added pub type NetworksAdded = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultNeworksAdded>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultNeworksAdded>; #[pallet::storage] /// --- DMAP ( hotkey, netuid ) --> bool pub type IsNetworkMember = StorageDoubleMap< @@ -1276,7 +1232,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Identity, - u16, + NetUid, bool, ValueQuery, DefaultIsNetworkMember, @@ -1284,174 +1240,177 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( netuid ) --> network_registration_allowed pub type NetworkRegistrationAllowed = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultRegistrationAllowed>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; #[pallet::storage] /// --- MAP ( netuid ) --> network_pow_allowed pub type NetworkPowRegistrationAllowed = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultRegistrationAllowed>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; #[pallet::storage] /// --- MAP ( netuid ) --> block_created pub type NetworkRegisteredAt = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultNetworkRegisteredAt>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultNetworkRegisteredAt>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_emission pub type PendingEmission = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultPendingEmission>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultPendingEmission>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_root_emission - pub type PendingRootDivs = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + pub type PendingRootDivs = + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_alpha_swapped pub type PendingAlphaSwapped = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_owner_cut - pub type PendingOwnerCut = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultZeroU64>; + pub type PendingOwnerCut = + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] /// --- MAP ( netuid ) --> blocks_since_last_step pub type BlocksSinceLastStep = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBlocksSinceLastStep>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBlocksSinceLastStep>; #[pallet::storage] /// --- MAP ( netuid ) --> last_mechanism_step_block pub type LastMechansimStepBlock = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultLastMechanismStepBlock>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastMechanismStepBlock>; #[pallet::storage] /// --- MAP ( netuid ) --> subnet_owner pub type SubnetOwner = - StorageMap<_, Identity, u16, T::AccountId, ValueQuery, DefaultSubnetOwner>; + StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; #[pallet::storage] /// --- MAP ( netuid ) --> subnet_owner_hotkey pub type SubnetOwnerHotkey = - StorageMap<_, Identity, u16, T::AccountId, ValueQuery, DefaultSubnetOwner>; + StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; #[pallet::storage] /// --- MAP ( netuid ) --> serving_rate_limit pub type ServingRateLimit = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultServingRateLimit>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultServingRateLimit>; #[pallet::storage] /// --- MAP ( netuid ) --> Rho - pub type Rho = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultRho>; + pub type Rho = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRho>; #[pallet::storage] /// --- MAP ( netuid ) --> AlphaSigmoidSteepness pub type AlphaSigmoidSteepness = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultAlphaSigmoidSteepness>; + StorageMap<_, Identity, NetUid, i16, ValueQuery, DefaultAlphaSigmoidSteepness>; #[pallet::storage] /// --- MAP ( netuid ) --> Kappa - pub type Kappa = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultKappa>; + pub type Kappa = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultKappa>; #[pallet::storage] /// --- MAP ( netuid ) --> registrations_this_interval - pub type RegistrationsThisInterval = StorageMap<_, Identity, u16, u16, ValueQuery>; + pub type RegistrationsThisInterval = + StorageMap<_, Identity, NetUid, u16, ValueQuery>; #[pallet::storage] /// --- MAP ( netuid ) --> pow_registrations_this_interval pub type POWRegistrationsThisInterval = - StorageMap<_, Identity, u16, u16, ValueQuery>; + StorageMap<_, Identity, NetUid, u16, ValueQuery>; #[pallet::storage] /// --- MAP ( netuid ) --> burn_registrations_this_interval pub type BurnRegistrationsThisInterval = - StorageMap<_, Identity, u16, u16, ValueQuery>; + StorageMap<_, Identity, NetUid, u16, ValueQuery>; #[pallet::storage] /// --- MAP ( netuid ) --> max_allowed_uids pub type MaxAllowedUids = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMaxAllowedUids>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedUids>; #[pallet::storage] /// --- MAP ( netuid ) --> immunity_period pub type ImmunityPeriod = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultImmunityPeriod>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmunityPeriod>; #[pallet::storage] /// --- MAP ( netuid ) --> activity_cutoff pub type ActivityCutoff = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultActivityCutoff>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultActivityCutoff>; #[pallet::storage] /// --- MAP ( netuid ) --> max_weight_limit pub type MaxWeightsLimit = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMaxWeightsLimit>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxWeightsLimit>; #[pallet::storage] /// --- MAP ( netuid ) --> weights_version_key pub type WeightsVersionKey = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultWeightsVersionKey>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsVersionKey>; #[pallet::storage] /// --- MAP ( netuid ) --> min_allowed_weights pub type MinAllowedWeights = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMinAllowedWeights>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinAllowedWeights>; #[pallet::storage] /// --- MAP ( netuid ) --> max_allowed_validators pub type MaxAllowedValidators = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMaxAllowedValidators>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedValidators>; #[pallet::storage] /// --- MAP ( netuid ) --> adjustment_interval pub type AdjustmentInterval = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultAdjustmentInterval>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultAdjustmentInterval>; #[pallet::storage] /// --- MAP ( netuid ) --> bonds_moving_average pub type BondsMovingAverage = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBondsMovingAverage>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBondsMovingAverage>; #[pallet::storage] /// --- MAP ( netuid ) --> bonds_penalty pub type BondsPenalty = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultBondsPenalty>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultBondsPenalty>; #[pallet::storage] /// --- MAP ( netuid ) --> bonds_reset pub type BondsResetOn = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultBondsResetOn>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultBondsResetOn>; /// --- MAP ( netuid ) --> weights_set_rate_limit #[pallet::storage] pub type WeightsSetRateLimit = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultWeightsSetRateLimit>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsSetRateLimit>; #[pallet::storage] /// --- MAP ( netuid ) --> validator_prune_len pub type ValidatorPruneLen = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultValidatorPruneLen>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultValidatorPruneLen>; #[pallet::storage] /// --- MAP ( netuid ) --> scaling_law_power pub type ScalingLawPower = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultScalingLawPower>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultScalingLawPower>; #[pallet::storage] /// --- MAP ( netuid ) --> target_registrations_this_interval pub type TargetRegistrationsPerInterval = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultTargetRegistrationsPerInterval>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTargetRegistrationsPerInterval>; #[pallet::storage] /// --- MAP ( netuid ) --> adjustment_alpha pub type AdjustmentAlpha = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultAdjustmentAlpha>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultAdjustmentAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> commit reveal v2 weights are enabled pub type CommitRevealWeightsEnabled = - StorageMap<_, Identity, u16, bool, ValueQuery, DefaultCommitRevealWeightsEnabled>; + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultCommitRevealWeightsEnabled>; #[pallet::storage] /// --- MAP ( netuid ) --> Burn - pub type Burn = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBurn>; + pub type Burn = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBurn>; #[pallet::storage] /// --- MAP ( netuid ) --> Difficulty - pub type Difficulty = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultDifficulty>; + pub type Difficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultDifficulty>; #[pallet::storage] /// --- MAP ( netuid ) --> MinBurn - pub type MinBurn = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultMinBurn>; + pub type MinBurn = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMinBurn>; #[pallet::storage] /// --- MAP ( netuid ) --> MaxBurn - pub type MaxBurn = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultMaxBurn>; + pub type MaxBurn = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMaxBurn>; #[pallet::storage] /// --- MAP ( netuid ) --> MinDifficulty pub type MinDifficulty = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultMinDifficulty>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMinDifficulty>; #[pallet::storage] /// --- MAP ( netuid ) --> MaxDifficulty pub type MaxDifficulty = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultMaxDifficulty>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMaxDifficulty>; #[pallet::storage] /// --- MAP ( netuid ) --> Block at last adjustment. pub type LastAdjustmentBlock = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultLastAdjustmentBlock>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastAdjustmentBlock>; #[pallet::storage] /// --- MAP ( netuid ) --> Registrations of this Block. pub type RegistrationsThisBlock = - StorageMap<_, Identity, u16, u16, ValueQuery, DefaultRegistrationsThisBlock>; + StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRegistrationsThisBlock>; #[pallet::storage] /// --- MAP ( netuid ) --> Halving time of average moving price. pub type EMAPriceHalvingBlocks = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultEMAPriceMovingBlocks>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultEMAPriceMovingBlocks>; #[pallet::storage] /// --- MAP ( netuid ) --> global_RAO_recycled_for_registration pub type RAORecycledForRegistration = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultRAORecycledForRegistration>; + StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultRAORecycledForRegistration>; #[pallet::storage] /// --- ITEM ( tx_rate_limit ) pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; @@ -1466,84 +1425,96 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( netuid ) --> Whether or not Liquid Alpha is enabled pub type LiquidAlphaOn = - StorageMap<_, Blake2_128Concat, u16, bool, ValueQuery, DefaultLiquidAlpha>; + StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultLiquidAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> Whether or not Yuma3 is enabled - pub type Yuma3On = StorageMap<_, Blake2_128Concat, u16, bool, ValueQuery, DefaultYuma3>; + pub type Yuma3On = + StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultYuma3>; #[pallet::storage] /// MAP ( netuid ) --> (alpha_low, alpha_high) pub type AlphaValues = - StorageMap<_, Identity, u16, (u16, u16), ValueQuery, DefaultAlphaValues>; + StorageMap<_, Identity, NetUid, (u16, u16), ValueQuery, DefaultAlphaValues>; #[pallet::storage] /// --- MAP ( netuid ) --> If subtoken trading enabled - pub type SubtokenEnabled = StorageMap<_, Identity, u16, bool, ValueQuery, DefaultFalse>; + pub type SubtokenEnabled = + StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultFalse>; /// ======================================= /// ==== Subnetwork Consensus Storage ==== /// ======================================= #[pallet::storage] // --- DMAP ( netuid ) --> stake_weight | weight for stake used in YC. pub(super) type StakeWeight = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- DMAP ( netuid, hotkey ) --> uid pub type Uids = - StorageDoubleMap<_, Identity, u16, Blake2_128Concat, T::AccountId, u16, OptionQuery>; + StorageDoubleMap<_, Identity, NetUid, Blake2_128Concat, T::AccountId, u16, OptionQuery>; #[pallet::storage] /// --- DMAP ( netuid, uid ) --> hotkey - pub type Keys = - StorageDoubleMap<_, Identity, u16, Identity, u16, T::AccountId, ValueQuery, DefaultKey>; + pub type Keys = StorageDoubleMap< + _, + Identity, + NetUid, + Identity, + u16, + T::AccountId, + ValueQuery, + DefaultKey, + >; #[pallet::storage] /// --- MAP ( netuid ) --> (hotkey, se, ve) pub type LoadedEmission = - StorageMap<_, Identity, u16, Vec<(T::AccountId, u64, u64)>, OptionQuery>; + StorageMap<_, Identity, NetUid, Vec<(T::AccountId, u64, u64)>, OptionQuery>; #[pallet::storage] /// --- MAP ( netuid ) --> active pub type Active = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] /// --- MAP ( netuid ) --> rank - pub type Rank = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Rank = + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> trust - pub type Trust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Trust = + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> consensus pub type Consensus = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> incentive pub type Incentive = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> dividends pub type Dividends = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> emission pub type Emission = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> last_update pub type LastUpdate = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> validator_trust pub type ValidatorTrust = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> pruning_scores pub type PruningScores = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> validator_permit pub type ValidatorPermit = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; + StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] /// --- DMAP ( netuid, uid ) --> weights pub type Weights = StorageDoubleMap< _, Identity, - u16, + NetUid, Identity, u16, Vec<(u16, u16)>, @@ -1555,7 +1526,7 @@ pub mod pallet { pub type Bonds = StorageDoubleMap< _, Identity, - u16, + NetUid, Identity, u16, Vec<(u16, u16)>, @@ -1567,7 +1538,7 @@ pub mod pallet { pub type BlockAtRegistration = StorageDoubleMap< _, Identity, - u16, + NetUid, Identity, u16, u64, @@ -1576,14 +1547,21 @@ pub mod pallet { >; #[pallet::storage] /// --- MAP ( netuid, hotkey ) --> axon_info - pub type Axons = - StorageDoubleMap<_, Identity, u16, Blake2_128Concat, T::AccountId, AxonInfoOf, OptionQuery>; + pub type Axons = StorageDoubleMap< + _, + Identity, + NetUid, + Blake2_128Concat, + T::AccountId, + AxonInfoOf, + OptionQuery, + >; /// --- MAP ( netuid, hotkey ) --> certificate #[pallet::storage] pub type NeuronCertificates = StorageDoubleMap< _, Identity, - u16, + NetUid, Blake2_128Concat, T::AccountId, NeuronCertificateOf, @@ -1594,7 +1572,7 @@ pub mod pallet { pub type Prometheus = StorageDoubleMap< _, Identity, - u16, + NetUid, Blake2_128Concat, T::AccountId, PrometheusInfoOf, @@ -1610,11 +1588,15 @@ pub mod pallet { #[pallet::storage] // --- MAP ( netuid ) --> identity. (DEPRECATED for V2) pub type SubnetIdentities = - StorageMap<_, Blake2_128Concat, u16, SubnetIdentityOf, OptionQuery>; + StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOf, OptionQuery>; - #[pallet::storage] // --- MAP ( netuid ) --> identityV2 + #[pallet::storage] // --- MAP ( netuid ) --> identityV2 (DEPRECATED for V3) pub type SubnetIdentitiesV2 = - StorageMap<_, Blake2_128Concat, u16, SubnetIdentityOfV2, OptionQuery>; + StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV2, OptionQuery>; + + #[pallet::storage] // --- MAP ( netuid ) --> SubnetIdentityOfV3 + pub type SubnetIdentitiesV3 = + StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV3, OptionQuery>; /// ================================= /// ==== Axon / Promo Endpoints ===== @@ -1624,7 +1606,7 @@ pub mod pallet { _, ( NMapKey, // hot - NMapKey, // netuid + NMapKey, // netuid NMapKey, // extrinsic enum. ), u64, @@ -1650,7 +1632,7 @@ pub mod pallet { pub type WeightCommits = StorageDoubleMap< _, Twox64Concat, - u16, + NetUid, Twox64Concat, T::AccountId, VecDeque<(H256, u64, u64, u64)>, @@ -1661,7 +1643,7 @@ pub mod pallet { pub type CRV3WeightCommits = StorageDoubleMap< _, Twox64Concat, - u16, + NetUid, Twox64Concat, u64, VecDeque<( @@ -1674,7 +1656,7 @@ pub mod pallet { #[pallet::storage] /// --- Map (netuid) --> Number of epochs allowed for commit reveal periods pub type RevealPeriodEpochs = - StorageMap<_, Twox64Concat, u16, u64, ValueQuery, DefaultRevealPeriodEpochs>; + StorageMap<_, Twox64Concat, NetUid, u64, ValueQuery, DefaultRevealPeriodEpochs>; #[pallet::storage] /// --- Map (coldkey, hotkey) --> u64 the last block at which stake was added/removed. @@ -1694,7 +1676,7 @@ pub mod pallet { #[pallet::storage] /// --- DMAP (netuid, uid) --> (H160, last_block_where_ownership_was_proven) pub type AssociatedEvmAddress = - StorageDoubleMap<_, Twox64Concat, u16, Twox64Concat, u16, (H160, u64), OptionQuery>; + StorageDoubleMap<_, Twox64Concat, NetUid, Twox64Concat, u16, (H160, u64), OptionQuery>; /// ================== /// ==== Genesis ===== @@ -1702,6 +1684,17 @@ pub mod pallet { #[pallet::storage] // --- Storage for migration run status pub type HasMigrationRun = StorageMap<_, Identity, Vec, bool, ValueQuery>; + #[pallet::type_value] + /// Default value for pending childkey cooldown (settable by root, default 0) + pub fn DefaultPendingChildKeyCooldown() -> u64 { + 0 + } + + #[pallet::storage] + /// Storage value for pending childkey cooldown, settable by root. + pub type PendingChildKeyCooldown = + StorageValue<_, u64, ValueQuery, DefaultPendingChildKeyCooldown>; + #[pallet::genesis_config] pub struct GenesisConfig { /// Stakes record in genesis. @@ -1722,7 +1715,7 @@ pub mod pallet { // ---- Subtensor helper functions. impl Pallet { /// Returns the transaction priority for setting weights. - pub fn get_priority_set_weights(hotkey: &T::AccountId, netuid: u16) -> u64 { + pub fn get_priority_set_weights(hotkey: &T::AccountId, netuid: NetUid) -> u64 { if let Ok(uid) = Self::get_uid_for_net_and_hotkey(netuid, hotkey) { // TODO rethink this. let _stake = Self::get_inherited_for_hotkey_on_subnet(hotkey, netuid); @@ -1754,15 +1747,15 @@ pub mod pallet { } /// Is the caller allowed to set weights - pub fn check_weights_min_stake(hotkey: &T::AccountId, netuid: u16) -> bool { + pub fn check_weights_min_stake(hotkey: &T::AccountId, netuid: NetUid) -> bool { // Blacklist weights transactions for low stake peers. let (total_stake, _, _) = Self::get_stake_weights_for_hotkey_on_subnet(hotkey, netuid); total_stake >= Self::get_stake_threshold() } /// Helper function to check if register is allowed - pub fn checked_allowed_register(netuid: u16) -> bool { - if netuid == Self::get_root_netuid() { + pub fn checked_allowed_register(netuid: NetUid) -> bool { + if netuid.is_root() { return false; } if !Self::if_subnet_exist(netuid) { @@ -1785,7 +1778,7 @@ pub mod pallet { } /// Ensure subtoken enalbed - pub fn ensure_subtoken_enabled(subnet: u16) -> DispatchResult { + pub fn ensure_subtoken_enabled(subnet: NetUid) -> Result<(), Error> { ensure!( SubtokenEnabled::::get(subnet), Error::::SubtokenDisabled @@ -1854,22 +1847,23 @@ impl From for u8 { } } -#[freeze_struct("61e2b893d5ce6701")] -#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct SubtensorSignedExtension(pub PhantomData); +impl From for TransactionValidityError { + fn from(variant: CustomTransactionError) -> Self { + TransactionValidityError::Invalid(InvalidTransaction::Custom(variant.into())) + } +} -impl Default for SubtensorSignedExtension -where - ::RuntimeCall: - Dispatchable, - ::RuntimeCall: IsSubType>, -{ - fn default() -> Self { - Self::new() +#[freeze_struct("2e02eb32e5cb25d3")] +#[derive(Default, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)] +pub struct SubtensorTransactionExtension(pub PhantomData); + +impl sp_std::fmt::Debug for SubtensorTransactionExtension { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "SubtensorTransactionExtension") } } -impl SubtensorSignedExtension +impl SubtensorTransactionExtension where ::RuntimeCall: Dispatchable, @@ -1885,7 +1879,7 @@ where u64::MAX } - pub fn get_priority_set_weights(who: &T::AccountId, netuid: u16) -> u64 { + pub fn get_priority_set_weights(who: &T::AccountId, netuid: NetUid) -> u64 { Pallet::::get_priority_set_weights(who, netuid) } @@ -1897,65 +1891,37 @@ where Pallet::::get_priority_staking(coldkey, hotkey, stake_amount) } - pub fn check_weights_min_stake(who: &T::AccountId, netuid: u16) -> bool { + pub fn check_weights_min_stake(who: &T::AccountId, netuid: NetUid) -> bool { Pallet::::check_weights_min_stake(who, netuid) } pub fn result_to_validity(result: Result<(), Error>, priority: u64) -> TransactionValidity { if let Err(err) = result { - match err { - Error::::AmountTooLow => Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()), - Error::::SubnetNotExists => Err(InvalidTransaction::Custom( - CustomTransactionError::SubnetDoesntExist.into(), - ) - .into()), - Error::::NotEnoughBalanceToStake => Err(InvalidTransaction::Custom( - CustomTransactionError::BalanceTooLow.into(), - ) - .into()), - Error::::HotKeyAccountNotExists => Err(InvalidTransaction::Custom( - CustomTransactionError::HotkeyAccountDoesntExist.into(), - ) - .into()), - Error::::NotEnoughStakeToWithdraw => Err(InvalidTransaction::Custom( - CustomTransactionError::NotEnoughStakeToWithdraw.into(), - ) - .into()), - Error::::InsufficientLiquidity => Err(InvalidTransaction::Custom( - CustomTransactionError::InsufficientLiquidity.into(), - ) - .into()), - Error::::SlippageTooHigh => Err(InvalidTransaction::Custom( - CustomTransactionError::SlippageTooHigh.into(), - ) - .into()), - Error::::TransferDisallowed => Err(InvalidTransaction::Custom( - CustomTransactionError::TransferDisallowed.into(), - ) - .into()), - Error::::HotKeyNotRegisteredInNetwork => Err(InvalidTransaction::Custom( - CustomTransactionError::HotKeyNotRegisteredInNetwork.into(), - ) - .into()), - Error::::InvalidIpAddress => Err(InvalidTransaction::Custom( - CustomTransactionError::InvalidIpAddress.into(), - ) - .into()), - Error::::ServingRateLimitExceeded => Err(InvalidTransaction::Custom( - CustomTransactionError::ServingRateLimitExceeded.into(), - ) - .into()), - Error::::InvalidPort => Err(InvalidTransaction::Custom( - CustomTransactionError::InvalidPort.into(), - ) - .into()), - _ => Err( - InvalidTransaction::Custom(CustomTransactionError::BadRequest.into()).into(), - ), - } + Err(match err { + Error::::AmountTooLow => CustomTransactionError::StakeAmountTooLow.into(), + Error::::SubnetNotExists => CustomTransactionError::SubnetDoesntExist.into(), + Error::::NotEnoughBalanceToStake => CustomTransactionError::BalanceTooLow.into(), + Error::::HotKeyAccountNotExists => { + CustomTransactionError::HotkeyAccountDoesntExist.into() + } + Error::::NotEnoughStakeToWithdraw => { + CustomTransactionError::NotEnoughStakeToWithdraw.into() + } + Error::::InsufficientLiquidity => { + CustomTransactionError::InsufficientLiquidity.into() + } + Error::::SlippageTooHigh => CustomTransactionError::SlippageTooHigh.into(), + Error::::TransferDisallowed => CustomTransactionError::TransferDisallowed.into(), + Error::::HotKeyNotRegisteredInNetwork => { + CustomTransactionError::HotKeyNotRegisteredInNetwork.into() + } + Error::::InvalidIpAddress => CustomTransactionError::InvalidIpAddress.into(), + Error::::ServingRateLimitExceeded => { + CustomTransactionError::ServingRateLimitExceeded.into() + } + Error::::InvalidPort => CustomTransactionError::InvalidPort.into(), + _ => CustomTransactionError::BadRequest.into(), + }) } else { Ok(ValidTransaction { priority, @@ -1965,127 +1931,119 @@ where } } -impl sp_std::fmt::Debug for SubtensorSignedExtension { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "SubtensorSignedExtension") - } -} - -impl SignedExtension - for SubtensorSignedExtension +impl + TransactionExtension<::RuntimeCall> + for SubtensorTransactionExtension where ::RuntimeCall: Dispatchable, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: IsSubType>, ::RuntimeCall: IsSubType>, { - const IDENTIFIER: &'static str = "SubtensorSignedExtension"; + const IDENTIFIER: &'static str = "SubtensorTransactionExtension"; - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = (); - type Pre = (CallType, u64, Self::AccountId); + type Implicit = (); + type Val = Option; + type Pre = Option; - fn additional_signed(&self) -> Result { - Ok(()) + fn weight(&self, _call: &::RuntimeCall) -> Weight { + // TODO: benchmark transaction extension + Weight::zero() } fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, _len: usize, - ) -> TransactionValidity { + _self_implicit: Self::Implicit, + _inherited_implication: &impl Implication, + _source: TransactionSource, + ) -> ValidateResult::RuntimeCall> { + // Ensure the transaction is signed, else we just skip the extension. + let Some(who) = origin.as_system_origin_signer() else { + return Ok((Default::default(), None, origin)); + }; + match call.is_sub_type() { Some(Call::commit_weights { netuid, .. }) => { if Self::check_weights_min_stake(who, *netuid) { let priority: u64 = Self::get_priority_set_weights(who, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::reveal_weights { netuid, .. }) => { if Self::check_weights_min_stake(who, *netuid) { let priority: u64 = Self::get_priority_set_weights(who, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::batch_reveal_weights { netuid, .. }) => { if Self::check_weights_min_stake(who, *netuid) { let priority: u64 = Self::get_priority_set_weights(who, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::set_weights { netuid, .. }) => { if Self::check_weights_min_stake(who, *netuid) { let priority: u64 = Self::get_priority_set_weights(who, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::set_tao_weights { netuid, hotkey, .. }) => { if Self::check_weights_min_stake(hotkey, *netuid) { let priority: u64 = Self::get_priority_set_weights(hotkey, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::commit_crv3_weights { netuid, .. }) => { if Self::check_weights_min_stake(who, *netuid) { let priority: u64 = Pallet::::get_priority_set_weights(who, *netuid); - Ok(ValidTransaction { + let validity = ValidTransaction { priority, longevity: 1, ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } else { - Err(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into(), - ) - .into()) + Err(CustomTransactionError::StakeAmountTooLow.into()) } } Some(Call::add_stake { @@ -2094,11 +2052,9 @@ where amount_staked, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } + // Fully validate the user input Self::result_to_validity( Pallet::::validate_add_stake( @@ -2111,6 +2067,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_staked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::add_stake_limit { hotkey, @@ -2120,18 +2077,12 @@ where allow_partial, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } // Calculate the maximum amount that can be executed with price limit let Ok(max_amount) = Pallet::::get_max_amount_add(*netuid, *limit_price) else { - return InvalidTransaction::Custom( - CustomTransactionError::ZeroMaxAmount.into(), - ) - .into(); + return Err(CustomTransactionError::ZeroMaxAmount.into()); }; // Fully validate the user input @@ -2146,6 +2097,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_staked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::remove_stake { hotkey, @@ -2164,6 +2116,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_unstaked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::remove_stake_limit { hotkey, @@ -2175,10 +2128,7 @@ where // Calculate the maximum amount that can be executed with price limit let Ok(max_amount) = Pallet::::get_max_amount_remove(*netuid, *limit_price) else { - return InvalidTransaction::Custom( - CustomTransactionError::ZeroMaxAmount.into(), - ) - .into(); + return Err(CustomTransactionError::ZeroMaxAmount.into()); }; // Fully validate the user input @@ -2193,119 +2143,15 @@ where ), Self::get_priority_staking(who, hotkey, *amount_unstaked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } - // Some(Call::add_stake_aggregate { - // hotkey, - // netuid, - // amount_staked, - // }) => { - // if ColdkeySwapScheduled::::contains_key(who) { - // return InvalidTransaction::Custom( - // CustomTransactionError::ColdkeyInSwapSchedule.into(), - // ) - // .into(); - // } - // // Fully validate the user input - // Self::result_to_validity( - // Pallet::::validate_add_stake( - // who, - // hotkey, - // *netuid, - // *amount_staked, - // *amount_staked, - // false, - // ), - // Self::get_priority_staking(who, hotkey, *amount_staked), - // ) - // } - // Some(Call::add_stake_limit_aggregate { - // hotkey, - // netuid, - // amount_staked, - // limit_price, - // allow_partial, - // }) => { - // if ColdkeySwapScheduled::::contains_key(who) { - // return InvalidTransaction::Custom( - // CustomTransactionError::ColdkeyInSwapSchedule.into(), - // ) - // .into(); - // } - // - // // Calculate the maximum amount that can be executed with price limit - // let Ok(max_amount) = Pallet::::get_max_amount_add(*netuid, *limit_price) else { - // return InvalidTransaction::Custom( - // CustomTransactionError::ZeroMaxAmount.into(), - // ) - // .into(); - // }; - // - // // Fully validate the user input - // Self::result_to_validity( - // Pallet::::validate_add_stake( - // who, - // hotkey, - // *netuid, - // *amount_staked, - // max_amount, - // *allow_partial, - // ), - // Self::get_priority_staking(who, hotkey, *amount_staked), - // ) - // } - // Some(Call::remove_stake_aggregate { - // hotkey, - // netuid, - // amount_unstaked, - // }) => { - // // Fully validate the user input - // Self::result_to_validity( - // Pallet::::validate_remove_stake( - // who, - // hotkey, - // *netuid, - // *amount_unstaked, - // *amount_unstaked, - // false, - // ), - // Self::get_priority_staking(who, hotkey, *amount_unstaked), - // ) - // } - // Some(Call::remove_stake_limit_aggregate { - // hotkey, - // netuid, - // amount_unstaked, - // limit_price, - // allow_partial, - // }) => { - // // Calculate the maximum amount that can be executed with price limit - // let Ok(max_amount) = Pallet::::get_max_amount_remove(*netuid, *limit_price) - // else { - // return InvalidTransaction::Custom( - // CustomTransactionError::ZeroMaxAmount.into(), - // ) - // .into(); - // }; - // - // // Fully validate the user input - // Self::result_to_validity( - // Pallet::::validate_remove_stake( - // who, - // hotkey, - // *netuid, - // *amount_unstaked, - // max_amount, - // *allow_partial, - // ), - // Self::get_priority_staking(who, hotkey, *amount_unstaked), - // ) - // } Some(Call::unstake_all { hotkey }) => { // Fully validate the user input Self::result_to_validity( Pallet::::validate_unstake_all(who, hotkey, false), Self::get_priority_vanilla(), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::unstake_all_alpha { hotkey }) => { // Fully validate the user input @@ -2313,6 +2159,7 @@ where Pallet::::validate_unstake_all(who, hotkey, true), Self::get_priority_vanilla(), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::move_stake { origin_hotkey, @@ -2322,10 +2169,7 @@ where alpha_amount, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } // Fully validate the user input @@ -2344,6 +2188,7 @@ where ), Self::get_priority_staking(who, origin_hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::transfer_stake { destination_coldkey, @@ -2353,10 +2198,7 @@ where alpha_amount, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } // Fully validate the user input @@ -2375,6 +2217,7 @@ where ), Self::get_priority_staking(who, hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::swap_stake { hotkey, @@ -2383,10 +2226,7 @@ where alpha_amount, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } // Fully validate the user input @@ -2405,6 +2245,7 @@ where ), Self::get_priority_staking(who, hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::swap_stake_limit { hotkey, @@ -2415,10 +2256,7 @@ where allow_partial, }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } // Get the max amount possible to exchange @@ -2427,10 +2265,7 @@ where *destination_netuid, *limit_price, ) else { - return InvalidTransaction::Custom( - CustomTransactionError::ZeroMaxAmount.into(), - ) - .into(); + return Err(CustomTransactionError::ZeroMaxAmount.into()); }; // Fully validate the user input @@ -2449,13 +2284,11 @@ where ), Self::get_priority_staking(who, hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::register { netuid, .. } | Call::burned_register { netuid, .. }) => { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } let registrations_this_interval = @@ -2465,29 +2298,31 @@ where if registrations_this_interval >= (max_registrations_per_interval.saturating_mul(3)) { // If the registration limit for the interval is exceeded, reject the transaction - return Err(InvalidTransaction::Custom( - CustomTransactionError::RateLimitExceeded.into(), - ) - .into()); + return Err(CustomTransactionError::RateLimitExceeded.into()); } - Ok(ValidTransaction { + let validity = ValidTransaction { priority: Self::get_priority_vanilla(), ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) + } + Some(Call::register_network { .. }) => { + let validity = ValidTransaction { + priority: Self::get_priority_vanilla(), + ..Default::default() + }; + + Ok((validity, Some(who.clone()), origin)) } - Some(Call::register_network { .. }) => Ok(ValidTransaction { - priority: Self::get_priority_vanilla(), - ..Default::default() - }), Some(Call::dissolve_network { .. }) => { if ColdkeySwapScheduled::::contains_key(who) { - InvalidTransaction::Custom(CustomTransactionError::ColdkeyInSwapSchedule.into()) - .into() + Err(CustomTransactionError::ColdkeyInSwapSchedule.into()) } else { - Ok(ValidTransaction { + let validity = ValidTransaction { priority: Self::get_priority_vanilla(), ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } } Some(Call::serve_axon { @@ -2515,6 +2350,7 @@ where ), Self::get_priority_vanilla(), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } _ => { if let Some( @@ -2524,102 +2360,77 @@ where ) = call.is_sub_type() { if ColdkeySwapScheduled::::contains_key(who) { - return InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into(), - ) - .into(); + return Err(CustomTransactionError::ColdkeyInSwapSchedule.into()); } } - Ok(ValidTransaction { + let validity = ValidTransaction { priority: Self::get_priority_vanilla(), ..Default::default() - }) + }; + Ok((validity, Some(who.clone()), origin)) } } } // NOTE: Add later when we put in a pre and post dispatch step. - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + val: Self::Val, + _origin: &::RuntimeOrigin, + call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, + _len: usize, ) -> Result { - // We need to perform same checks as Self::validate so that - // the validation is performed during Executive::apply_extrinsic as well. - // this prevents inclusion of invalid tx in a block by malicious block author. - self.validate(who, call, info, len)?; + // The transaction is not signed, given val is None, so we just skip this step. + if val.is_none() { + return Ok(None); + } + match call.is_sub_type() { - Some(Call::add_stake { .. }) => { - let transaction_fee = 100000; - Ok((CallType::AddStake, transaction_fee, who.clone())) - } - Some(Call::remove_stake { .. }) => { - let transaction_fee = 0; - Ok((CallType::RemoveStake, transaction_fee, who.clone())) - } - Some(Call::set_weights { .. }) => { - let transaction_fee = 0; - Ok((CallType::SetWeights, transaction_fee, who.clone())) - } - Some(Call::commit_weights { .. }) => { - let transaction_fee = 0; - Ok((CallType::SetWeights, transaction_fee, who.clone())) - } - Some(Call::reveal_weights { .. }) => { - let transaction_fee = 0; - Ok((CallType::SetWeights, transaction_fee, who.clone())) - } - Some(Call::register { .. }) => { - let transaction_fee = 0; - Ok((CallType::Register, transaction_fee, who.clone())) - } - Some(Call::serve_axon { .. }) => { - let transaction_fee = 0; - Ok((CallType::Serve, transaction_fee, who.clone())) - } - Some(Call::serve_axon_tls { .. }) => { - let transaction_fee = 0; - Ok((CallType::Serve, transaction_fee, who.clone())) - } - Some(Call::register_network { .. }) => { - let transaction_fee = 0; - Ok((CallType::RegisterNetwork, transaction_fee, who.clone())) - } - _ => { - let transaction_fee = 0; - Ok((CallType::Other, transaction_fee, who.clone())) - } + Some(Call::add_stake { .. }) => Ok(Some(CallType::AddStake)), + Some(Call::remove_stake { .. }) => Ok(Some(CallType::RemoveStake)), + Some(Call::set_weights { .. }) => Ok(Some(CallType::SetWeights)), + Some(Call::commit_weights { .. }) => Ok(Some(CallType::SetWeights)), + Some(Call::reveal_weights { .. }) => Ok(Some(CallType::SetWeights)), + Some(Call::register { .. }) => Ok(Some(CallType::Register)), + Some(Call::serve_axon { .. }) => Ok(Some(CallType::Serve)), + Some(Call::serve_axon_tls { .. }) => Ok(Some(CallType::Serve)), + Some(Call::register_network { .. }) => Ok(Some(CallType::RegisterNetwork)), + _ => Ok(Some(CallType::Other)), } } fn post_dispatch( - maybe_pre: Option, - _info: &DispatchInfoOf, - _post_info: &PostDispatchInfoOf, + pre: Self::Pre, + _info: &DispatchInfoOf<::RuntimeCall>, + _post_info: &mut PostDispatchInfoOf<::RuntimeCall>, _len: usize, _result: &dispatch::DispatchResult, ) -> Result<(), TransactionValidityError> { - if let Some((call_type, _transaction_fee, _who)) = maybe_pre { - match call_type { - CallType::SetWeights => { - log::debug!("Not Implemented!"); - } - CallType::AddStake => { - log::debug!("Not Implemented! Need to add potential transaction fees here."); - } - CallType::RemoveStake => { - log::debug!("Not Implemented! Need to add potential transaction fees here."); - } - CallType::Register => { - log::debug!("Not Implemented!"); - } - _ => { - log::debug!("Not Implemented!"); - } + // Skip this step if the transaction is not signed, meaning pre is None. + let call_type = match pre { + Some(call_type) => call_type, + None => return Ok(()), + }; + + match call_type { + CallType::SetWeights => { + log::debug!("Not Implemented!"); + } + CallType::AddStake => { + log::debug!("Not Implemented! Need to add potential transaction fees here."); + } + CallType::RemoveStake => { + log::debug!("Not Implemented! Need to add potential transaction fees here."); + } + CallType::Register => { + log::debug!("Not Implemented!"); + } + _ => { + log::debug!("Not Implemented!"); } } + Ok(()) } } @@ -2707,10 +2518,112 @@ impl CollectiveInterface for () { } } +impl> + subtensor_runtime_common::SubnetInfo for Pallet +{ + fn tao_reserve(netuid: NetUid) -> u64 { + SubnetTAO::::get(netuid).saturating_add(SubnetTaoProvided::::get(netuid)) + } + + fn alpha_reserve(netuid: NetUid) -> u64 { + SubnetAlphaIn::::get(netuid).saturating_add(SubnetAlphaInProvided::::get(netuid)) + } + + fn exists(netuid: NetUid) -> bool { + Self::if_subnet_exist(netuid) + } + + fn mechanism(netuid: NetUid) -> u16 { + SubnetMechanism::::get(netuid) + } + + fn is_owner(account_id: &T::AccountId, netuid: NetUid) -> bool { + SubnetOwner::::get(netuid) == *account_id + } +} + +impl> + subtensor_runtime_common::BalanceOps for Pallet +{ + fn tao_balance(account_id: &T::AccountId) -> u64 { + pallet_balances::Pallet::::free_balance(account_id) + } + + fn alpha_balance(netuid: NetUid, coldkey: &T::AccountId, hotkey: &T::AccountId) -> u64 { + Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) + } + + fn increase_balance(coldkey: &T::AccountId, tao: u64) { + Self::add_balance_to_coldkey_account(coldkey, tao) + } + + fn decrease_balance(coldkey: &T::AccountId, tao: u64) -> Result { + Self::remove_balance_from_coldkey_account(coldkey, tao) + } + + fn increase_stake( + coldkey: &T::AccountId, + hotkey: &T::AccountId, + netuid: NetUid, + alpha: u64, + ) -> Result<(), DispatchError> { + ensure!( + Self::hotkey_account_exists(hotkey), + Error::::HotKeyAccountNotExists + ); + + // Increse alpha out counter + SubnetAlphaOut::::mutate(netuid, |total| { + *total = total.saturating_add(alpha); + }); + + Self::increase_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, alpha); + + Ok(()) + } + + fn decrease_stake( + coldkey: &T::AccountId, + hotkey: &T::AccountId, + netuid: NetUid, + alpha: u64, + ) -> Result { + ensure!( + Self::hotkey_account_exists(hotkey), + Error::::HotKeyAccountNotExists + ); + + // Decrese alpha out counter + SubnetAlphaOut::::mutate(netuid, |total| { + *total = total.saturating_sub(alpha); + }); + + Ok(Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, alpha, + )) + } + + fn increase_provided_tao_reserve(netuid: NetUid, tao: u64) { + Self::increase_provided_tao_reserve(netuid, tao); + } + + fn decrease_provided_tao_reserve(netuid: NetUid, tao: u64) { + Self::decrease_provided_tao_reserve(netuid, tao); + } + + fn increase_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + Self::increase_provided_alpha_reserve(netuid, alpha); + } + + fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + Self::decrease_provided_alpha_reserve(netuid, alpha); + } +} + /// Enum that defines types of rate limited operations for /// storing last block when this operation occured #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] pub enum RateLimitKey { // The setting sn owner hotkey operation is rate limited per netuid - SetSNOwnerHotkey(u16), + SetSNOwnerHotkey(NetUid), } diff --git a/pallets/subtensor/src/macros/config.rs b/pallets/subtensor/src/macros/config.rs index 4377d9f016..da104291d8 100644 --- a/pallets/subtensor/src/macros/config.rs +++ b/pallets/subtensor/src/macros/config.rs @@ -5,6 +5,9 @@ use frame_support::pallet_macros::pallet_section; /// This can later be imported into the pallet using [`import_section`]. #[pallet_section] mod config { + + use subtensor_swap_interface::SwapHandler; + /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config + pallet_drand::Config { @@ -47,6 +50,9 @@ mod config { /// the preimage to store the call data. type Preimages: QueryPreimage + StorePreimage; + /// Swap interface. + type SwapInterface: SwapHandler; + /// ================================= /// ==== Initial Value Constants ==== /// ================================= @@ -107,7 +113,7 @@ mod config { type InitialRho: Get; /// AlphaSigmoidSteepness constant. #[pallet::constant] - type InitialAlphaSigmoidSteepness: Get; + type InitialAlphaSigmoidSteepness: Get; /// Kappa constant. #[pallet::constant] type InitialKappa: Get; @@ -224,5 +230,11 @@ mod config { /// Block number after a new subnet accept the start call extrinsic. #[pallet::constant] type DurationOfStartCall: Get; + /// Cost of swapping a hotkey in a subnet. + #[pallet::constant] + type KeySwapOnSubnetCost: Get; + /// Block number for a coldkey swap the hotkey in specific subnet. + #[pallet::constant] + type HotkeySwapOnSubnetInterval: Get; } } diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 650fb50451..8ceccc5fa2 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -82,7 +82,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn set_weights( origin: OriginFor, - netuid: u16, + netuid: NetUid, dests: Vec, weights: Vec, version_key: u64, @@ -125,7 +125,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn batch_set_weights( origin: OriginFor, - netuids: Vec>, + netuids: Vec>, weights: Vec, Compact)>>, version_keys: Vec>, ) -> DispatchResult { @@ -157,7 +157,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn commit_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, commit_hash: H256, ) -> DispatchResult { Self::do_commit_weights(origin, netuid, commit_hash) @@ -191,7 +191,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn batch_commit_weights( origin: OriginFor, - netuids: Vec>, + netuids: Vec>, commit_hashes: Vec, ) -> DispatchResult { Self::do_batch_commit_weights(origin, netuids, commit_hashes) @@ -240,7 +240,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn reveal_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, uids: Vec, values: Vec, salt: Vec, @@ -284,7 +284,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn commit_crv3_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, commit: BoundedVec>, reveal_round: u64, ) -> DispatchResult { @@ -336,7 +336,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn batch_reveal_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, uids_list: Vec>, values_list: Vec>, salts_list: Vec>, @@ -418,7 +418,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Normal, Pays::No))] pub fn set_tao_weights( _origin: OriginFor, - _netuid: u16, + _netuid: NetUid, _hotkey: T::AccountId, _dests: Vec, _weights: Vec, @@ -454,7 +454,7 @@ mod dispatches { /// - The hotkey we are delegating is not owned by the calling coldket. /// #[pallet::call_index(1)] - #[pallet::weight((Weight::from_parts(4_709_000, 0) + #[pallet::weight((Weight::from_parts(3_657_000, 0) .saturating_add(T::DbWeight::get().reads(0)) .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Normal, Pays::No))] pub fn become_delegate(_origin: OriginFor, _hotkey: T::AccountId) -> DispatchResult { @@ -551,11 +551,11 @@ mod dispatches { Self::do_increase_take(origin, hotkey, take) } - /// --- Adds stake to a hotkey. The call is made from the - /// coldkey account linked in the hotkey. - /// Only the associated coldkey is allowed to make staking and - /// unstaking requests. This protects the neuron against - /// attacks on its hotkey running in production code. + /// --- Adds stake to a hotkey. The call is made from a coldkey account. + /// This delegates stake to the hotkey. + /// + /// Note: the coldkey account may own the hotkey, in which case they are + /// delegating to themselves. /// /// # Args: /// * 'origin': (Origin): @@ -585,13 +585,13 @@ mod dispatches { /// - Errors stemming from transaction pallet. /// #[pallet::call_index(2)] - #[pallet::weight((Weight::from_parts(151_000_000, 0) - .saturating_add(T::DbWeight::get().reads(14)) - .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(345_500_000, 0) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(14)), DispatchClass::Normal, Pays::No))] pub fn add_stake( origin: OriginFor, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, amount_staked: u64, ) -> DispatchResult { Self::do_add_stake(origin, hotkey, netuid, amount_staked) @@ -635,7 +635,7 @@ mod dispatches { pub fn remove_stake( origin: OriginFor, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, amount_unstaked: u64, ) -> DispatchResult { Self::do_remove_stake(origin, hotkey, netuid, amount_unstaked) @@ -698,7 +698,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::No))] pub fn serve_axon( origin: OriginFor, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -782,7 +782,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::No))] pub fn serve_axon_tls( origin: OriginFor, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -832,7 +832,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::No))] pub fn serve_prometheus( origin: OriginFor, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -894,7 +894,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(23)), DispatchClass::Normal, Pays::No))] pub fn register( origin: OriginFor, - netuid: u16, + netuid: NetUid, block_number: u64, nonce: u64, work: Vec, @@ -924,28 +924,29 @@ mod dispatches { /// User register a new subnetwork via burning token #[pallet::call_index(7)] - #[pallet::weight((Weight::from_parts(219_400_000, 0) - .saturating_add(T::DbWeight::get().reads(33)) - .saturating_add(T::DbWeight::get().writes(29)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(354_400_000, 0) + .saturating_add(T::DbWeight::get().reads(49)) + .saturating_add(T::DbWeight::get().writes(43)), DispatchClass::Normal, Pays::No))] pub fn burned_register( origin: OriginFor, - netuid: u16, + netuid: NetUid, hotkey: T::AccountId, ) -> DispatchResult { Self::do_burned_registration(origin, netuid, hotkey) } - /// The extrinsic for user to change its hotkey + /// The extrinsic for user to change its hotkey in subnet or all subnets. #[pallet::call_index(70)] - #[pallet::weight((Weight::from_parts(240_600_000, 0) - .saturating_add(T::DbWeight::get().reads(31)) - .saturating_add(T::DbWeight::get().writes(23)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(285_900_000, 0) + .saturating_add(T::DbWeight::get().reads(47)) + .saturating_add(T::DbWeight::get().writes(37)), DispatchClass::Operational, Pays::No))] pub fn swap_hotkey( origin: OriginFor, hotkey: T::AccountId, new_hotkey: T::AccountId, + netuid: Option, ) -> DispatchResultWithPostInfo { - Self::do_swap_hotkey(origin, &hotkey, &new_hotkey) + Self::do_swap_hotkey(origin, &hotkey, &new_hotkey, netuid) } /// The extrinsic for user to change the coldkey associated with their account. @@ -1020,7 +1021,7 @@ mod dispatches { pub fn set_childkey_take( origin: OriginFor, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, take: u16, ) -> DispatchResult { let coldkey = ensure_signed(origin)?; @@ -1044,7 +1045,7 @@ mod dispatches { /// #[pallet::call_index(69)] #[pallet::weight(( - Weight::from_parts(6_873_000, 0) + Weight::from_parts(5_760_000, 0) .saturating_add(T::DbWeight::get().reads(0)) .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, @@ -1228,7 +1229,7 @@ mod dispatches { pub fn dissolve_network( origin: OriginFor, coldkey: T::AccountId, - netuid: u16, + netuid: NetUid, ) -> DispatchResult { ensure_root(origin)?; Self::user_remove_network(coldkey, netuid) @@ -1286,7 +1287,7 @@ mod dispatches { pub fn set_children( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, children: Vec<(u64, T::AccountId)>, ) -> DispatchResultWithPostInfo { Self::do_schedule_children(origin, hotkey, netuid, children)?; @@ -1406,7 +1407,7 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(31)), DispatchClass::Operational, Pays::Yes))] pub fn schedule_dissolve_network( _origin: OriginFor, - _netuid: u16, + _netuid: NetUid, ) -> DispatchResultWithPostInfo { Err(Error::::CallDisabled.into()) @@ -1464,7 +1465,7 @@ mod dispatches { /// - The ip type v4 or v6. /// #[pallet::call_index(68)] - #[pallet::weight((Weight::from_parts(32_340_000, 0) + #[pallet::weight((Weight::from_parts(38_980_000, 0) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::Yes))] pub fn set_identity( @@ -1511,13 +1512,14 @@ mod dispatches { .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::Yes))] pub fn set_subnet_identity( origin: OriginFor, - netuid: u16, + netuid: NetUid, subnet_name: Vec, github_repo: Vec, subnet_contact: Vec, subnet_url: Vec, discord: Vec, description: Vec, + logo_url: Vec, additional: Vec, ) -> DispatchResult { Self::do_set_subnet_identity( @@ -1529,6 +1531,7 @@ mod dispatches { subnet_url, discord, description, + logo_url, additional, ) } @@ -1541,7 +1544,7 @@ mod dispatches { pub fn register_network_with_identity( origin: OriginFor, hotkey: T::AccountId, - identity: Option, + identity: Option, ) -> DispatchResult { Self::do_register_network(origin, &hotkey, 1, identity) } @@ -1605,9 +1608,9 @@ mod dispatches { /// * `TxRateLimitExceeded`: /// - Thrown if key has hit transaction rate limit #[pallet::call_index(84)] - #[pallet::weight((Weight::from_parts(68_730_000, 0) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(6)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(369_500_000, 0) + .saturating_add(T::DbWeight::get().reads(32)) + .saturating_add(T::DbWeight::get().writes(16)), DispatchClass::Operational, Pays::No))] pub fn unstake_all_alpha(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_unstake_all_alpha(origin, hotkey) } @@ -1634,15 +1637,15 @@ mod dispatches { /// - The alpha stake amount to move. /// #[pallet::call_index(85)] - #[pallet::weight((Weight::from_parts(196_600_000, 0) - .saturating_add(T::DbWeight::get().reads(17)) - .saturating_add(T::DbWeight::get().writes(13)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(419_500_000, 0) + .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().writes(19)), DispatchClass::Operational, Pays::No))] pub fn move_stake( origin: T::RuntimeOrigin, origin_hotkey: T::AccountId, destination_hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> DispatchResult { Self::do_move_stake( @@ -1677,15 +1680,15 @@ mod dispatches { /// # Events /// May emit a `StakeTransferred` event on success. #[pallet::call_index(86)] - #[pallet::weight((Weight::from_parts(207_300_000, 0) - .saturating_add(T::DbWeight::get().reads(16)) - .saturating_add(T::DbWeight::get().writes(13)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(432_600_000, 0) + .saturating_add(T::DbWeight::get().reads(30)) + .saturating_add(T::DbWeight::get().writes(19)), DispatchClass::Operational, Pays::No))] pub fn transfer_stake( origin: T::RuntimeOrigin, destination_coldkey: T::AccountId, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> DispatchResult { Self::do_transfer_stake( @@ -1719,8 +1722,8 @@ mod dispatches { /// May emit a `StakeSwapped` event on success. #[pallet::call_index(87)] #[pallet::weight(( - Weight::from_parts(221_600_000, 0) - .saturating_add(T::DbWeight::get().reads(25)) + Weight::from_parts(351_300_000, 0) + .saturating_add(T::DbWeight::get().reads(31)) .saturating_add(T::DbWeight::get().writes(16)), DispatchClass::Operational, Pays::No @@ -1728,8 +1731,8 @@ mod dispatches { pub fn swap_stake( origin: T::RuntimeOrigin, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> DispatchResult { Self::do_swap_stake( @@ -1784,13 +1787,13 @@ mod dispatches { /// - Errors stemming from transaction pallet. /// #[pallet::call_index(88)] - #[pallet::weight((Weight::from_parts(159_200_000, 0) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(402_800_000, 0) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(14)), DispatchClass::Normal, Pays::No))] pub fn add_stake_limit( origin: OriginFor, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, amount_staked: u64, limit_price: u64, allow_partial: bool, @@ -1848,13 +1851,13 @@ mod dispatches { /// - Thrown if there is not enough stake on the hotkey to withdwraw this amount. /// #[pallet::call_index(89)] - #[pallet::weight((Weight::from_parts(192_600_000, 0) - .saturating_add(T::DbWeight::get().reads(18)) - .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(403_800_000, 0) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(14)), DispatchClass::Normal, Pays::No))] pub fn remove_stake_limit( origin: OriginFor, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, amount_unstaked: u64, limit_price: u64, allow_partial: bool, @@ -1892,8 +1895,8 @@ mod dispatches { /// May emit a `StakeSwapped` event on success. #[pallet::call_index(90)] #[pallet::weight(( - Weight::from_parts(232_000_000, 0) - .saturating_add(T::DbWeight::get().reads(25)) + Weight::from_parts(426_500_000, 0) + .saturating_add(T::DbWeight::get().reads(31)) .saturating_add(T::DbWeight::get().writes(16)), DispatchClass::Operational, Pays::No @@ -1901,8 +1904,8 @@ mod dispatches { pub fn swap_stake_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, limit_price: u64, allow_partial: bool, @@ -1957,7 +1960,7 @@ mod dispatches { DispatchClass::Operational, Pays::Yes ))] - pub fn start_call(origin: T::RuntimeOrigin, netuid: u16) -> DispatchResult { + pub fn start_call(origin: T::RuntimeOrigin, netuid: NetUid) -> DispatchResult { Self::do_start_call(origin, netuid)?; Ok(()) } @@ -1997,13 +2000,12 @@ mod dispatches { ))] pub fn associate_evm_key( origin: T::RuntimeOrigin, - netuid: u16, - hotkey: T::AccountId, + netuid: NetUid, evm_key: H160, block_number: u64, signature: Signature, ) -> DispatchResult { - Self::do_associate_evm_key(origin, netuid, hotkey, evm_key, block_number, signature) + Self::do_associate_evm_key(origin, netuid, evm_key, block_number, signature) } /// Recycles alpha from a cold/hot key pair, reducing AlphaOut on a subnet @@ -2026,7 +2028,7 @@ mod dispatches { origin: T::RuntimeOrigin, hotkey: T::AccountId, amount: u64, - netuid: u16, + netuid: NetUid, ) -> DispatchResult { Self::do_recycle_alpha(origin, hotkey, amount, netuid) } @@ -2051,293 +2053,21 @@ mod dispatches { origin: T::RuntimeOrigin, hotkey: T::AccountId, amount: u64, - netuid: u16, + netuid: NetUid, ) -> DispatchResult { Self::do_burn_alpha(origin, hotkey, amount, netuid) } - // /// --- Adds stake to a hotkey on a subnet with a price limit. - // /// This extrinsic allows to specify the limit price for alpha token - // /// at which or better (lower) the staking should execute. - // /// - // /// In case if slippage occurs and the price shall move beyond the limit - // /// price, the staking order may execute only partially or not execute - // /// at all. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * 'origin': (Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * 'hotkey' (T::AccountId): - // /// - The associated hotkey account. - // /// - // /// * 'netuid' (u16): - // /// - Subnetwork UID - // /// - // /// * 'amount_staked' (u64): - // /// - The amount of stake to be added to the hotkey staking account. - // /// - // /// # Event: - // /// * StakeAdded; - // /// - On the successfully adding stake to a global account. - // /// - // /// # Raises: - // /// * 'NotEnoughBalanceToStake': - // /// - Not enough balance on the coldkey to add onto the global account. - // /// - // /// * 'NonAssociatedColdKey': - // /// - The calling coldkey is not associated with this hotkey. - // /// - // /// * 'BalanceWithdrawalError': - // /// - Errors stemming from transaction pallet. - // /// - // #[pallet::call_index(103)] - // #[pallet::weight((Weight::from_parts(162_000_000, 5127) - // .saturating_add(T::DbWeight::get().reads(15_u64)) - // .saturating_add(T::DbWeight::get().writes(12_u64)), DispatchClass::Normal, Pays::No))] - // pub fn add_stake_aggregate( - // origin: OriginFor, - // hotkey: T::AccountId, - // netuid: u16, - // amount_staked: u64, - // ) -> DispatchResult { - // Self::do_add_stake_aggregate(origin, hotkey, netuid, amount_staked) - // } - - // /// --- Removes stake from a hotkey on a subnet with a price limit. - // /// This extrinsic allows to specify the limit price for alpha token - // /// at which or better (higher) the staking should execute. - // /// - // /// In case if slippage occurs and the price shall move beyond the limit - // /// price, the staking order may execute only partially or not execute - // /// at all. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * 'origin': (Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * 'hotkey' (T::AccountId): - // /// - The associated hotkey account. - // /// - // /// * 'netuid' (u16): - // /// - Subnetwork UID - // /// - // /// * 'amount_unstaked' (u64): - // /// - The amount of stake to be added to the hotkey staking account. - // /// - // /// # Event: - // /// * StakeRemoved; - // /// - On the successfully removing stake from the hotkey account. - // /// - // /// # Raises: - // /// * 'NotRegistered': - // /// - Thrown if the account we are attempting to unstake from is non existent. - // /// - // /// * 'NonAssociatedColdKey': - // /// - Thrown if the coldkey does not own the hotkey we are unstaking from. - // /// - // /// * 'NotEnoughStakeToWithdraw': - // /// - Thrown if there is not enough stake on the hotkey to withdwraw this amount. - // /// - // #[pallet::call_index(104)] - // #[pallet::weight((Weight::from_parts(213_300_000, 10163) - // .saturating_add(T::DbWeight::get().reads(20_u64)) - // .saturating_add(T::DbWeight::get().writes(12_u64)), DispatchClass::Normal, Pays::No))] - // pub fn remove_stake_aggregate( - // origin: OriginFor, - // hotkey: T::AccountId, - // netuid: u16, - // amount_unstaked: u64, - // ) -> DispatchResult { - // Self::do_remove_stake_aggregate(origin, hotkey, netuid, amount_unstaked) - // } - - // /// --- Adds stake to a hotkey on a subnet with a price limit. - // /// This extrinsic allows to specify the limit price for alpha token - // /// at which or better (lower) the staking should execute. - // /// - // /// In case if slippage occurs and the price shall move beyond the limit - // /// price, the staking order may execute only partially or not execute - // /// at all. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * 'origin': (Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * 'hotkey' (T::AccountId): - // /// - The associated hotkey account. - // /// - // /// * 'netuid' (u16): - // /// - Subnetwork UID - // /// - // /// * 'amount_staked' (u64): - // /// - The amount of stake to be added to the hotkey staking account. - // /// - // /// * 'limit_price' (u64): - // /// - The limit price expressed in units of RAO per one Alpha. - // /// - // /// * 'allow_partial' (bool): - // /// - Allows partial execution of the amount. If set to false, this becomes - // /// fill or kill type or order. - // /// - // /// # Event: - // /// * StakeAdded; - // /// - On the successfully adding stake to a global account. - // /// - // /// # Raises: - // /// * 'NotEnoughBalanceToStake': - // /// - Not enough balance on the coldkey to add onto the global account. - // /// - // /// * 'NonAssociatedColdKey': - // /// - The calling coldkey is not associated with this hotkey. - // /// - // /// * 'BalanceWithdrawalError': - // /// - Errors stemming from transaction pallet. - // /// - // #[pallet::call_index(105)] - // #[pallet::weight((Weight::from_parts(169_200_000, 5127) - // .saturating_add(T::DbWeight::get().reads(14_u64)) - // .saturating_add(T::DbWeight::get().writes(12_u64)), DispatchClass::Normal, Pays::No))] - // pub fn add_stake_limit_aggregate( - // origin: OriginFor, - // hotkey: T::AccountId, - // netuid: u16, - // amount_staked: u64, - // limit_price: u64, - // allow_partial: bool, - // ) -> DispatchResult { - // Self::do_add_stake_limit_aggregate( - // origin, - // hotkey, - // netuid, - // amount_staked, - // limit_price, - // allow_partial, - // ) - // } - - // /// --- Removes stake from a hotkey on a subnet with a price limit. - // /// This extrinsic allows to specify the limit price for alpha token - // /// at which or better (higher) the staking should execute. - // /// - // /// In case if slippage occurs and the price shall move beyond the limit - // /// price, the staking order may execute only partially or not execute - // /// at all. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * 'origin': (Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * 'hotkey' (T::AccountId): - // /// - The associated hotkey account. - // /// - // /// * 'netuid' (u16): - // /// - Subnetwork UID - // /// - // /// * 'amount_unstaked' (u64): - // /// - The amount of stake to be added to the hotkey staking account. - // /// - // /// * 'limit_price' (u64): - // /// - The limit price expressed in units of RAO per one Alpha. - // /// - // /// * 'allow_partial' (bool): - // /// - Allows partial execution of the amount. If set to false, this becomes - // /// fill or kill type or order. - // /// - // /// # Event: - // /// * StakeRemoved; - // /// - On the successfully removing stake from the hotkey account. - // /// - // /// # Raises: - // /// * 'NotRegistered': - // /// - Thrown if the account we are attempting to unstake from is non existent. - // /// - // /// * 'NonAssociatedColdKey': - // /// - Thrown if the coldkey does not own the hotkey we are unstaking from. - // /// - // /// * 'NotEnoughStakeToWithdraw': - // /// - Thrown if there is not enough stake on the hotkey to withdwraw this amount. - // /// - // #[pallet::call_index(106)] - // #[pallet::weight((Weight::from_parts(211_700_000, 10163) - // .saturating_add(T::DbWeight::get().reads(19_u64)) - // .saturating_add(T::DbWeight::get().writes(12_u64)), DispatchClass::Normal, Pays::No))] - // pub fn remove_stake_limit_aggregate( - // origin: OriginFor, - // hotkey: T::AccountId, - // netuid: u16, - // amount_unstaked: u64, - // limit_price: u64, - // allow_partial: bool, - // ) -> DispatchResult { - // Self::do_remove_stake_limit_aggregate( - // origin, - // hotkey, - // netuid, - // amount_unstaked, - // limit_price, - // allow_partial, - // ) - // } - - // /// ---- The implementation for the extrinsic unstake_all_aggregate: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * `origin` - (::Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * `hotkey` (T::AccountId): - // /// - The associated hotkey account. - // /// - // /// # Event: - // /// * StakeRemoved; - // /// - On the successfully removing stake from the hotkey account. - // /// - // /// # Raises: - // /// * `NotRegistered`: - // /// - Thrown if the account we are attempting to unstake from is non existent. - // /// - // /// * `NonAssociatedColdKey`: - // /// - Thrown if the coldkey does not own the hotkey we are unstaking from. - // /// - // /// * `NotEnoughStakeToWithdraw`: - // /// - Thrown if there is not enough stake on the hotkey to withdraw this amount. - // /// - // /// * `TxRateLimitExceeded`: - // /// - Thrown if key has hit transaction rate limit - // #[pallet::call_index(107)] - // #[pallet::weight((Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No))] - // pub fn unstake_all_aggregate(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { - // Self::do_unstake_all_aggregate(origin, hotkey) - // } - - // /// ---- The implementation for the extrinsic unstake_all_alpha_aggregate: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. - // /// - // /// The operation will be delayed. - // /// - // /// # Args: - // /// * `origin` - (::Origin): - // /// - The signature of the caller's coldkey. - // /// - // /// * `hotkey` (T::AccountId): - // /// - The associated hotkey account. - // #[pallet::call_index(108)] - // #[pallet::weight((Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No))] - // pub fn unstake_all_alpha_aggregate( - // origin: OriginFor, - // hotkey: T::AccountId, - // ) -> DispatchResult { - // Self::do_unstake_all_alpha_aggregate(origin, hotkey) - // } + /// Sets the pending childkey cooldown (in blocks). Root only. + #[pallet::call_index(109)] + #[pallet::weight((Weight::from_parts(10_000, 0), DispatchClass::Operational, Pays::No))] + pub fn set_pending_childkey_cooldown( + origin: OriginFor, + cooldown: u64, + ) -> DispatchResult { + ensure_root(origin)?; + PendingChildKeyCooldown::::put(cooldown); + Ok(()) + } } } diff --git a/pallets/subtensor/src/macros/errors.rs b/pallets/subtensor/src/macros/errors.rs index 2a8e5bc346..fd7bc12e16 100644 --- a/pallets/subtensor/src/macros/errors.rs +++ b/pallets/subtensor/src/macros/errors.rs @@ -210,9 +210,13 @@ mod errors { InvalidRecoveredPublicKey, /// SubToken disabled now SubtokenDisabled, + /// Too frequent hotkey swap on subnet + HotKeySwapOnSubnetIntervalNotPassed, /// Zero max stake amount ZeroMaxStakeAmount, /// Invalid netuid duplication SameNetuid, + /// The caller does not have enough balance for the operation. + InsufficientBalance, } } diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index 9849a517ee..3f3c71860d 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -10,107 +10,90 @@ mod events { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// a new network is added. - NetworkAdded(u16, u16), + NetworkAdded(NetUid, u16), /// a network is removed. - NetworkRemoved(u16), + NetworkRemoved(NetUid), /// stake has been transferred from the a coldkey account onto the hotkey staking account. - StakeAdded(T::AccountId, T::AccountId, u64, u64, u16, u64), + StakeAdded(T::AccountId, T::AccountId, u64, u64, NetUid, u64), /// stake has been removed from the hotkey staking account onto the coldkey account. - StakeRemoved(T::AccountId, T::AccountId, u64, u64, u16, u64), - /// stake has been transferred from the coldkey account onto the hotkey staking account (at the end of the block) - AggregatedStakeAdded(T::AccountId, T::AccountId, u16, u64), - /// adding aggregated stake has failed - FailedToAddAggregatedStake(T::AccountId, T::AccountId, u16, u64), - /// limited stake has been transferred from the coldkey account onto the hotkey staking account (at the end of the block) - AggregatedLimitedStakeAdded(T::AccountId, T::AccountId, u16, u64, u64, bool), - /// adding limited aggregated stake has failed - FailedToAddAggregatedLimitedStake(T::AccountId, T::AccountId, u16, u64, u64, bool), - /// stake has been removed from the hotkey staking account into the coldkey account (at the end of the block). - AggregatedStakeRemoved(T::AccountId, T::AccountId, u16, u64), - /// removing aggregated stake has failed - FailedToRemoveAggregatedStake(T::AccountId, T::AccountId, u16, u64), - /// aggregated limited stake has been removed from the hotkey staking account into the coldkey account (at the end of the block). - AggregatedLimitedStakeRemoved(T::AccountId, T::AccountId, u16, u64, u64, bool), - /// removing limited aggregated stake has failed - FailedToRemoveAggregatedLimitedStake(T::AccountId, T::AccountId, u16, u64, u64, bool), - /// aggregated unstake_all operation has succeeded - AggregatedUnstakeAllSucceeded(T::AccountId, T::AccountId), - /// aggregated unstake_all operation has failed - AggregatedUnstakeAllFailed(T::AccountId, T::AccountId), - /// aggregated unstake_all_alpha operation has succeeded - AggregatedUnstakeAllAlphaSucceeded(T::AccountId, T::AccountId), - /// aggregated unstake_all_alpha operation has failed - AggregatedUnstakeAllAlphaFailed(T::AccountId, T::AccountId), + StakeRemoved(T::AccountId, T::AccountId, u64, u64, NetUid, u64), /// stake has been moved from origin (hotkey, subnet ID) to destination (hotkey, subnet ID) of this amount (in TAO). - StakeMoved(T::AccountId, T::AccountId, u16, T::AccountId, u16, u64), + StakeMoved( + T::AccountId, + T::AccountId, + NetUid, + T::AccountId, + NetUid, + u64, + ), /// a caller successfully sets their weights on a subnetwork. - WeightsSet(u16, u16), + WeightsSet(NetUid, u16), /// a new neuron account has been registered to the chain. - NeuronRegistered(u16, u16, T::AccountId), + NeuronRegistered(NetUid, u16, T::AccountId), /// multiple uids have been concurrently registered. BulkNeuronsRegistered(u16, u16), /// FIXME: Not used yet BulkBalancesSet(u16, u16), /// max allowed uids has been set for a subnetwork. - MaxAllowedUidsSet(u16, u16), + MaxAllowedUidsSet(NetUid, u16), /// the max weight limit has been set for a subnetwork. - MaxWeightLimitSet(u16, u16), + MaxWeightLimitSet(NetUid, u16), /// the difficulty has been set for a subnet. - DifficultySet(u16, u64), + DifficultySet(NetUid, u64), /// the adjustment interval is set for a subnet. - AdjustmentIntervalSet(u16, u16), + AdjustmentIntervalSet(NetUid, u16), /// registration per interval is set for a subnet. - RegistrationPerIntervalSet(u16, u16), + RegistrationPerIntervalSet(NetUid, u16), /// we set max registrations per block. - MaxRegistrationsPerBlockSet(u16, u16), + MaxRegistrationsPerBlockSet(NetUid, u16), /// an activity cutoff is set for a subnet. - ActivityCutoffSet(u16, u16), + ActivityCutoffSet(NetUid, u16), /// Rho value is set. - RhoSet(u16, u16), + RhoSet(NetUid, u16), /// steepness of the sigmoid used to compute alpha values. - AlphaSigmoidSteepnessSet(u16, u16), + AlphaSigmoidSteepnessSet(NetUid, i16), /// Kappa is set for a subnet. - KappaSet(u16, u16), + KappaSet(NetUid, u16), /// minimum allowed weight is set for a subnet. - MinAllowedWeightSet(u16, u16), + MinAllowedWeightSet(NetUid, u16), /// the validator pruning length has been set. - ValidatorPruneLenSet(u16, u64), + ValidatorPruneLenSet(NetUid, u64), /// the scaling law power has been set for a subnet. - ScalingLawPowerSet(u16, u16), + ScalingLawPowerSet(NetUid, u16), /// weights set rate limit has been set for a subnet. - WeightsSetRateLimitSet(u16, u64), + WeightsSetRateLimitSet(NetUid, u64), /// immunity period is set for a subnet. - ImmunityPeriodSet(u16, u16), + ImmunityPeriodSet(NetUid, u16), /// bonds moving average is set for a subnet. - BondsMovingAverageSet(u16, u64), + BondsMovingAverageSet(NetUid, u64), /// bonds penalty is set for a subnet. - BondsPenaltySet(u16, u16), + BondsPenaltySet(NetUid, u16), /// bonds reset is set for a subnet. - BondsResetOnSet(u16, bool), + BondsResetOnSet(NetUid, bool), /// setting the max number of allowed validators on a subnet. - MaxAllowedValidatorsSet(u16, u16), + MaxAllowedValidatorsSet(NetUid, u16), /// the axon server information is added to the network. - AxonServed(u16, T::AccountId), + AxonServed(NetUid, T::AccountId), /// the prometheus server information is added to the network. - PrometheusServed(u16, T::AccountId), + PrometheusServed(NetUid, T::AccountId), /// a hotkey has become a delegate. DelegateAdded(T::AccountId, T::AccountId, u16), /// the default take is set. DefaultTakeSet(u16), /// weights version key is set for a network. - WeightsVersionKeySet(u16, u64), + WeightsVersionKeySet(NetUid, u64), /// setting min difficulty on a network. - MinDifficultySet(u16, u64), + MinDifficultySet(NetUid, u64), /// setting max difficulty on a network. - MaxDifficultySet(u16, u64), + MaxDifficultySet(NetUid, u64), /// setting the prometheus serving rate limit. - ServingRateLimitSet(u16, u64), + ServingRateLimitSet(NetUid, u64), /// setting burn on a network. - BurnSet(u16, u64), + BurnSet(NetUid, u64), /// setting max burn on a network. - MaxBurnSet(u16, u64), + MaxBurnSet(NetUid, u64), /// setting min burn on a network. - MinBurnSet(u16, u64), + MinBurnSet(NetUid, u64), /// setting the transaction rate limit. TxRateLimitSet(u64), /// setting the delegate take transaction rate limit. @@ -126,19 +109,19 @@ mod events { /// a sudo call is done. Sudid(DispatchResult), /// registration is allowed/disallowed for a subnet. - RegistrationAllowed(u16, bool), + RegistrationAllowed(NetUid, bool), /// POW registration is allowed/disallowed for a subnet. - PowRegistrationAllowed(u16, bool), + PowRegistrationAllowed(NetUid, bool), /// setting tempo on a network - TempoSet(u16, u16), + TempoSet(NetUid, u16), /// setting the RAO recycled for registration. - RAORecycledForRegistrationSet(u16, u64), + RAORecycledForRegistrationSet(NetUid, u64), /// min stake is set for validators to set weights. StakeThresholdSet(u64), /// setting the minimum required stake amount for senate registration. SenateRequiredStakePercentSet(u64), /// setting the adjustment alpha on a subnet. - AdjustmentAlphaSet(u16, u64), + AdjustmentAlphaSet(NetUid, u64), /// the faucet it called on the test net. Faucet(T::AccountId, u64), /// the subnet owner cut is set. @@ -214,9 +197,9 @@ mod events { coldkey: T::AccountId, }, /// Setting of children of a hotkey have been scheduled - SetChildrenScheduled(T::AccountId, u16, u64, Vec<(u64, T::AccountId)>), + SetChildrenScheduled(T::AccountId, NetUid, u64, Vec<(u64, T::AccountId)>), /// The children of a hotkey have been set - SetChildren(T::AccountId, u16, Vec<(u64, T::AccountId)>), + SetChildren(T::AccountId, NetUid, Vec<(u64, T::AccountId)>), // /// The hotkey emission tempo has been set // HotkeyEmissionTempoSet(u64), // /// The network maximum stake has been set @@ -224,15 +207,15 @@ mod events { /// The identity of a coldkey has been set ChainIdentitySet(T::AccountId), /// The identity of a subnet has been set - SubnetIdentitySet(u16), + SubnetIdentitySet(NetUid), /// The identity of a subnet has been removed - SubnetIdentityRemoved(u16), + SubnetIdentityRemoved(NetUid), /// A dissolve network extrinsic scheduled. DissolveNetworkScheduled { /// The account ID schedule the dissolve network extrisnic account: T::AccountId, /// network ID will be dissolved - netuid: u16, + netuid: NetUid, /// extrinsic execution block number execution_block: BlockNumberFor, }, @@ -245,33 +228,33 @@ mod events { /// - **who**: The account ID of the user committing the weights. /// - **netuid**: The network identifier. /// - **commit_hash**: The hash representing the committed weights. - CRV3WeightsCommitted(T::AccountId, u16, H256), + CRV3WeightsCommitted(T::AccountId, NetUid, H256), /// Weights have been successfully committed. /// /// - **who**: The account ID of the user committing the weights. /// - **netuid**: The network identifier. /// - **commit_hash**: The hash representing the committed weights. - WeightsCommitted(T::AccountId, u16, H256), + WeightsCommitted(T::AccountId, NetUid, H256), /// Weights have been successfully revealed. /// /// - **who**: The account ID of the user revealing the weights. /// - **netuid**: The network identifier. /// - **commit_hash**: The hash of the revealed weights. - WeightsRevealed(T::AccountId, u16, H256), + WeightsRevealed(T::AccountId, NetUid, H256), /// Weights have been successfully batch revealed. /// /// - **who**: The account ID of the user revealing the weights. /// - **netuid**: The network identifier. /// - **revealed_hashes**: A vector of hashes representing each revealed weight set. - WeightsBatchRevealed(T::AccountId, u16, Vec), + WeightsBatchRevealed(T::AccountId, NetUid, Vec), /// A batch of weights (or commits) have been force-set. /// /// - **netuids**: The netuids these weights were successfully set/committed for. /// - **who**: The hotkey that set this batch. - BatchWeightsCompleted(Vec>, T::AccountId), + BatchWeightsCompleted(Vec>, T::AccountId), /// A batch extrinsic completed but with some errors. BatchCompletedWithErrors(), @@ -284,48 +267,55 @@ mod events { /// Stake has been transferred from one coldkey to another on the same subnet. /// Parameters: /// (origin_coldkey, destination_coldkey, hotkey, origin_netuid, destination_netuid, amount) - StakeTransferred(T::AccountId, T::AccountId, T::AccountId, u16, u16, u64), + StakeTransferred( + T::AccountId, + T::AccountId, + T::AccountId, + NetUid, + NetUid, + u64, + ), /// Stake has been swapped from one subnet to another for the same coldkey-hotkey pair. /// /// Parameters: /// (coldkey, hotkey, origin_netuid, destination_netuid, amount) - StakeSwapped(T::AccountId, T::AccountId, u16, u16, u64), + StakeSwapped(T::AccountId, T::AccountId, NetUid, NetUid, u64), /// Event called when transfer is toggled on a subnet. /// /// Parameters: /// (netuid, bool) - TransferToggle(u16, bool), + TransferToggle(NetUid, bool), /// The owner hotkey for a subnet has been set. /// /// Parameters: /// (netuid, new_hotkey) - SubnetOwnerHotkeySet(u16, T::AccountId), + SubnetOwnerHotkeySet(NetUid, T::AccountId), /// FirstEmissionBlockNumber is set via start call extrinsic /// /// Parameters: /// netuid /// block number - FirstEmissionBlockNumberSet(u16, u64), + FirstEmissionBlockNumberSet(NetUid, u64), /// Alpha has been recycled, reducing AlphaOut on a subnet. /// /// Parameters: /// (coldkey, hotkey, amount, subnet_id) - AlphaRecycled(T::AccountId, T::AccountId, u64, u16), + AlphaRecycled(T::AccountId, T::AccountId, u64, NetUid), /// Alpha have been burned without reducing AlphaOut. /// /// Parameters: /// (coldkey, hotkey, amount, subnet_id) - AlphaBurned(T::AccountId, T::AccountId, u64, u16), + AlphaBurned(T::AccountId, T::AccountId, u64, NetUid), /// An EVM key has been associated with a hotkey. EvmKeyAssociated { /// The subnet that the hotkey belongs to. - netuid: u16, + netuid: NetUid, /// The hotkey associated with the EVM key. hotkey: T::AccountId, /// The EVM key being associated with the hotkey. @@ -338,18 +328,30 @@ mod events { /// /// - **netuid**: The network identifier. /// - **who**: The account ID of the user revealing the weights. - CRV3WeightsRevealed(u16, T::AccountId), + CRV3WeightsRevealed(NetUid, T::AccountId), /// Commit-Reveal periods has been successfully set. /// /// - **netuid**: The network identifier. /// - **periods**: The number of epochs before the reveal. - CommitRevealPeriodsSet(u16, u64), + CommitRevealPeriodsSet(NetUid, u64), /// Commit-Reveal has been successfully toggled. /// /// - **netuid**: The network identifier. /// - **Enabled**: Is Commit-Reveal enabled. - CommitRevealEnabled(u16, bool), + CommitRevealEnabled(NetUid, bool), + + /// the hotkey is swapped + HotkeySwappedOnSubnet { + /// the account ID of coldkey + coldkey: T::AccountId, + /// the account ID of old hotkey + old_hotkey: T::AccountId, + /// the account ID of new hotkey + new_hotkey: T::AccountId, + /// the subnet ID + netuid: NetUid, + }, } } diff --git a/pallets/subtensor/src/macros/genesis.rs b/pallets/subtensor/src/macros/genesis.rs index f1288c5a63..ff8f4864b4 100644 --- a/pallets/subtensor/src/macros/genesis.rs +++ b/pallets/subtensor/src/macros/genesis.rs @@ -11,98 +11,91 @@ mod genesis { // Set initial total issuance from balances TotalIssuance::::put(self.balances_issuance); - // Get the root network uid. - let root_netuid: u16 = 0; - // Set the root network as added. - NetworksAdded::::insert(root_netuid, true); + NetworksAdded::::insert(NetUid::ROOT, true); // Increment the number of total networks. TotalNetworks::::mutate(|n| *n = n.saturating_add(1)); // Set the number of validators to 1. - SubnetworkN::::insert(root_netuid, 0); + SubnetworkN::::insert(NetUid::ROOT, 0); // Set the maximum number to the number of senate members. - MaxAllowedUids::::insert(root_netuid, 64u16); + MaxAllowedUids::::insert(NetUid::ROOT, 64u16); // Set the maximum number to the number of validators to all members. - MaxAllowedValidators::::insert(root_netuid, 64u16); + MaxAllowedValidators::::insert(NetUid::ROOT, 64u16); // Set the min allowed weights to zero, no weights restrictions. - MinAllowedWeights::::insert(root_netuid, 0); + MinAllowedWeights::::insert(NetUid::ROOT, 0); // Set the max weight limit to infitiy, no weight restrictions. - MaxWeightsLimit::::insert(root_netuid, u16::MAX); + MaxWeightsLimit::::insert(NetUid::ROOT, u16::MAX); // Add default root tempo. - Tempo::::insert(root_netuid, 100); + Tempo::::insert(NetUid::ROOT, 100); // Set the root network as open. - NetworkRegistrationAllowed::::insert(root_netuid, true); + NetworkRegistrationAllowed::::insert(NetUid::ROOT, true); // Set target registrations for validators as 1 per block. - TargetRegistrationsPerInterval::::insert(root_netuid, 1); - - for net in 1..2 { - let netuid: u16 = net as u16; - let hotkey = DefaultAccount::::get(); - SubnetMechanism::::insert(netuid, 1); // Make dynamic. - Owner::::insert(hotkey.clone(), hotkey.clone()); - SubnetAlphaIn::::insert(netuid, 10_000_000_000); - SubnetTAO::::insert(netuid, 10_000_000_000); - NetworksAdded::::insert(netuid, true); - TotalNetworks::::mutate(|n| *n = n.saturating_add(1)); - SubnetworkN::::insert(netuid, 0); - MaxAllowedUids::::insert(netuid, 256u16); - MaxAllowedValidators::::insert(netuid, 64u16); - MinAllowedWeights::::insert(netuid, 0); - MaxWeightsLimit::::insert(netuid, u16::MAX); - Tempo::::insert(netuid, 100); - NetworkRegistrationAllowed::::insert(netuid, true); - SubnetOwner::::insert(netuid, hotkey.clone()); - SubnetLocked::::insert(netuid, 1); - LargestLocked::::insert(netuid, 1); - Alpha::::insert( - // Lock the initial funds making this key the owner. - (hotkey.clone(), hotkey.clone(), netuid), - U64F64::saturating_from_num(1_000_000_000), - ); - TotalHotkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); - TotalHotkeyShares::::insert( - hotkey.clone(), - netuid, - U64F64::saturating_from_num(1_000_000_000), - ); - // TotalColdkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); - SubnetAlphaOut::::insert(netuid, 1_000_000_000); - let mut staking_hotkeys = StakingHotkeys::::get(hotkey.clone()); - if !staking_hotkeys.contains(&hotkey) { - staking_hotkeys.push(hotkey.clone()); - StakingHotkeys::::insert(hotkey.clone(), staking_hotkeys.clone()); - } + TargetRegistrationsPerInterval::::insert(NetUid::ROOT, 1); - let block_number = Pallet::::get_current_block_as_u64(); - for next_uid_s in 0..1 { - let next_uid: u16 = next_uid_s as u16; - SubnetworkN::::insert(netuid, next_uid.saturating_add(1)); - Rank::::mutate(netuid, |v| v.push(0)); - Trust::::mutate(netuid, |v| v.push(0)); - Active::::mutate(netuid, |v| v.push(true)); - Emission::::mutate(netuid, |v| v.push(0)); - Consensus::::mutate(netuid, |v| v.push(0)); - Incentive::::mutate(netuid, |v| v.push(0)); - Dividends::::mutate(netuid, |v| v.push(0)); - LastUpdate::::mutate(netuid, |v| v.push(block_number)); - PruningScores::::mutate(netuid, |v| v.push(0)); - ValidatorTrust::::mutate(netuid, |v| v.push(0)); - ValidatorPermit::::mutate(netuid, |v| v.push(false)); - Keys::::insert(netuid, next_uid, hotkey.clone()); // Make hotkey - uid association. - Uids::::insert(netuid, hotkey.clone(), next_uid); // Make uid - hotkey association. - BlockAtRegistration::::insert(netuid, next_uid, block_number); // Fill block at registration. - IsNetworkMember::::insert(hotkey.clone(), netuid, true); // Fill network is member. - } + let netuid = NetUid::from(1); + let hotkey = DefaultAccount::::get(); + SubnetMechanism::::insert(netuid, 1); // Make dynamic. + Owner::::insert(hotkey.clone(), hotkey.clone()); + SubnetAlphaIn::::insert(netuid, 10_000_000_000); + SubnetTAO::::insert(netuid, 10_000_000_000); + NetworksAdded::::insert(netuid, true); + TotalNetworks::::mutate(|n| *n = n.saturating_add(1)); + SubnetworkN::::insert(netuid, 0); + MaxAllowedUids::::insert(netuid, 256u16); + MaxAllowedValidators::::insert(netuid, 64u16); + MinAllowedWeights::::insert(netuid, 0); + MaxWeightsLimit::::insert(netuid, u16::MAX); + Tempo::::insert(netuid, 100); + NetworkRegistrationAllowed::::insert(netuid, true); + SubnetOwner::::insert(netuid, hotkey.clone()); + SubnetLocked::::insert(netuid, 1); + LargestLocked::::insert(netuid, 1); + Alpha::::insert( + // Lock the initial funds making this key the owner. + (hotkey.clone(), hotkey.clone(), netuid), + U64F64::saturating_from_num(1_000_000_000), + ); + TotalHotkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); + TotalHotkeyShares::::insert( + hotkey.clone(), + netuid, + U64F64::saturating_from_num(1_000_000_000), + ); + // TotalColdkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); + SubnetAlphaOut::::insert(netuid, 1_000_000_000); + let mut staking_hotkeys = StakingHotkeys::::get(hotkey.clone()); + if !staking_hotkeys.contains(&hotkey) { + staking_hotkeys.push(hotkey.clone()); + StakingHotkeys::::insert(hotkey.clone(), staking_hotkeys.clone()); } + + let block_number = Pallet::::get_current_block_as_u64(); + + SubnetworkN::::insert(netuid, 1); + Rank::::mutate(netuid, |v| v.push(0)); + Trust::::mutate(netuid, |v| v.push(0)); + Active::::mutate(netuid, |v| v.push(true)); + Emission::::mutate(netuid, |v| v.push(0)); + Consensus::::mutate(netuid, |v| v.push(0)); + Incentive::::mutate(netuid, |v| v.push(0)); + Dividends::::mutate(netuid, |v| v.push(0)); + LastUpdate::::mutate(netuid, |v| v.push(block_number)); + PruningScores::::mutate(netuid, |v| v.push(0)); + ValidatorTrust::::mutate(netuid, |v| v.push(0)); + ValidatorPermit::::mutate(netuid, |v| v.push(false)); + Keys::::insert(netuid, 0, hotkey.clone()); // Make hotkey - uid association. + Uids::::insert(netuid, hotkey.clone(), 0); // Make uid - hotkey association. + BlockAtRegistration::::insert(netuid, 0, block_number); // Fill block at registration. + IsNetworkMember::::insert(hotkey.clone(), netuid, true); // Fill network is member. } } } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index a0e2fc6e72..5e30388735 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -14,7 +14,9 @@ mod hooks { // # Args: // * 'n': (BlockNumberFor): // - The number of the block we are initializing. - fn on_initialize(_block_number: BlockNumberFor) -> Weight { + fn on_initialize(block_number: BlockNumberFor) -> Weight { + let hotkey_swap_clean_up_weight = Self::clean_up_hotkey_swap_records(block_number); + let block_step_result = Self::block_step(); match block_step_result { Ok(_) => { @@ -23,6 +25,7 @@ mod hooks { Weight::from_parts(110_634_229_000_u64, 0) .saturating_add(T::DbWeight::get().reads(8304_u64)) .saturating_add(T::DbWeight::get().writes(110_u64)) + .saturating_add(hotkey_swap_clean_up_weight) } Err(e) => { // --- If the block step was unsuccessful, return the weight anyway. @@ -30,6 +33,7 @@ mod hooks { Weight::from_parts(110_634_229_000_u64, 0) .saturating_add(T::DbWeight::get().reads(8304_u64)) .saturating_add(T::DbWeight::get().writes(110_u64)) + .saturating_add(hotkey_swap_clean_up_weight) } } } @@ -102,9 +106,7 @@ mod hooks { // Remove all entries in TotalHotkeyColdkeyStakesThisInterval .saturating_add(migrations::migrate_remove_total_hotkey_coldkey_stakes_this_interval::migrate_remove_total_hotkey_coldkey_stakes_this_interval::()) // Wipe the deprecated RateLimit storage item in the commitments pallet - .saturating_add(migrations::migrate_remove_commitments_rate_limit::migrate_remove_commitments_rate_limit::()); - - weight + .saturating_add(migrations::migrate_remove_commitments_rate_limit::migrate_remove_commitments_rate_limit::()) // Remove all entries in orphaned storage items .saturating_add( migrations::migrate_orphaned_storage_items::migrate_orphaned_storage_items::( @@ -127,4 +129,43 @@ mod hooks { Ok(()) } } + + impl Pallet { + // This function is to clean up the old hotkey swap records + // It just clean up for one subnet at a time, according to the block number + fn clean_up_hotkey_swap_records(block_number: BlockNumberFor) -> Weight { + let mut weight = Weight::from_parts(0, 0); + let hotkey_swap_on_subnet_interval = T::HotkeySwapOnSubnetInterval::get(); + let block_number: u64 = TryInto::try_into(block_number) + .ok() + .expect("blockchain will not exceed 2^64 blocks; QED."); + weight.saturating_accrue(T::DbWeight::get().reads(2_u64)); + + let netuids = Self::get_all_subnet_netuids(); + weight.saturating_accrue(T::DbWeight::get().reads(netuids.len() as u64)); + + if let Some(slot) = block_number.checked_rem(hotkey_swap_on_subnet_interval) { + // only handle the subnet with the same residue as current block number by HotkeySwapOnSubnetInterval + for netuid in netuids.iter().filter(|netuid| { + (u16::from(**netuid) as u64).checked_rem(hotkey_swap_on_subnet_interval) + == Some(slot) + }) { + // Iterate over all the coldkeys in the subnet + for (coldkey, swap_block_number) in + LastHotkeySwapOnNetuid::::iter_prefix(netuid) + { + // Clean up out of date swap records + if swap_block_number.saturating_add(hotkey_swap_on_subnet_interval) + < block_number + { + LastHotkeySwapOnNetuid::::remove(netuid, coldkey); + weight.saturating_accrue(T::DbWeight::get().writes(1_u64)); + } + weight.saturating_accrue(T::DbWeight::get().reads(1_u64)); + } + } + } + weight + } + } } diff --git a/pallets/subtensor/src/migrations/migrate_create_root_network.rs b/pallets/subtensor/src/migrations/migrate_create_root_network.rs index c413d1f078..24e2251c38 100644 --- a/pallets/subtensor/src/migrations/migrate_create_root_network.rs +++ b/pallets/subtensor/src/migrations/migrate_create_root_network.rs @@ -6,6 +6,7 @@ use frame_support::{ weights::Weight, }; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; // TODO (camfairchild): TEST MIGRATION @@ -39,47 +40,44 @@ pub mod deprecated_loaded_emission_format { /// let weight = migrate_create_root_network::(); /// ``` pub fn migrate_create_root_network() -> Weight { - // Define the root network UID - let root_netuid: u16 = 0; - // Initialize weight counter let mut weight = T::DbWeight::get().reads(1); // Check if root network already exists - if NetworksAdded::::get(root_netuid) { + if NetworksAdded::::get(NetUid::ROOT) { // Return early if root network already exists return weight; } // Set the root network as added - NetworksAdded::::insert(root_netuid, true); + NetworksAdded::::insert(NetUid::ROOT, true); // Increment the total number of networks TotalNetworks::::mutate(|n| *n = n.saturating_add(1)); // Set the maximum number of UIDs to the number of senate members - MaxAllowedUids::::insert(root_netuid, 64); + MaxAllowedUids::::insert(NetUid::ROOT, 64); // Set the maximum number of validators to all members - MaxAllowedValidators::::insert(root_netuid, 64); + MaxAllowedValidators::::insert(NetUid::ROOT, 64); // Set the minimum allowed weights to zero (no weight restrictions) - MinAllowedWeights::::insert(root_netuid, 0); + MinAllowedWeights::::insert(NetUid::ROOT, 0); // Set the maximum weight limit to u16::MAX (no weight restrictions) - MaxWeightsLimit::::insert(root_netuid, u16::MAX); + MaxWeightsLimit::::insert(NetUid::ROOT, u16::MAX); // Set default root tempo - Tempo::::insert(root_netuid, 100); + Tempo::::insert(NetUid::ROOT, 100); // Set the root network as open for registration - NetworkRegistrationAllowed::::insert(root_netuid, true); + NetworkRegistrationAllowed::::insert(NetUid::ROOT, true); // Set target registrations for validators as 1 per block - TargetRegistrationsPerInterval::::insert(root_netuid, 1); + TargetRegistrationsPerInterval::::insert(NetUid::ROOT, 1); // TODO: Consider if WeightsSetRateLimit should be set - // WeightsSetRateLimit::::insert(root_netuid, 7200); + // WeightsSetRateLimit::::insert(NetUid::ROOT, 7200); // Accrue weight for database writes weight.saturating_accrue(T::DbWeight::get().writes(8)); diff --git a/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs b/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs index d12a58ed37..eae5eedc87 100644 --- a/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs +++ b/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs @@ -1,12 +1,12 @@ use super::*; use frame_support::{ - pallet_prelude::*, storage_alias, traits::{Get, GetStorageVersion, StorageVersion}, weights::Weight, }; use log::info; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; /// Constant for logging purposes const LOG_TARGET: &str = "migrate_delete_subnet_21"; @@ -50,10 +50,10 @@ pub fn migrate_delete_subnet_21() -> Weight { let onchain_version = Pallet::::on_chain_storage_version(); // Only runs if we haven't already updated version past above new_storage_version and subnet 21 exists. - if onchain_version < new_storage_version && Pallet::::if_subnet_exist(21) { + if onchain_version < new_storage_version && Pallet::::if_subnet_exist(NetUid::from(21)) { info!(target: LOG_TARGET, ">>> Removing subnet 21 {:?}", onchain_version); - let netuid = 21; + let netuid = NetUid::from(21); // We do this all manually as we don't want to call code related to giving subnet owner back their locked token cost. // Remove network count diff --git a/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs b/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs index 0e85c56554..f9c4b3c196 100644 --- a/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs +++ b/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs @@ -1,6 +1,5 @@ use super::*; use frame_support::{ - pallet_prelude::*, storage_alias, traits::{Get, GetStorageVersion, StorageVersion}, weights::Weight, @@ -50,14 +49,14 @@ pub fn migrate_delete_subnet_3() -> Weight { let onchain_version = Pallet::::on_chain_storage_version(); // Only proceed if current version is less than the new version and subnet 3 exists - if onchain_version < new_storage_version && Pallet::::if_subnet_exist(3) { + if onchain_version < new_storage_version && Pallet::::if_subnet_exist(3.into()) { info!( target: LOG_TARGET, "Removing subnet 3. Current version: {:?}", onchain_version ); - let netuid = 3; + let netuid = NetUid::from(3); // Remove network count SubnetworkN::::remove(netuid); diff --git a/pallets/subtensor/src/migrations/migrate_rao.rs b/pallets/subtensor/src/migrations/migrate_rao.rs index 975ab55c11..ebc99cdb7a 100644 --- a/pallets/subtensor/src/migrations/migrate_rao.rs +++ b/pallets/subtensor/src/migrations/migrate_rao.rs @@ -1,8 +1,7 @@ -use alloc::string::String; +use alloc::{format, string::String}; use frame_support::IterableStorageMap; use frame_support::{traits::Get, weights::Weight}; -use sp_runtime::format; use super::*; @@ -25,7 +24,7 @@ pub fn migrate_rao() -> Weight { String::from_utf8_lossy(&migration_name) ); - let netuids: Vec = as IterableStorageMap>::iter() + let netuids: Vec = as IterableStorageMap>::iter() .map(|(netuid, _)| netuid) .collect(); weight = weight.saturating_add(T::DbWeight::get().reads_writes(netuids.len() as u64, 0)); @@ -62,12 +61,12 @@ pub fn migrate_rao() -> Weight { NetworkMinLockCost::::set(1_000_000_000); // Set tao weight. TaoWeight::::set(3_320_413_933_267_719_290); - for netuid in netuids.iter().clone() { - if *netuid == 0 { + for netuid in netuids.iter() { + if netuid.is_root() { // Give root a single RAO in pool to avoid any catestrophic division by zero. SubnetAlphaIn::::insert(netuid, 1_000_000_000); SubnetMechanism::::insert(netuid, 0); // Set to zero mechanism. - TokenSymbol::::insert(netuid, Pallet::::get_symbol_for_subnet(0)); + TokenSymbol::::insert(netuid, Pallet::::get_symbol_for_subnet(NetUid::ROOT)); continue; } let owner = SubnetOwner::::get(netuid); diff --git a/pallets/subtensor/src/migrations/migrate_set_first_emission_block_number.rs b/pallets/subtensor/src/migrations/migrate_set_first_emission_block_number.rs index 04ad306218..2da7cef51a 100644 --- a/pallets/subtensor/src/migrations/migrate_set_first_emission_block_number.rs +++ b/pallets/subtensor/src/migrations/migrate_set_first_emission_block_number.rs @@ -26,7 +26,7 @@ pub fn migrate_set_first_emission_block_number() -> Weight { let netuids = Pallet::::get_all_subnet_netuids(); let current_block_number = Pallet::::get_current_block_as_u64(); for netuid in netuids.iter() { - if *netuid != 0 { + if !netuid.is_root() { FirstEmissionBlockNumber::::insert(netuid, current_block_number); } } diff --git a/pallets/subtensor/src/migrations/migrate_set_min_burn.rs b/pallets/subtensor/src/migrations/migrate_set_min_burn.rs index a38badfbb1..8a74e1e51c 100644 --- a/pallets/subtensor/src/migrations/migrate_set_min_burn.rs +++ b/pallets/subtensor/src/migrations/migrate_set_min_burn.rs @@ -24,13 +24,13 @@ pub fn migrate_set_min_burn() -> Weight { String::from_utf8_lossy(&migration_name) ); - let netuids: Vec = as IterableStorageMap>::iter() + let netuids: Vec = as IterableStorageMap>::iter() .map(|(netuid, _)| netuid) .collect(); weight = weight.saturating_add(T::DbWeight::get().reads(netuids.len() as u64)); - for netuid in netuids.iter().clone() { - if *netuid == 0 { + for netuid in netuids.iter() { + if netuid.is_root() { continue; } // Set min burn to the newest initial min burn diff --git a/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs b/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs index 6d859925ae..bdc6c993e2 100644 --- a/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs +++ b/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs @@ -24,13 +24,13 @@ pub fn migrate_set_min_difficulty() -> Weight { String::from_utf8_lossy(&migration_name) ); - let netuids: Vec = as IterableStorageMap>::iter() + let netuids: Vec = as IterableStorageMap>::iter() .map(|(netuid, _)| netuid) .collect(); weight = weight.saturating_add(T::DbWeight::get().reads(netuids.len() as u64)); - for netuid in netuids.iter().clone() { - if *netuid == 0 { + for netuid in netuids.iter() { + if netuid.is_root() { continue; } // Set min difficulty to 10 million for all subnets diff --git a/pallets/subtensor/src/migrations/migrate_set_subtoken_enabled.rs b/pallets/subtensor/src/migrations/migrate_set_subtoken_enabled.rs index da4386c4b8..3b0d236f99 100644 --- a/pallets/subtensor/src/migrations/migrate_set_subtoken_enabled.rs +++ b/pallets/subtensor/src/migrations/migrate_set_subtoken_enabled.rs @@ -25,7 +25,7 @@ pub fn migrate_set_subtoken_enabled() -> Weight { // ------------------------------ let netuids = Pallet::::get_all_subnet_netuids(); for netuid in netuids.iter() { - if *netuid != 0 { + if !netuid.is_root() { // set it as true if start call executed and value exists for first emission block number SubtokenEnabled::::insert( netuid, diff --git a/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs b/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs new file mode 100644 index 0000000000..b101227787 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs @@ -0,0 +1,66 @@ +use super::*; +use frame_support::weights::Weight; +use log; +use scale_info::prelude::{string::String, vec::Vec}; + +pub fn migrate_subnet_identities_to_v3() -> Weight { + use frame_support::traits::Get; + let migration_name = b"migrate_subnet_identities_to_v3".to_vec(); + + // Start counting weight + let mut weight = T::DbWeight::get().reads(1); + + // Check if we already ran this migration + if HasMigrationRun::::get(&migration_name) { + log::info!( + target: "runtime", + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + target: "runtime", + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + // ----------------------------- + // 1) Migrate Subnet Identities + // ----------------------------- + let old_subnet_identities = SubnetIdentitiesV2::::iter().collect::>(); + for (netuid, old_subnet_identity) in old_subnet_identities.clone() { + let new_subnet_identity = SubnetIdentityV3 { + subnet_name: old_subnet_identity.subnet_name, + github_repo: old_subnet_identity.github_repo, + subnet_contact: old_subnet_identity.subnet_contact, + subnet_url: Vec::new(), + discord: Vec::new(), + description: Vec::new(), + logo_url: Vec::new(), + additional: Vec::new(), + }; + + // Insert into the new storage map + SubnetIdentitiesV3::::insert(netuid, &new_subnet_identity); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + SubnetIdentitiesV2::::remove(netuid); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + weight = weight.saturating_add(T::DbWeight::get().reads(old_subnet_identities.len() as u64)); + + // ----------------------------- + // Mark the migration as done + // ----------------------------- + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + target: "runtime", + "Migration '{}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs b/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs index 5d28337dcb..edea6a4c4b 100644 --- a/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs +++ b/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs @@ -1,6 +1,5 @@ use super::*; use frame_support::{ - pallet_prelude::*, storage_alias, traits::{Get, GetStorageVersion, StorageVersion}, weights::Weight, @@ -72,7 +71,7 @@ pub fn migrate_to_v1_separate_emission() -> Weight { // Translate old storage values to new format LoadedEmission::::translate::, u64)>, _>( - |netuid: u16, + |netuid: NetUid, netuid_emissions: Vec<(AccountIdOf, u64)>| -> Option, u64, u64)>> { info!(target: LOG_TARGET, " Do migration of netuid: {:?}...", netuid); diff --git a/pallets/subtensor/src/migrations/migrate_to_v2_fixed_total_stake.rs b/pallets/subtensor/src/migrations/migrate_to_v2_fixed_total_stake.rs index b0a711ac77..6410f79321 100644 --- a/pallets/subtensor/src/migrations/migrate_to_v2_fixed_total_stake.rs +++ b/pallets/subtensor/src/migrations/migrate_to_v2_fixed_total_stake.rs @@ -1,6 +1,5 @@ use super::*; use frame_support::{ - pallet_prelude::*, storage_alias, traits::{Get, GetStorageVersion}, weights::Weight, diff --git a/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs b/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs index 8d1bd437c6..10a93784bb 100644 --- a/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs +++ b/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs @@ -65,13 +65,13 @@ pub fn migrate_transfer_ownership_to_foundation(coldkey: [u8; 32]) -> weight.saturating_accrue(T::DbWeight::get().reads(1)); // Transfer ownership of subnets 1 and 11 to the foundation - SubnetOwner::::insert(1, coldkey_account.clone()); - SubnetOwner::::insert(11, coldkey_account); + SubnetOwner::::insert(NetUid::from(1), coldkey_account.clone()); + SubnetOwner::::insert(NetUid::from(11), coldkey_account); // Set the registration time for subnet 1 to extend immunity period - NetworkRegisteredAt::::insert(1, current_block.saturating_add(13 * 7200)); + NetworkRegisteredAt::::insert(NetUid::from(1), current_block.saturating_add(13 * 7200)); // Set the registration time for subnet 11 to the current block - NetworkRegisteredAt::::insert(11, current_block); + NetworkRegisteredAt::::insert(NetUid::from(11), current_block); weight.saturating_accrue(T::DbWeight::get().writes(4)); diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 5c6347034f..ea2cff1458 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -27,6 +27,7 @@ pub mod migrate_set_min_burn; pub mod migrate_set_min_difficulty; pub mod migrate_set_subtoken_enabled; pub mod migrate_stake_threshold; +pub mod migrate_subnet_identities_to_v3; pub mod migrate_subnet_volume; pub mod migrate_to_v1_separate_emission; pub mod migrate_to_v2_fixed_total_stake; diff --git a/pallets/subtensor/src/rpc_info/delegate_info.rs b/pallets/subtensor/src/rpc_info/delegate_info.rs index f0a2447e4f..94e4034b66 100644 --- a/pallets/subtensor/src/rpc_info/delegate_info.rs +++ b/pallets/subtensor/src/rpc_info/delegate_info.rs @@ -6,16 +6,17 @@ use substrate_fixed::types::U64F64; extern crate alloc; use alloc::collections::BTreeMap; use codec::Compact; +use subtensor_runtime_common::NetUid; -#[freeze_struct("7cd21f57627d2d0d")] +#[freeze_struct("1fafc4fcf28cba7a")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct DelegateInfo { pub delegate_ss58: AccountId, pub take: Compact, - pub nominators: Vec<(AccountId, Vec<(Compact, Compact)>)>, // map of nominator_ss58 to netuid and stake amount + pub nominators: Vec<(AccountId, Vec<(Compact, Compact)>)>, // map of nominator_ss58 to netuid and stake amount pub owner_ss58: AccountId, - pub registrations: Vec>, // Vec of netuid this delegate is registered on - pub validator_permits: Vec>, // Vec of netuid this delegate has validator permit on + pub registrations: Vec>, // Vec of netuid this delegate is registered on + pub validator_permits: Vec>, // Vec of netuid this delegate has validator permit on pub return_per_1000: Compact, // Delegators current daily return per 1000 TAO staked minus take fee pub total_daily_return: Compact, // Delegators current daily return } @@ -53,8 +54,9 @@ impl Pallet { delegate: AccountIdOf, skip_nominators: bool, ) -> DelegateInfo { - let mut nominators = Vec::<(T::AccountId, Vec<(Compact, Compact)>)>::new(); - let mut nominator_map = BTreeMap::, Compact)>>::new(); + let mut nominators = Vec::<(T::AccountId, Vec<(Compact, Compact)>)>::new(); + let mut nominator_map = + BTreeMap::, Compact)>>::new(); if !skip_nominators { let mut alpha_share_pools = vec![]; @@ -68,7 +70,7 @@ impl Pallet { continue; } - if let Some(alpha_share_pool) = alpha_share_pools.get(netuid as usize) { + if let Some(alpha_share_pool) = alpha_share_pools.get(u16::from(netuid) as usize) { let coldkey_stake = alpha_share_pool.get_value_from_shares(alpha_stake); nominator_map @@ -84,7 +86,7 @@ impl Pallet { } let registrations = Self::get_registered_networks_for_hotkey(&delegate.clone()); - let mut validator_permits = Vec::>::new(); + let mut validator_permits = Vec::>::new(); let mut emissions_per_day: U64F64 = U64F64::saturating_from_num(0); for netuid in registrations.iter() { @@ -108,7 +110,7 @@ impl Pallet { let take: Compact = >::get(delegate.clone()).into(); let total_stake: U64F64 = - Self::get_stake_for_hotkey_on_subnet(&delegate.clone(), Self::get_root_netuid()).into(); + Self::get_stake_for_hotkey_on_subnet(&delegate.clone(), NetUid::ROOT).into(); let return_per_1000: U64F64 = Self::return_per_1000_tao(take, total_stake, emissions_per_day); @@ -151,8 +153,8 @@ impl Pallet { /// pub fn get_delegated( delegatee: T::AccountId, - ) -> Vec<(DelegateInfo, (Compact, Compact))> { - let mut delegates: Vec<(DelegateInfo, (Compact, Compact))> = + ) -> Vec<(DelegateInfo, (Compact, Compact))> { + let mut delegates: Vec<(DelegateInfo, (Compact, Compact))> = Vec::new(); for delegate in as IterableStorageMap>::iter_keys() { // Staked to this delegate, so add to list diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index b363931d9c..e6838404d4 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -4,11 +4,12 @@ use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; +use subtensor_runtime_common::NetUid; -#[freeze_struct("7fbd2013e8262885")] +#[freeze_struct("ddf2c1fdd5bb7e7")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct DynamicInfo { - netuid: Compact, + netuid: Compact, owner_hotkey: AccountId, owner_coldkey: AccountId, subnet_name: Vec>, @@ -27,12 +28,12 @@ pub struct DynamicInfo { pending_root_emission: Compact, subnet_volume: Compact, network_registered_at: Compact, - subnet_identity: Option, + subnet_identity: Option, moving_price: I96F32, } impl Pallet { - pub fn get_dynamic_info(netuid: u16) -> Option> { + pub fn get_dynamic_info(netuid: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } @@ -65,12 +66,12 @@ impl Pallet { pending_root_emission: PendingRootDivs::::get(netuid).into(), subnet_volume: SubnetVolume::::get(netuid).into(), network_registered_at: NetworkRegisteredAt::::get(netuid).into(), - subnet_identity: SubnetIdentitiesV2::::get(netuid), + subnet_identity: SubnetIdentitiesV3::::get(netuid), moving_price: SubnetMovingPrice::::get(netuid), }) } pub fn get_all_dynamic_info() -> Vec>> { - let netuids: Vec = Self::get_all_subnet_netuids(); + let netuids = Self::get_all_subnet_netuids(); let mut dynamic_info = Vec::>>::new(); for netuid in netuids.clone().iter() { dynamic_info.push(Self::get_dynamic_info(*netuid)); diff --git a/pallets/subtensor/src/rpc_info/metagraph.rs b/pallets/subtensor/src/rpc_info/metagraph.rs index 04325fef4d..d910bbaff5 100644 --- a/pallets/subtensor/src/rpc_info/metagraph.rs +++ b/pallets/subtensor/src/rpc_info/metagraph.rs @@ -2,21 +2,23 @@ use super::*; extern crate alloc; use crate::epoch::math::*; use codec::Compact; +use frame_support::IterableStorageDoubleMap; use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; +use subtensor_runtime_common::NetUid; -#[freeze_struct("cb3ff125c0c35c9e")] +#[freeze_struct("140374b562d8498b")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct Metagraph { // Subnet index - netuid: Compact, + netuid: Compact, // Name and symbol name: Vec>, // name symbol: Vec>, // token symbol - identity: Option, // identity information. + identity: Option, // identity information. network_registered_at: Compact, // block at registration // Keys for owner. @@ -107,16 +109,16 @@ pub struct Metagraph { alpha_dividends_per_hotkey: Vec<(AccountId, Compact)>, // List of dividend payout in alpha via subnet. } -#[freeze_struct("182c7375fee9db7b")] +#[freeze_struct("55ca82be1558e748")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SelectiveMetagraph { // Subnet index - netuid: Compact, + netuid: Compact, // Name and symbol name: Option>>, // name symbol: Option>>, // token symbol - identity: Option>, // identity information. + identity: Option>, // identity information. network_registered_at: Option>, // block at registration // Keys for owner. @@ -205,6 +207,9 @@ pub struct SelectiveMetagraph { // Dividend break down. tao_dividends_per_hotkey: Option)>>, // List of dividend payouts in tao via root. alpha_dividends_per_hotkey: Option)>>, // List of dividend payout in alpha via subnet. + + // validators + validators: Option>>, // List of validators } impl SelectiveMetagraph @@ -361,7 +366,7 @@ where Some(SelectiveMetagraphIndex::AlphaDividendsPerHotkey) => { self.alpha_dividends_per_hotkey = other.alpha_dividends_per_hotkey.clone() } - + Some(SelectiveMetagraphIndex::Validators) => self.validators = other.validators.clone(), None => {} }; } @@ -373,7 +378,7 @@ where { fn default() -> Self { Self { - netuid: 0.into(), + netuid: NetUid::ROOT.into(), name: None, symbol: None, identity: None, @@ -445,6 +450,7 @@ where total_stake: None, tao_dividends_per_hotkey: None, alpha_dividends_per_hotkey: None, + validators: None, } } } @@ -522,6 +528,7 @@ pub enum SelectiveMetagraphIndex { TotalStake, TaoDividendsPerHotkey, AlphaDividendsPerHotkey, + Validators, } impl SelectiveMetagraphIndex { @@ -599,12 +606,13 @@ impl SelectiveMetagraphIndex { 69 => Some(SelectiveMetagraphIndex::TotalStake), 70 => Some(SelectiveMetagraphIndex::TaoDividendsPerHotkey), 71 => Some(SelectiveMetagraphIndex::AlphaDividendsPerHotkey), + 72 => Some(SelectiveMetagraphIndex::Validators), _ => None, } } } impl Pallet { - pub fn get_metagraph(netuid: u16) -> Option> { + pub fn get_metagraph(netuid: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } @@ -655,7 +663,7 @@ impl Pallet { .into_iter() .map(Compact) .collect(), // Symbol. - identity: SubnetIdentitiesV2::::get(netuid), // identity information. + identity: SubnetIdentitiesV3::::get(netuid), // identity information. network_registered_at: NetworkRegisteredAt::::get(netuid).into(), // block at registration // Keys for owner. @@ -780,7 +788,7 @@ impl Pallet { }) } pub fn get_all_metagraphs() -> Vec>> { - let netuids: Vec = Self::get_all_subnet_netuids(); + let netuids = Self::get_all_subnet_netuids(); let mut metagraphs = Vec::>>::new(); for netuid in netuids.clone().iter() { metagraphs.push(Self::get_metagraph(*netuid)); @@ -789,7 +797,7 @@ impl Pallet { } pub fn get_selective_metagraph( - netuid: u16, + netuid: NetUid, metagraph_indexes: Vec, ) -> Option> { if !Self::if_subnet_exist(netuid) { @@ -805,7 +813,7 @@ impl Pallet { } fn get_single_selective_metagraph( - netuid: u16, + netuid: NetUid, metagraph_index: u16, ) -> SelectiveMetagraph { match SelectiveMetagraphIndex::from_index(metagraph_index as usize) { @@ -836,7 +844,7 @@ impl Pallet { }, Some(SelectiveMetagraphIndex::Identity) => SelectiveMetagraph { netuid: netuid.into(), - identity: Some(SubnetIdentitiesV2::::get(netuid)), + identity: Some(SubnetIdentitiesV3::::get(netuid)), ..Default::default() }, Some(SelectiveMetagraphIndex::NetworkRegisteredAt) => SelectiveMetagraph { @@ -1356,6 +1364,7 @@ impl Pallet { ..Default::default() } } + Some(SelectiveMetagraphIndex::Validators) => Self::get_validators(netuid), None => SelectiveMetagraph { // Subnet index netuid: netuid.into(), @@ -1363,13 +1372,52 @@ impl Pallet { }, } } + + fn get_validators(netuid: NetUid) -> SelectiveMetagraph { + let stake_threshold = Self::get_stake_threshold(); + let hotkeys: Vec<(u16, T::AccountId)> = + as IterableStorageDoubleMap>::iter_prefix(netuid) + .collect(); + let validator_permits: Vec = Self::get_validator_permit(netuid); + + // filter according to validator_permits + let hotkeys: Vec<&(u16, T::AccountId)> = hotkeys + .iter() + .filter(|(uid, _)| *validator_permits.get(*uid as usize).unwrap_or(&false)) + .collect::>(); + + // map hotkeys to validators with stake + let mut validators: Vec<(u16, I64F64)> = hotkeys + .iter() + .map(|(uid, hotkey)| { + let stake = Self::get_stake_weights_for_hotkey_on_subnet(hotkey, netuid); + (*uid, stake.0) + }) + .collect(); + + // sort validators by stake + validators.sort_by(|a, b| a.1.cmp(&b.1)); + + let validators: Vec> = validators + .iter() + .filter(|(_uid, stake)| *stake > stake_threshold) + .map(|(uid, _)| Compact::from(*uid)) + .collect::>(); + + SelectiveMetagraph { + // Subnet index + netuid: netuid.into(), + validators: Some(validators), + ..Default::default() + } + } } #[test] fn test_selective_metagraph() { let mut metagraph = SelectiveMetagraph::::default(); let expected = SelectiveMetagraph:: { - netuid: 0_u16.into(), + netuid: NetUid::ROOT.into(), name: None, symbol: None, identity: None, @@ -1441,6 +1489,7 @@ fn test_selective_metagraph() { total_stake: None, tao_dividends_per_hotkey: None, alpha_dividends_per_hotkey: None, + validators: None, }; // test init value @@ -1448,7 +1497,7 @@ fn test_selective_metagraph() { let wrong_index: usize = 100; let metagraph_name = SelectiveMetagraph:: { - netuid: 0_u16.into(), + netuid: NetUid::ROOT.into(), name: Some(vec![1_u8].into_iter().map(Compact).collect()), ..Default::default() }; @@ -1463,7 +1512,7 @@ fn test_selective_metagraph() { let alph_low_index: usize = 50; let metagraph_alpha_low = SelectiveMetagraph:: { - netuid: 0_u16.into(), + netuid: NetUid::ROOT.into(), alpha_low: Some(0_u16.into()), ..Default::default() }; diff --git a/pallets/subtensor/src/rpc_info/neuron_info.rs b/pallets/subtensor/src/rpc_info/neuron_info.rs index 4838b376f9..337b89212d 100644 --- a/pallets/subtensor/src/rpc_info/neuron_info.rs +++ b/pallets/subtensor/src/rpc_info/neuron_info.rs @@ -2,14 +2,15 @@ use super::*; use frame_support::pallet_prelude::{Decode, Encode}; extern crate alloc; use codec::Compact; +use subtensor_runtime_common::NetUid; -#[freeze_struct("d6da7340b3350951")] +#[freeze_struct("3bddc0abfa5445a6")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct NeuronInfo { hotkey: AccountId, coldkey: AccountId, uid: Compact, - netuid: Compact, + netuid: Compact, active: bool, axon_info: AxonInfo, prometheus_info: PrometheusInfo, @@ -28,13 +29,13 @@ pub struct NeuronInfo { pruning_score: Compact, } -#[freeze_struct("3e9eed057f379b3b")] +#[freeze_struct("e2a6a95696a82c4f")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct NeuronInfoLite { hotkey: AccountId, coldkey: AccountId, uid: Compact, - netuid: Compact, + netuid: Compact, active: bool, axon_info: AxonInfo, prometheus_info: PrometheusInfo, @@ -53,7 +54,7 @@ pub struct NeuronInfoLite { } impl Pallet { - pub fn get_neurons(netuid: u16) -> Vec> { + pub fn get_neurons(netuid: NetUid) -> Vec> { if !Self::if_subnet_exist(netuid) { return Vec::new(); } @@ -71,7 +72,7 @@ impl Pallet { neurons } - fn get_neuron_subnet_exists(netuid: u16, uid: u16) -> Option> { + fn get_neuron_subnet_exists(netuid: NetUid, uid: u16) -> Option> { let hotkey = match Self::get_hotkey_for_net_and_uid(netuid, uid) { Ok(h) => h, Err(_) => return None, @@ -95,10 +96,10 @@ impl Pallet { let last_update = Self::get_last_update_for_uid(netuid, uid); let validator_permit = Self::get_validator_permit_for_uid(netuid, uid); - let weights = >::get(netuid, uid) - .iter() + let weights = Weights::::get(netuid, uid) + .into_iter() .filter_map(|(i, w)| { - if *w > 0 { + if w > 0 { Some((i.into(), w.into())) } else { None @@ -146,7 +147,7 @@ impl Pallet { Some(neuron) } - pub fn get_neuron(netuid: u16, uid: u16) -> Option> { + pub fn get_neuron(netuid: NetUid, uid: u16) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } @@ -155,7 +156,7 @@ impl Pallet { } fn get_neuron_lite_subnet_exists( - netuid: u16, + netuid: NetUid, uid: u16, ) -> Option> { let hotkey = match Self::get_hotkey_for_net_and_uid(netuid, uid) { @@ -210,7 +211,7 @@ impl Pallet { Some(neuron) } - pub fn get_neurons_lite(netuid: u16) -> Vec> { + pub fn get_neurons_lite(netuid: NetUid) -> Vec> { if !Self::if_subnet_exist(netuid) { return Vec::new(); } @@ -228,7 +229,7 @@ impl Pallet { neurons } - pub fn get_neuron_lite(netuid: u16, uid: u16) -> Option> { + pub fn get_neuron_lite(netuid: NetUid, uid: u16) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } diff --git a/pallets/subtensor/src/rpc_info/show_subnet.rs b/pallets/subtensor/src/rpc_info/show_subnet.rs index 9b66439fa2..aa5b2f4d36 100644 --- a/pallets/subtensor/src/rpc_info/show_subnet.rs +++ b/pallets/subtensor/src/rpc_info/show_subnet.rs @@ -4,11 +4,12 @@ use crate::epoch::math::*; use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; +use subtensor_runtime_common::NetUid; -#[freeze_struct("7954f39fd0755b28")] +#[freeze_struct("11f58860434dd863")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SubnetState { - netuid: Compact, + netuid: Compact, hotkeys: Vec, coldkeys: Vec, active: Vec, @@ -79,7 +80,7 @@ impl Pallet { /// /// * `Option>` - An optional `SubnetState` struct containing the collected data for the subnet. /// Returns `None` if the subnet does not exist. - pub fn get_subnet_state(netuid: u16) -> Option> { + pub fn get_subnet_state(netuid: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } diff --git a/pallets/subtensor/src/rpc_info/stake_info.rs b/pallets/subtensor/src/rpc_info/stake_info.rs index 8a3888061f..5fd9f6f7b8 100644 --- a/pallets/subtensor/src/rpc_info/stake_info.rs +++ b/pallets/subtensor/src/rpc_info/stake_info.rs @@ -1,15 +1,18 @@ -use super::*; -use frame_support::pallet_prelude::{Decode, Encode}; extern crate alloc; + use codec::Compact; -use substrate_fixed::types::U96F32; +use frame_support::pallet_prelude::{Decode, Encode}; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; + +use super::*; -#[freeze_struct("5cfb3c84c3af3116")] +#[freeze_struct("56f5e9f33e5ec9da")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct StakeInfo { hotkey: AccountId, coldkey: AccountId, - netuid: Compact, + netuid: Compact, stake: Compact, locked: Compact, emission: Compact, @@ -25,7 +28,7 @@ impl Pallet { if coldkeys.is_empty() { return Vec::new(); // No coldkeys to check } - let netuids: Vec = Self::get_all_subnet_netuids(); + let netuids = Self::get_all_subnet_netuids(); let mut stake_info: Vec<(T::AccountId, Vec>)> = Vec::new(); for coldkey_i in coldkeys.clone().iter() { // Get all hotkeys associated with this coldkey. @@ -90,7 +93,7 @@ impl Pallet { pub fn get_stake_info_for_hotkey_coldkey_netuid( hotkey_account: T::AccountId, coldkey_account: T::AccountId, - netuid: u16, + netuid: NetUid, ) -> Option> { let alpha: u64 = Self::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account, @@ -115,31 +118,13 @@ impl Pallet { } pub fn get_stake_fee( - origin: Option<(T::AccountId, u16)>, - origin_coldkey_account: T::AccountId, - destination: Option<(T::AccountId, u16)>, - destination_coldkey_account: T::AccountId, + origin: Option<(T::AccountId, NetUid)>, + _origin_coldkey_account: T::AccountId, + destination: Option<(T::AccountId, NetUid)>, + _destination_coldkey_account: T::AccountId, amount: u64, ) -> u64 { - let origin_: Option<(&T::AccountId, u16)> = - if let Some((ref origin_hotkey, origin_netuid)) = origin { - Some((origin_hotkey, origin_netuid)) - } else { - None - }; - - let destination_ = if let Some((ref destination_hotkey, destination_netuid)) = destination { - Some((destination_hotkey, destination_netuid)) - } else { - None - }; - - Self::calculate_staking_fee( - origin_, - &origin_coldkey_account, - destination_, - &destination_coldkey_account, - U96F32::saturating_from_num(amount), - ) + let netuid = destination.or(origin).map(|v| v.1).unwrap_or_default(); + T::SwapInterface::approx_fee_amount(netuid.into(), amount) } } diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index 6e9e722295..cab1f8800b 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -3,11 +3,13 @@ use frame_support::pallet_prelude::{Decode, Encode}; use frame_support::storage::IterableStorageMap; extern crate alloc; use codec::Compact; +use substrate_fixed::types::I32F32; +use subtensor_runtime_common::NetUid; -#[freeze_struct("1eee6f3911800c6b")] +#[freeze_struct("dd2293544ffd8f2e")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SubnetInfo { - netuid: Compact, + netuid: Compact, rho: Compact, kappa: Compact, difficulty: Compact, @@ -27,10 +29,10 @@ pub struct SubnetInfo { owner: AccountId, } -#[freeze_struct("a86ee623525247cc")] +#[freeze_struct("4e60a45245fc2ad1")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SubnetInfov2 { - netuid: Compact, + netuid: Compact, rho: Compact, kappa: Compact, difficulty: Compact, @@ -48,7 +50,7 @@ pub struct SubnetInfov2 { emission_value: Compact, burn: Compact, owner: AccountId, - identity: Option, + identity: Option, } #[freeze_struct("7b506df55bd44646")] @@ -83,8 +85,46 @@ pub struct SubnetHyperparams { liquid_alpha_enabled: bool, } +#[freeze_struct("a13c536303dec16f")] +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] +pub struct SubnetHyperparamsV2 { + rho: Compact, + kappa: Compact, + immunity_period: Compact, + min_allowed_weights: Compact, + max_weights_limit: Compact, + tempo: Compact, + min_difficulty: Compact, + max_difficulty: Compact, + weights_version: Compact, + weights_rate_limit: Compact, + adjustment_interval: Compact, + activity_cutoff: Compact, + pub registration_allowed: bool, + target_regs_per_interval: Compact, + min_burn: Compact, + max_burn: Compact, + bonds_moving_avg: Compact, + max_regs_per_block: Compact, + serving_rate_limit: Compact, + max_validators: Compact, + adjustment_alpha: Compact, + difficulty: Compact, + commit_reveal_period: Compact, + commit_reveal_weights_enabled: bool, + alpha_high: Compact, + alpha_low: Compact, + liquid_alpha_enabled: bool, + alpha_sigmoid_steepness: I32F32, + yuma_version: Compact, + subnet_is_active: bool, + transfers_enabled: bool, + bonds_reset_enabled: bool, + user_liquidity_enabled: bool, +} + impl Pallet { - pub fn get_subnet_info(netuid: u16) -> Option> { + pub fn get_subnet_info(netuid: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } @@ -132,28 +172,28 @@ impl Pallet { } pub fn get_subnets_info() -> Vec>> { - let mut subnet_netuids = Vec::::new(); + let mut subnet_netuids = Vec::::new(); let mut max_netuid: u16 = 0; - for (netuid, added) in as IterableStorageMap>::iter() { + for (netuid, added) in as IterableStorageMap>::iter() { if added { subnet_netuids.push(netuid); - if netuid > max_netuid { - max_netuid = netuid; + if u16::from(netuid) > max_netuid { + max_netuid = u16::from(netuid); } } } let mut subnets_info = Vec::>>::new(); for netuid_ in 0..=max_netuid { - if subnet_netuids.contains(&netuid_) { - subnets_info.push(Self::get_subnet_info(netuid_)); + if subnet_netuids.contains(&netuid_.into()) { + subnets_info.push(Self::get_subnet_info(netuid_.into())); } } subnets_info } - pub fn get_subnet_info_v2(netuid: u16) -> Option> { + pub fn get_subnet_info_v2(netuid: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { return None; } @@ -172,7 +212,7 @@ impl Pallet { let tempo = Self::get_tempo(netuid); let network_modality = >::get(netuid); let burn: Compact = Self::get_burn_as_u64(netuid).into(); - let identity: Option = SubnetIdentitiesV2::::get(netuid); + let identity: Option = SubnetIdentitiesV3::::get(netuid); // DEPRECATED let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new(); @@ -204,28 +244,28 @@ impl Pallet { } pub fn get_subnets_info_v2() -> Vec>> { - let mut subnet_netuids = Vec::::new(); + let mut subnet_netuids = Vec::::new(); let mut max_netuid: u16 = 0; - for (netuid, added) in as IterableStorageMap>::iter() { + for (netuid, added) in as IterableStorageMap>::iter() { if added { subnet_netuids.push(netuid); - if netuid > max_netuid { - max_netuid = netuid; + if u16::from(netuid) > max_netuid { + max_netuid = u16::from(netuid); } } } let mut subnets_info = Vec::>>::new(); for netuid_ in 0..=max_netuid { - if subnet_netuids.contains(&netuid_) { - subnets_info.push(Self::get_subnet_info_v2(netuid_)); + if subnet_netuids.contains(&netuid_.into()) { + subnets_info.push(Self::get_subnet_info_v2(netuid_.into())); } } subnets_info } - pub fn get_subnet_hyperparams(netuid: u16) -> Option { + pub fn get_subnet_hyperparams(netuid: NetUid) -> Option { if !Self::if_subnet_exist(netuid) { return None; } @@ -287,4 +327,82 @@ impl Pallet { liquid_alpha_enabled, }) } + + pub fn get_subnet_hyperparams_v2(netuid: NetUid) -> Option { + if !Self::if_subnet_exist(netuid) { + return None; + } + + let rho = Self::get_rho(netuid); + let kappa = Self::get_kappa(netuid); + let immunity_period = Self::get_immunity_period(netuid); + let min_allowed_weights = Self::get_min_allowed_weights(netuid); + let max_weights_limit = Self::get_max_weight_limit(netuid); + let tempo = Self::get_tempo(netuid); + let min_difficulty = Self::get_min_difficulty(netuid); + let max_difficulty = Self::get_max_difficulty(netuid); + let weights_version = Self::get_weights_version_key(netuid); + let weights_rate_limit = Self::get_weights_set_rate_limit(netuid); + let adjustment_interval = Self::get_adjustment_interval(netuid); + let activity_cutoff = Self::get_activity_cutoff(netuid); + let registration_allowed = Self::get_network_registration_allowed(netuid); + let target_regs_per_interval = Self::get_target_registrations_per_interval(netuid); + let min_burn = Self::get_min_burn_as_u64(netuid); + let max_burn = Self::get_max_burn_as_u64(netuid); + let bonds_moving_avg = Self::get_bonds_moving_average(netuid); + let max_regs_per_block = Self::get_max_registrations_per_block(netuid); + let serving_rate_limit = Self::get_serving_rate_limit(netuid); + let max_validators = Self::get_max_allowed_validators(netuid); + let adjustment_alpha = Self::get_adjustment_alpha(netuid); + let difficulty = Self::get_difficulty_as_u64(netuid); + let commit_reveal_period = Self::get_reveal_period(netuid); + let commit_reveal_weights_enabled = Self::get_commit_reveal_weights_enabled(netuid); + let liquid_alpha_enabled = Self::get_liquid_alpha_enabled(netuid); + let (alpha_low, alpha_high): (u16, u16) = Self::get_alpha_values(netuid); + let alpha_sigmoid_steepness = Self::get_alpha_sigmoid_steepness(netuid); + let yuma_version: u16 = match Self::get_yuma3_enabled(netuid) { + true => 3u16, + false => 2u16, + }; + let subnet_token_enabled = Self::get_subtoken_enabled(netuid); + let transfers_enabled = Self::get_transfer_toggle(netuid); + let bonds_reset = Self::get_bonds_reset(netuid); + let user_liquidity_enabled: bool = Self::is_user_liquidity_enabled(netuid); + + Some(SubnetHyperparamsV2 { + rho: rho.into(), + kappa: kappa.into(), + immunity_period: immunity_period.into(), + min_allowed_weights: min_allowed_weights.into(), + max_weights_limit: max_weights_limit.into(), + tempo: tempo.into(), + min_difficulty: min_difficulty.into(), + max_difficulty: max_difficulty.into(), + weights_version: weights_version.into(), + weights_rate_limit: weights_rate_limit.into(), + adjustment_interval: adjustment_interval.into(), + activity_cutoff: activity_cutoff.into(), + registration_allowed, + target_regs_per_interval: target_regs_per_interval.into(), + min_burn: min_burn.into(), + max_burn: max_burn.into(), + bonds_moving_avg: bonds_moving_avg.into(), + max_regs_per_block: max_regs_per_block.into(), + serving_rate_limit: serving_rate_limit.into(), + max_validators: max_validators.into(), + adjustment_alpha: adjustment_alpha.into(), + difficulty: difficulty.into(), + commit_reveal_period: commit_reveal_period.into(), + commit_reveal_weights_enabled, + alpha_high: alpha_high.into(), + alpha_low: alpha_low.into(), + liquid_alpha_enabled, + alpha_sigmoid_steepness, + yuma_version: yuma_version.into(), + subnet_is_active: subnet_token_enabled, + transfers_enabled, + bonds_reset_enabled: bonds_reset, + user_liquidity_enabled, + }) + } } diff --git a/pallets/subtensor/src/staking/add_stake.rs b/pallets/subtensor/src/staking/add_stake.rs index 8886806cd9..77b4a8fa48 100644 --- a/pallets/subtensor/src/staking/add_stake.rs +++ b/pallets/subtensor/src/staking/add_stake.rs @@ -1,5 +1,8 @@ -use super::*; use substrate_fixed::types::I96F32; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler}; + +use super::*; impl Pallet { /// ---- The implementation for the extrinsic add_stake: Adds stake to a hotkey account. @@ -37,7 +40,7 @@ impl Pallet { pub fn do_add_stake( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, stake_to_be_added: u64, ) -> dispatch::DispatchResult { // 1. We check that the transaction is signed by the caller and retrieve the T::AccountId coldkey information. @@ -68,167 +71,18 @@ impl Pallet { // 4. Swap the stake into alpha on the subnet and increase counters. // Emit the staking event. - let fee = DefaultStakingFee::::get(); Self::stake_into_subnet( &hotkey, &coldkey, netuid, tao_staked.saturating_to_num::(), - fee, - ); + T::SwapInterface::max_price(), + )?; // Ok and return. Ok(()) } - /// ---- The implementation for the extrinsic add_stake_aggregate: Adds stake to a hotkey account. - /// The operation will be delayed until the end of the block. - /// # Args: - /// * 'origin': (RuntimeOrigin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - /// - /// * 'netuid' (u16): - /// - Subnetwork UID - /// - /// * 'stake_to_be_added' (u64): - /// - The amount of stake to be added to the hotkey staking account. - /// - /// # Event: - /// * StakeAdded; - /// - On the successfully adding stake to a global account. - /// - /// # Raises: - /// * 'NotEnoughBalanceToStake': - /// - Not enough balance on the coldkey to add onto the global account. - /// - /// * 'NonAssociatedColdKey': - /// - The calling coldkey is not associated with this hotkey. - /// - /// * 'BalanceWithdrawalError': - /// - Errors stemming from transaction pallet. - /// - /// * 'TxRateLimitExceeded': - /// - Thrown if key has hit transaction rate limit - /// - pub fn do_add_stake_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - netuid: u16, - stake_to_be_added: u64, - ) -> dispatch::DispatchResult { - // We check that the transaction is signed by the caller and retrieve the T::AccountId coldkey information. - let coldkey = ensure_signed(origin)?; - - // Consider the weight from on_finalize - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_add_stake( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - netuid, - stake_to_be_added, - )?; - } - - // Save the staking job for the on_finalize - let stake_job = StakeJob::AddStake { - hotkey, - coldkey, - netuid, - stake_to_be_added, - }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - Ok(()) - } - - /// ---- The implementation for the extrinsic add_stake_limit_aggregate: Adds stake to a hotkey - /// account on a subnet with price limit. The operation will be delayed until the end of the - /// block. - /// - /// # Args: - /// * 'origin': (RuntimeOrigin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - /// - /// * 'netuid' (u16): - /// - Subnetwork UID - /// - /// * 'stake_to_be_added' (u64): - /// - The amount of stake to be added to the hotkey staking account. - /// - /// * 'limit_price' (u64): - /// - The limit price expressed in units of RAO per one Alpha. - /// - /// * 'allow_partial' (bool): - /// - Allows partial execution of the amount. If set to false, this becomes - /// fill or kill type or order. - /// - /// # Event: - /// * StakeAdded; - /// - On the successfully adding stake to a global account. - /// - /// # Raises: - /// * 'NotEnoughBalanceToStake': - /// - Not enough balance on the coldkey to add onto the global account. - /// - /// * 'NonAssociatedColdKey': - /// - The calling coldkey is not associated with this hotkey. - /// - /// * 'BalanceWithdrawalError': - /// - Errors stemming from transaction pallet. - /// - /// * 'TxRateLimitExceeded': - /// - Thrown if key has hit transaction rate limit - /// - pub fn do_add_stake_limit_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - netuid: u16, - stake_to_be_added: u64, - limit_price: u64, - allow_partial: bool, - ) -> dispatch::DispatchResult { - let coldkey = ensure_signed(origin)?; - - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_add_stake_limit( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - netuid, - stake_to_be_added, - limit_price, - allow_partial, - )?; - } - - let stake_job = StakeJob::AddStakeLimit { - hotkey, - coldkey, - netuid, - stake_to_be_added, - limit_price, - allow_partial, - }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - Ok(()) - } - /// ---- The implementation for the extrinsic add_stake_limit: Adds stake to a hotkey /// account on a subnet with price limit. /// @@ -272,7 +126,7 @@ impl Pallet { pub fn do_add_stake_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, stake_to_be_added: u64, limit_price: u64, allow_partial: bool, @@ -310,30 +164,22 @@ impl Pallet { } // 5. Ensure the remove operation from the coldkey is a success. - let tao_staked: I96F32 = - Self::remove_balance_from_coldkey_account(&coldkey, possible_stake)?.into(); + let tao_staked: u64 = Self::remove_balance_from_coldkey_account(&coldkey, possible_stake)?; // 6. Swap the stake into alpha on the subnet and increase counters. // Emit the staking event. - let fee = DefaultStakingFee::::get(); - Self::stake_into_subnet( - &hotkey, - &coldkey, - netuid, - tao_staked.saturating_to_num::(), - fee, - ); + Self::stake_into_subnet(&hotkey, &coldkey, netuid, tao_staked, limit_price)?; // Ok and return. Ok(()) } // Returns the maximum amount of RAO that can be executed with price limit - pub fn get_max_amount_add(netuid: u16, limit_price: u64) -> Result> { + pub fn get_max_amount_add(netuid: NetUid, limit_price: u64) -> Result> { // Corner case: root and stao // There's no slippage for root or stable subnets, so if limit price is 1e9 rao or // higher, then max_amount equals u64::MAX, otherwise it is 0. - if (netuid == Self::get_root_netuid()) || (SubnetMechanism::::get(netuid)) == 0 { + if netuid.is_root() || SubnetMechanism::::get(netuid) == 0 { if limit_price >= 1_000_000_000 { return Ok(u64::MAX); } else { @@ -341,49 +187,16 @@ impl Pallet { } } - // Corner case: SubnetAlphaIn is zero. Staking can't happen, so max amount is zero. - let alpha_in = SubnetAlphaIn::::get(netuid); - if alpha_in == 0 { - return Err(Error::ZeroMaxStakeAmount); - } - let alpha_in_u128 = alpha_in as u128; - - // Corner case: SubnetTAO is zero. Staking can't happen, so max amount is zero. - let tao_reserve = SubnetTAO::::get(netuid); - if tao_reserve == 0 { - return Err(Error::ZeroMaxStakeAmount); - } - let tao_reserve_u128 = tao_reserve as u128; - - // Corner case: limit_price < current_price (price cannot decrease with staking) - let tao = 1_000_000_000_u128; - let limit_price_u128 = limit_price as u128; - if (limit_price_u128 - < Self::get_alpha_price(netuid) - .saturating_to_num::() - .saturating_mul(tao)) - || (limit_price == 0u64) - { - return Err(Error::ZeroMaxStakeAmount); - } - - // Main case: return limit_price * SubnetAlphaIn - SubnetTAO - // Non overflowing calculation: limit_price * alpha_in <= u64::MAX * u64::MAX <= u128::MAX - // May overflow result, then it will be capped at u64::MAX, which is OK because that matches balance u64 size. - let result = limit_price_u128 - .saturating_mul(alpha_in_u128) - .checked_div(tao) - .unwrap_or(0) - .saturating_sub(tao_reserve_u128); - - if result == 0 { - return Err(Error::ZeroMaxStakeAmount); - } + // Use reverting swap to estimate max limit amount + let result = + T::SwapInterface::swap(netuid.into(), OrderType::Buy, u64::MAX, limit_price, true) + .map(|r| r.amount_paid_in.saturating_add(r.fee_paid)) + .map_err(|_| Error::ZeroMaxStakeAmount)?; - if result < u64::MAX as u128 { - Ok(result as u64) + if result != 0 { + Ok(result) } else { - Ok(u64::MAX) + Err(Error::ZeroMaxStakeAmount) } } } diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 9ee04f36a8..286877b1c9 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -1,7 +1,3 @@ -use super::*; -use safe_math::*; -use substrate_fixed::types::U96F32; - use frame_support::traits::{ Imbalance, tokens::{ @@ -9,6 +5,12 @@ use frame_support::traits::{ fungible::{Balanced as _, Inspect as _}, }, }; +use safe_math::*; +use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler}; + +use super::*; impl Pallet { // Returns true if the passed hotkey allow delegative staking. @@ -41,19 +43,21 @@ impl Pallet { TotalStake::::put(Self::get_total_stake().saturating_sub(decrement)); } - // Returns the total amount of stake under a hotkey (delegative or otherwise) - // + /// Returns the total amount of stake (in TAO) under a hotkey (delegative or otherwise) pub fn get_total_stake_for_hotkey(hotkey: &T::AccountId) -> u64 { Self::get_all_subnet_netuids() - .iter() + .into_iter() .map(|netuid| { - let alpha: U96F32 = U96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(hotkey, *netuid), + let alpha = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet( + hotkey, netuid, + )); + let alpha_price = U96F32::saturating_from_num( + T::SwapInterface::current_alpha_price(netuid.into()), ); - let tao_price: U96F32 = Self::get_alpha_price(*netuid); - alpha.saturating_mul(tao_price).saturating_to_num::() + alpha.saturating_mul(alpha_price) }) - .sum() + .sum::() + .saturating_to_num::() } // Returns the total amount of stake under a coldkey @@ -63,18 +67,23 @@ impl Pallet { hotkeys .iter() .map(|hotkey| { - let mut total_stake: u64 = 0; - for (netuid, _) in Alpha::::iter_prefix((hotkey, coldkey)) { - let alpha_stake = - Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); - let tao_price: U96F32 = Self::get_alpha_price(netuid); - total_stake = total_stake.saturating_add( - U96F32::saturating_from_num(alpha_stake) - .saturating_mul(tao_price) - .saturating_to_num::(), - ); - } - total_stake + Alpha::::iter_prefix((hotkey, coldkey)) + .map(|(netuid, _)| { + let alpha_stake = Self::get_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, + ); + T::SwapInterface::sim_swap(netuid.into(), OrderType::Sell, alpha_stake) + .map(|r| { + let fee: u64 = U96F32::saturating_from_num(r.fee_paid) + .saturating_mul(T::SwapInterface::current_alpha_price( + netuid.into(), + )) + .saturating_to_num(); + r.amount_paid_out.saturating_add(fee) + }) + .unwrap_or_default() + }) + .sum::() }) .sum::() } @@ -165,7 +174,7 @@ impl Pallet { pub fn clear_small_nomination_if_required( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, ) { // Verify if the account is a nominator account by checking ownership of the hotkey by the coldkey. if !Self::coldkey_owns_hotkey(coldkey, hotkey) { @@ -178,9 +187,25 @@ impl Pallet { // Remove the stake from the nominator account. (this is a more forceful unstake operation which ) // Actually deletes the staking account. // Do not apply any fees - let cleared_stake = Self::unstake_from_subnet(hotkey, coldkey, netuid, stake, 0); - // Add the stake to the coldkey account. - Self::add_balance_to_coldkey_account(coldkey, cleared_stake); + let maybe_cleared_stake = Self::unstake_from_subnet( + hotkey, + coldkey, + netuid, + stake, + T::SwapInterface::min_price(), + ); + + if let Ok(cleared_stake) = maybe_cleared_stake { + // Add the stake to the coldkey account. + Self::add_balance_to_coldkey_account(coldkey, cleared_stake); + } else { + // Just clear small alpha + let alpha = + Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); + Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, alpha, + ); + } } } } @@ -277,4 +302,8 @@ impl Pallet { Ok(credit) } + + pub fn is_user_liquidity_enabled(netuid: NetUid) -> bool { + T::SwapInterface::is_user_liquidity_enabled(netuid) + } } diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index ef576f3607..ebacd90194 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -1,7 +1,9 @@ use super::*; use safe_math::*; use sp_core::Get; -use substrate_fixed::types::{U64F64, U96F32}; +use substrate_fixed::types::U64F64; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; impl Pallet { /// Moves stake from one hotkey to another across subnets. @@ -29,8 +31,8 @@ impl Pallet { origin: T::RuntimeOrigin, origin_hotkey: T::AccountId, destination_hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> dispatch::DispatchResult { // Check that the origin is signed by the origin_hotkey. @@ -72,6 +74,28 @@ impl Pallet { Ok(()) } + /// Toggles the atomic alpha transfers for a specific subnet. + /// + /// # Arguments + /// * `netuid` - The network ID (subnet) for which the transfer functionality is being toggled. + /// * `toggle` - A boolean value indicating whether to enable (true) or disable (false) transfers. + /// + /// # Returns + /// * `DispatchResult` - Indicates success or failure of the operation. + /// + /// # Events + /// Emits a `TransferToggle` event upon successful completion. + pub fn toggle_transfer(netuid: NetUid, toggle: bool) -> dispatch::DispatchResult { + TransferToggle::::insert(netuid, toggle); + log::debug!( + "TransferToggle( netuid: {:?}, toggle: {:?} ) ", + netuid, + toggle + ); + Self::deposit_event(Event::TransferToggle(netuid, toggle)); + Ok(()) + } + /// Transfers stake from one coldkey to another, optionally moving from one subnet to another, /// while keeping the same hotkey. /// @@ -97,22 +121,12 @@ impl Pallet { /// /// # Events /// Emits a `StakeTransferred` event upon successful completion of the transfer. - pub fn toggle_transfer(netuid: u16, toggle: bool) -> dispatch::DispatchResult { - TransferToggle::::insert(netuid, toggle); - log::debug!( - "TransferToggle( netuid: {:?}, toggle: {:?} ) ", - netuid, - toggle - ); - Self::deposit_event(Event::TransferToggle(netuid, toggle)); - Ok(()) - } pub fn do_transfer_stake( origin: T::RuntimeOrigin, destination_coldkey: T::AccountId, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> dispatch::DispatchResult { // Ensure the extrinsic is signed by the origin_coldkey. @@ -181,8 +195,8 @@ impl Pallet { pub fn do_swap_stake( origin: T::RuntimeOrigin, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, ) -> dispatch::DispatchResult { // Ensure the extrinsic is signed by the coldkey. @@ -251,8 +265,8 @@ impl Pallet { pub fn do_swap_stake_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, limit_price: u64, allow_partial: bool, @@ -302,13 +316,13 @@ impl Pallet { destination_coldkey: &T::AccountId, origin_hotkey: &T::AccountId, destination_hotkey: &T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, maybe_limit_price: Option, maybe_allow_partial: Option, check_transfer_toggle: bool, - ) -> Result> { + ) -> Result { // Calculate the maximum amount that can be executed let max_amount = if let Some(limit_price) = maybe_limit_price { Self::get_max_amount_move(origin_netuid, destination_netuid, limit_price)? @@ -337,28 +351,18 @@ impl Pallet { max_amount }; - // Unstake from the origin subnet, returning TAO (or a 1:1 equivalent). - let fee = Self::calculate_staking_fee( - Some((origin_hotkey, origin_netuid)), - origin_coldkey, - Some((destination_hotkey, destination_netuid)), - destination_coldkey, - U96F32::saturating_from_num(alpha_amount), - ) - .safe_div(2); - let tao_unstaked = Self::unstake_from_subnet( origin_hotkey, origin_coldkey, origin_netuid, move_amount, - fee, - ); + T::SwapInterface::min_price(), + )?; // Stake the unstaked amount into the destination. // Because of the fee, the tao_unstaked may be too low if initial stake is low. In that case, // do not restake. - if tao_unstaked >= DefaultMinStake::::get().saturating_add(fee) { + if tao_unstaked >= DefaultMinStake::::get() { // If the coldkey is not the owner, make the hotkey a delegate. if Self::get_owning_coldkey_for_hotkey(destination_hotkey) != *destination_coldkey { Self::maybe_become_delegate(destination_hotkey); @@ -369,11 +373,11 @@ impl Pallet { destination_coldkey, destination_netuid, tao_unstaked, - fee, - ); + T::SwapInterface::max_price(), + )?; } - Ok(tao_unstaked.saturating_sub(fee)) + Ok(tao_unstaked) } /// Returns the maximum amount of origin netuid Alpha that can be executed before we cross @@ -397,9 +401,11 @@ impl Pallet { /// /// In the corner case when SubnetTAO(2) == SubnetTAO(1), no slippage is going to occur. /// + /// TODO: This formula only works for a single swap step, so it is not 100% correct for swap v3. We need an updated one. + /// pub fn get_max_amount_move( - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, limit_price: u64, ) -> Result> { let tao: U64F64 = U64F64::saturating_from_num(1_000_000_000); @@ -407,10 +413,8 @@ impl Pallet { // Corner case: both subnet IDs are root or stao // There's no slippage for root or stable subnets, so slippage is always 0. // The price always stays at 1.0, return 0 if price is expected to raise. - if ((origin_netuid == Self::get_root_netuid()) - || (SubnetMechanism::::get(origin_netuid)) == 0) - && ((destination_netuid == Self::get_root_netuid()) - || (SubnetMechanism::::get(destination_netuid)) == 0) + if (origin_netuid.is_root() || SubnetMechanism::::get(origin_netuid) == 0) + && (destination_netuid.is_root() || SubnetMechanism::::get(destination_netuid) == 0) { if limit_price > tao.saturating_to_num::() { return Err(Error::ZeroMaxStakeAmount); @@ -421,9 +425,8 @@ impl Pallet { // Corner case: Origin is root or stable, destination is dynamic // Same as adding stake with limit price - if ((origin_netuid == Self::get_root_netuid()) - || (SubnetMechanism::::get(origin_netuid)) == 0) - && ((SubnetMechanism::::get(destination_netuid)) == 1) + if (origin_netuid.is_root() || SubnetMechanism::::get(origin_netuid) == 0) + && (SubnetMechanism::::get(destination_netuid) == 1) { if limit_price == 0 { return Ok(u64::MAX); @@ -439,16 +442,17 @@ impl Pallet { // Corner case: Origin is dynamic, destination is root or stable // Same as removing stake with limit price - if ((destination_netuid == Self::get_root_netuid()) - || (SubnetMechanism::::get(destination_netuid)) == 0) - && ((SubnetMechanism::::get(origin_netuid)) == 1) + if (destination_netuid.is_root() || SubnetMechanism::::get(destination_netuid) == 0) + && (SubnetMechanism::::get(origin_netuid) == 1) { return Self::get_max_amount_remove(origin_netuid, limit_price); } // Corner case: SubnetTAO for any of two subnets is zero - let subnet_tao_1 = SubnetTAO::::get(origin_netuid); - let subnet_tao_2 = SubnetTAO::::get(destination_netuid); + let subnet_tao_1 = SubnetTAO::::get(origin_netuid) + .saturating_add(SubnetTaoProvided::::get(origin_netuid)); + let subnet_tao_2 = SubnetTAO::::get(destination_netuid) + .saturating_add(SubnetTaoProvided::::get(destination_netuid)); if (subnet_tao_1 == 0) || (subnet_tao_2 == 0) { return Err(Error::ZeroMaxStakeAmount); } @@ -456,8 +460,10 @@ impl Pallet { let subnet_tao_2_float: U64F64 = U64F64::saturating_from_num(subnet_tao_2); // Corner case: SubnetAlphaIn for any of two subnets is zero - let alpha_in_1 = SubnetAlphaIn::::get(origin_netuid); - let alpha_in_2 = SubnetAlphaIn::::get(destination_netuid); + let alpha_in_1 = SubnetAlphaIn::::get(origin_netuid) + .saturating_add(SubnetAlphaInProvided::::get(origin_netuid)); + let alpha_in_2 = SubnetAlphaIn::::get(destination_netuid) + .saturating_add(SubnetAlphaInProvided::::get(destination_netuid)); if (alpha_in_1 == 0) || (alpha_in_2 == 0) { return Err(Error::ZeroMaxStakeAmount); } @@ -471,8 +477,9 @@ impl Pallet { let limit_price_float: U64F64 = U64F64::saturating_from_num(limit_price) .checked_div(U64F64::saturating_from_num(1_000_000_000)) .unwrap_or(U64F64::saturating_from_num(0)); - let current_price = Self::get_alpha_price(origin_netuid) - .safe_div(Self::get_alpha_price(destination_netuid)); + let current_price = T::SwapInterface::current_alpha_price(origin_netuid.into()).safe_div( + T::SwapInterface::current_alpha_price(destination_netuid.into()), + ); if limit_price_float > current_price { return Err(Error::ZeroMaxStakeAmount); } diff --git a/pallets/subtensor/src/staking/recycle_alpha.rs b/pallets/subtensor/src/staking/recycle_alpha.rs index ef3cea2b29..5bb9f2da1c 100644 --- a/pallets/subtensor/src/staking/recycle_alpha.rs +++ b/pallets/subtensor/src/staking/recycle_alpha.rs @@ -1,5 +1,6 @@ use super::*; use crate::{Error, system::ensure_signed}; +use subtensor_runtime_common::NetUid; impl Pallet { /// Recycles alpha from a cold/hot key pair, reducing AlphaOut on a subnet @@ -18,7 +19,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: T::AccountId, amount: u64, - netuid: u16, + netuid: NetUid, ) -> DispatchResult { let coldkey: T::AccountId = ensure_signed(origin)?; @@ -28,7 +29,7 @@ impl Pallet { ); ensure!( - netuid != Self::get_root_netuid(), + !netuid.is_root(), Error::::CannotBurnOrRecycleOnRootSubnet ); @@ -87,7 +88,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: T::AccountId, amount: u64, - netuid: u16, + netuid: NetUid, ) -> DispatchResult { let coldkey = ensure_signed(origin)?; @@ -97,7 +98,7 @@ impl Pallet { ); ensure!( - netuid != Self::get_root_netuid(), + !netuid.is_root(), Error::::CannotBurnOrRecycleOnRootSubnet ); diff --git a/pallets/subtensor/src/staking/remove_stake.rs b/pallets/subtensor/src/staking/remove_stake.rs index 378ea8001b..5f54a7449b 100644 --- a/pallets/subtensor/src/staking/remove_stake.rs +++ b/pallets/subtensor/src/staking/remove_stake.rs @@ -1,5 +1,7 @@ +use subtensor_swap_interface::{OrderType, SwapHandler}; + use super::*; -use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; impl Pallet { /// ---- The implementation for the extrinsic remove_stake: Removes stake from a hotkey account and adds it onto a coldkey. @@ -37,7 +39,7 @@ impl Pallet { pub fn do_remove_stake( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, alpha_unstaked: u64, ) -> dispatch::DispatchResult { // 1. We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information. @@ -63,15 +65,13 @@ impl Pallet { )?; // 3. Swap the alpba to tao and update counters for this subnet. - let fee = Self::calculate_staking_fee( - Some((&hotkey, netuid)), - &coldkey, - None, + let tao_unstaked: u64 = Self::unstake_from_subnet( + &hotkey, &coldkey, - U96F32::saturating_from_num(alpha_unstaked), - ); - let tao_unstaked: u64 = - Self::unstake_from_subnet(&hotkey, &coldkey, netuid, alpha_unstaked, fee); + netuid, + alpha_unstaked, + T::SwapInterface::min_price(), + )?; // 4. We add the balance to the coldkey. If the above fails we will not credit this coldkey. Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked); @@ -90,74 +90,6 @@ impl Pallet { Ok(()) } - /// ---- The implementation for the extrinsic remove_stake_aggregate: Removes stake from a hotkey account and adds it onto a coldkey. - /// The operation will be delayed until the end of the block. - /// # Args: - /// * 'origin': (RuntimeOrigin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - /// - /// * 'netuid' (u16): - /// - Subnetwork UID - /// - /// * 'stake_to_be_added' (u64): - /// - The amount of stake to be added to the hotkey staking account. - /// - /// # Event: - /// * StakeRemoved; - /// - On the successfully removing stake from the hotkey account. - /// - /// # Raises: - /// * 'NotRegistered': - /// - Thrown if the account we are attempting to unstake from is non existent. - /// - /// * 'NonAssociatedColdKey': - /// - Thrown if the coldkey does not own the hotkey we are unstaking from. - /// - /// * 'NotEnoughStakeToWithdraw': - /// - Thrown if there is not enough stake on the hotkey to withdwraw this amount. - /// - /// * 'TxRateLimitExceeded': - /// - Thrown if key has hit transaction rate limit - /// - pub fn do_remove_stake_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - netuid: u16, - alpha_unstaked: u64, - ) -> dispatch::DispatchResult { - // We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information. - let coldkey = ensure_signed(origin)?; - - // Consider the weight from on_finalize - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_remove_stake( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - netuid, - alpha_unstaked, - )?; - } - - // Save the staking job for the on_finalize - let stake_job = StakeJob::RemoveStake { - hotkey, - coldkey, - netuid, - alpha_unstaked, - }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - Ok(()) - } - /// ---- The implementation for the extrinsic unstake_all: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. /// /// # Args: @@ -199,7 +131,7 @@ impl Pallet { ); // 3. Get all netuids. - let netuids: Vec = Self::get_all_subnet_netuids(); + let netuids = Self::get_all_subnet_netuids(); log::debug!("All subnet netuids: {:?}", netuids); // 4. Iterate through all subnets and remove stake. @@ -225,18 +157,15 @@ impl Pallet { continue; } - let fee = Self::calculate_staking_fee( - Some((&hotkey, netuid)), - &coldkey, - None, - &coldkey, - U96F32::saturating_from_num(alpha_unstaked), - ); - if alpha_unstaked > 0 { // Swap the alpha to tao and update counters for this subnet. - let tao_unstaked: u64 = - Self::unstake_from_subnet(&hotkey, &coldkey, netuid, alpha_unstaked, fee); + let tao_unstaked: u64 = Self::unstake_from_subnet( + &hotkey, + &coldkey, + netuid, + alpha_unstaked, + T::SwapInterface::min_price(), + )?; // Add the balance to the coldkey. If the above fails we will not credit this coldkey. Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked); @@ -250,41 +179,6 @@ impl Pallet { Ok(()) } - /// ---- The implementation for the extrinsic unstake_all_aggregate: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. - /// - /// # Args: - /// * 'origin': (RuntimeOrigin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - pub fn do_unstake_all_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - ) -> dispatch::DispatchResult { - // We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information. - let coldkey = ensure_signed(origin)?; - - // Consider the weight from on_finalize - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_unstake_all( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - )?; - } - - // Save the unstake_all job for the on_finalize - let stake_job = StakeJob::UnstakeAll { hotkey, coldkey }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - Ok(()) - } - /// ---- The implementation for the extrinsic unstake_all: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. /// /// # Args: @@ -326,7 +220,7 @@ impl Pallet { ); // 3. Get all netuids. - let netuids: Vec = Self::get_all_subnet_netuids(); + let netuids = Self::get_all_subnet_netuids(); log::debug!("All subnet netuids: {:?}", netuids); // 4. Iterate through all subnets and remove stake. @@ -336,7 +230,7 @@ impl Pallet { continue; } // If not Root network. - if netuid != Self::get_root_netuid() { + if !netuid.is_root() { // Ensure that the hotkey has enough stake to withdraw. let alpha_unstaked = Self::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); @@ -355,18 +249,15 @@ impl Pallet { continue; } - let fee = Self::calculate_staking_fee( - Some((&hotkey, netuid)), - &coldkey, - None, - &coldkey, - U96F32::saturating_from_num(alpha_unstaked), - ); - if alpha_unstaked > 0 { // Swap the alpha to tao and update counters for this subnet. - let tao_unstaked = - Self::unstake_from_subnet(&hotkey, &coldkey, netuid, alpha_unstaked, fee); + let tao_unstaked = Self::unstake_from_subnet( + &hotkey, + &coldkey, + netuid, + alpha_unstaked, + T::SwapInterface::min_price(), + )?; // Increment total total_tao_unstaked = total_tao_unstaked.saturating_add(tao_unstaked); @@ -381,50 +272,15 @@ impl Pallet { Self::stake_into_subnet( &hotkey, &coldkey, - Self::get_root_netuid(), + NetUid::ROOT, total_tao_unstaked, - 0, // no fee for restaking - ); + T::SwapInterface::max_price(), + )?; // 5. Done and ok. Ok(()) } - /// ---- The implementation for the extrinsic unstake_all_alpha_aggregate: Removes all stake from a hotkey account across all subnets and adds it onto a coldkey. - /// - /// # Args: - /// * 'origin': (RuntimeOrigin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - pub fn do_unstake_all_alpha_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - ) -> dispatch::DispatchResult { - // We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information. - let coldkey = ensure_signed(origin)?; - - // Consider the weight from on_finalize - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_unstake_all_alpha( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - )?; - } - - // Save the unstake_all_alpha job for the on_finalize - let stake_job = StakeJob::UnstakeAllAlpha { hotkey, coldkey }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - Ok(()) - } - /// ---- The implementation for the extrinsic remove_stake_limit: Removes stake from /// a hotkey on a subnet with a price limit. /// @@ -469,7 +325,7 @@ impl Pallet { pub fn do_remove_stake_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, alpha_unstaked: u64, limit_price: u64, allow_partial: bool, @@ -502,15 +358,8 @@ impl Pallet { )?; // 4. Swap the alpha to tao and update counters for this subnet. - let fee = Self::calculate_staking_fee( - Some((&hotkey, netuid)), - &coldkey, - None, - &coldkey, - U96F32::saturating_from_num(alpha_unstaked), - ); let tao_unstaked = - Self::unstake_from_subnet(&hotkey, &coldkey, netuid, possible_alpha, fee); + Self::unstake_from_subnet(&hotkey, &coldkey, netuid, possible_alpha, limit_price)?; // 5. We add the balance to the coldkey. If the above fails we will not credit this coldkey. Self::add_balance_to_coldkey_account(&coldkey, tao_unstaked); @@ -529,96 +378,12 @@ impl Pallet { Ok(()) } - /// ---- The implementation for the extrinsic remove_stake_limit_aggregate: Removes stake from - /// a hotkey on a subnet with a price limit. - /// - /// In case if slippage occurs and the price shall move beyond the limit - /// price, the staking order may execute only partially or not execute - /// at all. - /// - /// The operation will be delayed until the end of the block. - /// - /// # Args: - /// * 'origin': (Origin): - /// - The signature of the caller's coldkey. - /// - /// * 'hotkey' (T::AccountId): - /// - The associated hotkey account. - /// - /// * 'netuid' (u16): - /// - Subnetwork UID - /// - /// * 'amount_unstaked' (u64): - /// - The amount of stake to be added to the hotkey staking account. - /// - /// * 'limit_price' (u64): - /// - The limit price expressed in units of RAO per one Alpha. - /// - /// * 'allow_partial' (bool): - /// - Allows partial execution of the amount. If set to false, this becomes - /// fill or kill type or order. - /// - /// # Event: - /// * StakeRemoved; - /// - On the successfully removing stake from the hotkey account. - /// - /// # Raises: - /// * 'NotRegistered': - /// - Thrown if the account we are attempting to unstake from is non existent. - /// - /// * 'NonAssociatedColdKey': - /// - Thrown if the coldkey does not own the hotkey we are unstaking from. - /// - /// * 'NotEnoughStakeToWithdraw': - /// - Thrown if there is not enough stake on the hotkey to withdwraw this amount. - /// - pub fn do_remove_stake_limit_aggregate( - origin: T::RuntimeOrigin, - hotkey: T::AccountId, - netuid: u16, - alpha_unstaked: u64, - limit_price: u64, - allow_partial: bool, - ) -> dispatch::DispatchResult { - let coldkey = ensure_signed(origin)?; - - // Consider the weight from on_finalize - if cfg!(feature = "runtime-benchmarks") && !cfg!(test) { - Self::do_remove_stake_limit( - crate::dispatch::RawOrigin::Signed(coldkey.clone()).into(), - hotkey.clone(), - netuid, - alpha_unstaked, - limit_price, - allow_partial, - )?; - } - - let stake_job = StakeJob::RemoveStakeLimit { - hotkey, - coldkey, - netuid, - alpha_unstaked, - limit_price, - allow_partial, - }; - - let stake_job_id = NextStakeJobId::::get(); - let current_blocknumber = >::block_number(); - - StakeJobs::::insert(current_blocknumber, stake_job_id, stake_job); - NextStakeJobId::::set(stake_job_id.saturating_add(1)); - - // Done and ok. - Ok(()) - } - // Returns the maximum amount of RAO that can be executed with price limit - pub fn get_max_amount_remove(netuid: u16, limit_price: u64) -> Result> { + pub fn get_max_amount_remove(netuid: NetUid, limit_price: u64) -> Result> { // Corner case: root and stao // There's no slippage for root or stable subnets, so if limit price is 1e9 rao or // lower, then max_amount equals u64::MAX, otherwise it is 0. - if (netuid == Self::get_root_netuid()) || (SubnetMechanism::::get(netuid)) == 0 { + if netuid.is_root() || SubnetMechanism::::get(netuid) == 0 { if limit_price <= 1_000_000_000 { return Ok(u64::MAX); } else { @@ -626,57 +391,16 @@ impl Pallet { } } - // Corner case: SubnetAlphaIn is zero. Staking can't happen, so max amount is zero. - let alpha_in = SubnetAlphaIn::::get(netuid); - if alpha_in == 0 { - return Err(Error::ZeroMaxStakeAmount); - } - let alpha_in_u128 = alpha_in as u128; - - // Corner case: SubnetTAO is zero. Staking can't happen, so max amount is zero. - let tao_reserve = SubnetTAO::::get(netuid); - if tao_reserve == 0 { - return Err(Error::ZeroMaxStakeAmount); - } - let tao_reserve_u128 = tao_reserve as u128; - - // Corner case: limit_price == 0 (because there's division by limit price) - // => can sell all - if limit_price == 0 { - return Ok(u64::MAX); - } - - // Corner case: limit_price >= current_price (price cannot increase with unstaking) - // No overflows: alpha_price * tao <= u64::MAX * u64::MAX - // Alpha price is U96F32 size, but it is calculated as u64/u64, so it never uses all 96 bits. - let limit_price_u128 = limit_price as u128; - let tao = 1_000_000_000_u128; - if limit_price_u128 - >= tao_reserve_u128 - .saturating_mul(tao) - .checked_div(alpha_in_u128) - .unwrap_or(0) - { - return Err(Error::ZeroMaxStakeAmount); - } - - // Main case: SubnetTAO / limit_price - SubnetAlphaIn - // Non overflowing calculation: tao_reserve * tao <= u64::MAX * u64::MAX <= u128::MAX - // May overflow result, then it will be capped at u64::MAX, which is OK because that matches Alpha u64 size. - let result = tao_reserve_u128 - .saturating_mul(tao) - .checked_div(limit_price_u128) - .unwrap_or(0) - .saturating_sub(alpha_in_u128); - - if result < u64::MAX as u128 { - if result == 0 { - return Err(Error::ZeroMaxStakeAmount); - } + // Use reverting swap to estimate max limit amount + let result = + T::SwapInterface::swap(netuid.into(), OrderType::Sell, u64::MAX, limit_price, true) + .map(|r| r.amount_paid_in.saturating_add(r.fee_paid)) + .map_err(|_| Error::ZeroMaxStakeAmount)?; - Ok(result as u64) + if result != 0 { + Ok(result) } else { - Ok(u64::MAX) + Err(Error::ZeroMaxStakeAmount) } } } diff --git a/pallets/subtensor/src/staking/set_children.rs b/pallets/subtensor/src/staking/set_children.rs index 2d2ebaec47..35867f82ca 100644 --- a/pallets/subtensor/src/staking/set_children.rs +++ b/pallets/subtensor/src/staking/set_children.rs @@ -1,5 +1,6 @@ use super::*; -use sp_core::Get; + +use subtensor_runtime_common::NetUid; impl Pallet { /// ---- The implementation for the extrinsic do_set_child_singular: Sets a single child. @@ -36,7 +37,7 @@ impl Pallet { pub fn do_schedule_children( origin: T::RuntimeOrigin, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, children: Vec<(u64, T::AccountId)>, ) -> DispatchResult { // Check that the caller has signed the transaction. (the coldkey of the pairing) @@ -61,7 +62,7 @@ impl Pallet { // Check that this delegation is not on the root network. Child hotkeys are not valid on root. ensure!( - netuid != Self::get_root_netuid(), + !netuid.is_root(), Error::::RegistrationNotPermittedOnRootSubnet ); @@ -123,7 +124,7 @@ impl Pallet { // Calculate cool-down block let cooldown_block = - Self::get_current_block_as_u64().saturating_add(DefaultPendingCooldown::::get()); + Self::get_current_block_as_u64().saturating_add(PendingChildKeyCooldown::::get()); // Insert or update PendingChildKeys PendingChildKeys::::insert(netuid, hotkey.clone(), (children.clone(), cooldown_block)); @@ -170,7 +171,7 @@ impl Pallet { /// 1. **Old Children Cleanup**: Removes the hotkey from the parent list of its old children. /// 2. **New Children Assignment**: Assigns the new child to the hotkey and updates the parent list for the new child. /// - pub fn do_set_pending_children(netuid: u16) { + pub fn do_set_pending_children(netuid: NetUid) { let current_block = Self::get_current_block_as_u64(); // Iterate over all pending children of this subnet and set as needed @@ -251,7 +252,7 @@ impl Pallet { /// ``` /// let children = SubtensorModule::get_children(&hotkey, netuid); */ - pub fn get_children(hotkey: &T::AccountId, netuid: u16) -> Vec<(u64, T::AccountId)> { + pub fn get_children(hotkey: &T::AccountId, netuid: NetUid) -> Vec<(u64, T::AccountId)> { ChildKeys::::get(hotkey, netuid) } @@ -268,7 +269,7 @@ impl Pallet { /// ``` /// let parents = SubtensorModule::get_parents(&child, netuid); */ - pub fn get_parents(child: &T::AccountId, netuid: u16) -> Vec<(u64, T::AccountId)> { + pub fn get_parents(child: &T::AccountId, netuid: NetUid) -> Vec<(u64, T::AccountId)> { ParentKeys::::get(child, netuid) } @@ -302,7 +303,7 @@ impl Pallet { pub fn do_set_childkey_take( coldkey: T::AccountId, hotkey: T::AccountId, - netuid: u16, + netuid: NetUid, take: u16, ) -> DispatchResult { // Ensure the coldkey owns the hotkey @@ -373,7 +374,7 @@ impl Pallet { /// * `u16` /// - The childkey take value. This is a percentage represented as a value between 0 /// and 10000, where 10000 represents 100%. - pub fn get_childkey_take(hotkey: &T::AccountId, netuid: u16) -> u16 { + pub fn get_childkey_take(hotkey: &T::AccountId, netuid: NetUid) -> u16 { ChildkeyTake::::get(hotkey, netuid) } } diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 058622177e..cc1a1ad148 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -1,10 +1,10 @@ use super::*; -//use frame_system::pallet_prelude::BlockNumberFor; use safe_math::*; use share_pool::{SharePool, SharePoolDataOperations}; -//use sp_runtime::Saturating; use sp_std::ops::Neg; -use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32, U110F18}; +use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32}; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler, SwapResult}; impl Pallet { /// Retrieves the total alpha issuance for a given subnet. @@ -17,39 +17,13 @@ impl Pallet { /// /// # Returns /// * `u64` - The total alpha issuance for the specified subnet. - pub fn get_alpha_issuance(netuid: u16) -> u64 { + pub fn get_alpha_issuance(netuid: NetUid) -> u64 { SubnetAlphaIn::::get(netuid).saturating_add(SubnetAlphaOut::::get(netuid)) } - /// Calculates the price of alpha for a given subnet. - /// - /// This function determines the price of alpha by dividing the total TAO - /// reserves by the total alpha reserves (`SubnetAlphaIn`) for the specified subnet. - /// If the alpha reserves are zero, the function returns zero to avoid division by zero. - /// - /// # Arguments - /// * `netuid` - The unique identifier of the subnet. - /// - /// # Returns - /// * `I96F32` - The price of alpha for the specified subnet. - pub fn get_alpha_price(netuid: u16) -> U96F32 { - if netuid == Self::get_root_netuid() { - return U96F32::saturating_from_num(1.0); // Root. - } - if SubnetMechanism::::get(netuid) == 0 { - return U96F32::saturating_from_num(1.0); // Stable - } - if SubnetAlphaIn::::get(netuid) == 0 { - U96F32::saturating_from_num(0) - } else { - U96F32::saturating_from_num(SubnetTAO::::get(netuid)) - .checked_div(U96F32::saturating_from_num(SubnetAlphaIn::::get(netuid))) - .unwrap_or(U96F32::saturating_from_num(0)) - } - } - pub fn get_moving_alpha_price(netuid: u16) -> U96F32 { + pub fn get_moving_alpha_price(netuid: NetUid) -> U96F32 { let one = U96F32::saturating_from_num(1.0); - if netuid == Self::get_root_netuid() { + if netuid.is_root() { // Root. one } else if SubnetMechanism::::get(netuid) == 0 { @@ -60,7 +34,7 @@ impl Pallet { } } - pub fn update_moving_price(netuid: u16) { + pub fn update_moving_price(netuid: NetUid) { let blocks_since_start_call = U96F32::saturating_from_num({ // We expect FirstEmissionBlockNumber to be set earlier, and we take the block when // `start_call` was called (first block before FirstEmissionBlockNumber). @@ -83,8 +57,10 @@ impl Pallet { // Because alpha = b / (b + h), where b and h > 0, alpha < 1, so 1 - alpha > 0. // We can use unsigned type here: U96F32 let one_minus_alpha: U96F32 = U96F32::saturating_from_num(1.0).saturating_sub(alpha); - let current_price: U96F32 = alpha - .saturating_mul(Self::get_alpha_price(netuid).min(U96F32::saturating_from_num(1.0))); + let current_price: U96F32 = alpha.saturating_mul( + T::SwapInterface::current_alpha_price(netuid.into()) + .min(U96F32::saturating_from_num(1.0)), + ); let current_moving: U96F32 = one_minus_alpha.saturating_mul(Self::get_moving_alpha_price(netuid)); // Convert batch to signed I96F32 to avoid migration of SubnetMovingPrice for now`` @@ -146,7 +122,7 @@ impl Pallet { /// pub fn get_stake_weights_for_hotkey_on_subnet( hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, ) -> (I64F64, I64F64, I64F64) { // Retrieve the global tao weight. let tao_weight = I64F64::saturating_from_num(Self::get_tao_weight()); @@ -172,7 +148,9 @@ impl Pallet { /// Calculates the weighted combination of alpha and global tao for hotkeys on a subnet. /// - pub fn get_stake_weights_for_network(netuid: u16) -> (Vec, Vec, Vec) { + pub fn get_stake_weights_for_network( + netuid: NetUid, + ) -> (Vec, Vec, Vec) { // Retrieve the global tao weight. let tao_weight: I64F64 = I64F64::saturating_from_num(Self::get_tao_weight()); log::debug!("tao_weight: {:?}", tao_weight); @@ -250,10 +228,9 @@ impl Pallet { /// /// # Note /// This function uses saturating arithmetic to prevent overflows. - pub fn get_tao_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16) -> u64 { - let initial_tao: U96F32 = U96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(hotkey, Self::get_root_netuid()), - ); + pub fn get_tao_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> u64 { + let initial_tao: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT)); // Initialize variables to track alpha allocated to children and inherited from parents. let mut tao_to_children: U96F32 = U96F32::saturating_from_num(0); @@ -298,9 +275,10 @@ impl Pallet { // Step 4: Calculate the total tao inherited from parents. for (proportion, parent) in parents { // Retrieve the parent's total stake on this subnet. - let parent_tao: U96F32 = U96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(&parent, Self::get_root_netuid()), - ); + let parent_tao = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet( + &parent, + NetUid::ROOT, + )); log::trace!( "Parent tao for parent {:?} on subnet {}: {:?}", parent, @@ -309,7 +287,7 @@ impl Pallet { ); // Convert the proportion to a normalized value between 0 and 1. - let normalized_proportion: U96F32 = U96F32::saturating_from_num(proportion) + let normalized_proportion = U96F32::saturating_from_num(proportion) .safe_div(U96F32::saturating_from_num(u64::MAX)); log::trace!( "Normalized proportion from parent: {:?}", @@ -344,7 +322,7 @@ impl Pallet { finalized_tao.saturating_to_num::() } - pub fn get_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16) -> u64 { + pub fn get_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> u64 { // Step 1: Retrieve the initial total stake (alpha) for the hotkey on the specified subnet. let initial_alpha: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); @@ -354,7 +332,7 @@ impl Pallet { netuid, initial_alpha ); - if netuid == 0 { + if netuid.is_root() { return initial_alpha.saturating_to_num::(); } @@ -469,7 +447,7 @@ impl Pallet { pub fn has_enough_stake_on_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, decrement: u64, ) -> bool { // Retrieve the current stake for this hotkey-coldkey pair on the subnet @@ -501,7 +479,7 @@ impl Pallet { pub fn get_stake_for_hotkey_and_coldkey_on_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, ) -> u64 { let alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); alpha_share_pool.try_get_value(coldkey).unwrap_or(0) @@ -521,7 +499,7 @@ impl Pallet { /// /// # Note /// This function returns the cumulative stake across all coldkeys associated with this hotkey on the subnet. - pub fn get_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16) -> u64 { + pub fn get_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> u64 { // Retrieve and return the total alpha this hotkey owns on this subnet. // This value represents the sum of stakes from all coldkeys associated with this hotkey. TotalHotkeyAlpha::::get(hotkey, netuid) @@ -536,7 +514,7 @@ impl Pallet { /// * `netuid` - The unique identifier of the subnet. /// * `amount` - The amount of alpha to be added. /// - pub fn increase_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16, amount: u64) { + pub fn increase_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid, amount: u64) { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); alpha_share_pool.update_value_for_all(amount as i64); } @@ -550,7 +528,7 @@ impl Pallet { /// * `netuid` - The unique identifier of the subnet. /// * `amount` - The amount of alpha to be added. /// - pub fn decrease_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16, amount: u64) { + pub fn decrease_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid, amount: u64) { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); alpha_share_pool.update_value_for_all((amount as i64).neg()); } @@ -568,7 +546,7 @@ impl Pallet { pub fn increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, amount: u64, ) -> u64 { if amount > 0 { @@ -590,7 +568,7 @@ impl Pallet { pub fn try_increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, amount: u64, ) -> bool { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); @@ -610,7 +588,7 @@ impl Pallet { pub fn decrease_stake_for_hotkey_and_coldkey_on_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, amount: u64, ) -> u64 { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); @@ -630,146 +608,119 @@ impl Pallet { actual_alpha.neg().max(0).unsigned_abs() } - /// Calculates Some(Alpha) returned from pool by staking operation - /// if liquidity allows that. If not, returns None. - /// - /// If new alpha_reserve is about to drop below DefaultMinimumPoolLiquidity, - /// then don't do it. - /// - pub fn sim_swap_tao_for_alpha(netuid: u16, tao: u64) -> Option { - // Step 1: Get the mechanism type for the subnet (0 for Stable, 1 for Dynamic) - let mechanism_id: u16 = SubnetMechanism::::get(netuid); - // Step 2: Initialized vars. - if mechanism_id == 1 { - // Step 3.a.1: Dynamic mechanism calculations - let tao_reserves: U110F18 = U110F18::saturating_from_num(SubnetTAO::::get(netuid)); - let alpha_reserves: U110F18 = - U110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); - // Step 3.a.2: Compute constant product k = alpha * tao - let k: U110F18 = alpha_reserves.saturating_mul(tao_reserves); - - // Calculate new alpha reserve - let new_alpha_reserves: U110F18 = - k.safe_div(tao_reserves.saturating_add(U110F18::saturating_from_num(tao))); - - // Step 3.a.3: Calculate alpha staked using the constant product formula - // alpha_stake_recieved = current_alpha - (k / (current_tao + new_tao)) - if new_alpha_reserves >= DefaultMinimumPoolLiquidity::::get() { - Some( - alpha_reserves - .saturating_sub(new_alpha_reserves) - .saturating_to_num::(), - ) - } else { - None - } - } else { - // Step 3.b.1: Stable mechanism, just return the value 1:1 - Some(tao) - } - } - - /// Calculates Some(Tao) returned from pool by unstaking operation - /// if liquidity allows that. If not, returns None. - /// - /// If new tao_reserve is about to drop below DefaultMinimumPoolLiquidity, - /// then don't do it. + /// Swaps TAO for the alpha token on the subnet. /// - pub fn sim_swap_alpha_for_tao(netuid: u16, alpha: u64) -> Option { + /// Updates TaoIn, AlphaIn, and AlphaOut + pub fn swap_tao_for_alpha( + netuid: NetUid, + tao: u64, + price_limit: u64, + ) -> Result { // Step 1: Get the mechanism type for the subnet (0 for Stable, 1 for Dynamic) let mechanism_id: u16 = SubnetMechanism::::get(netuid); - // Step 2: Swap alpha and attain tao if mechanism_id == 1 { - // Step 3.a.1: Dynamic mechanism calculations - let tao_reserves: U110F18 = U110F18::saturating_from_num(SubnetTAO::::get(netuid)); - let alpha_reserves: U110F18 = - U110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); - // Step 3.a.2: Compute constant product k = alpha * tao - let k: U110F18 = alpha_reserves.saturating_mul(tao_reserves); - - // Calculate new tao reserve - let new_tao_reserves: U110F18 = k - .checked_div(alpha_reserves.saturating_add(U110F18::saturating_from_num(alpha))) - .unwrap_or(U110F18::saturating_from_num(0)); - - // Step 3.a.3: Calculate alpha staked using the constant product formula - // tao_recieved = tao_reserves - (k / (alpha_reserves + new_tao)) - if new_tao_reserves >= DefaultMinimumPoolLiquidity::::get() { - Some( - tao_reserves - .saturating_sub(new_tao_reserves) - .saturating_to_num::(), - ) - } else { - None - } - } else { - // Step 3.b.1: Stable mechanism, just return the value 1:1 - Some(alpha) - } - } + let swap_result = + T::SwapInterface::swap(netuid.into(), OrderType::Buy, tao, price_limit, false)?; + + // Decrease Alpha reserves. + Self::decrease_provided_alpha_reserve( + netuid.into(), + swap_result + .alpha_reserve_delta + .abs() + .try_into() + .unwrap_or(0), + ); - /// Swaps TAO for the alpha token on the subnet. - /// - /// Updates TaoIn, AlphaIn, and AlphaOut - pub fn swap_tao_for_alpha(netuid: u16, tao: u64) -> u64 { - if let Some(alpha) = Self::sim_swap_tao_for_alpha(netuid, tao) { - // Step 4. Decrease Alpha reserves. - SubnetAlphaIn::::mutate(netuid, |total| { - *total = total.saturating_sub(alpha); - }); - // Step 5: Increase Alpha outstanding. + // Increase Alpha outstanding. SubnetAlphaOut::::mutate(netuid, |total| { - *total = total.saturating_add(alpha); + *total = total.saturating_add(swap_result.amount_paid_out); }); - // Step 6: Increase Tao reserves. + + // Increase only the protocol TAO reserve. We only use the sum of + // (SubnetTAO + SubnetTaoProvided) in tao_reserve(), so it is irrelevant + // which one to increase. SubnetTAO::::mutate(netuid, |total| { - *total = total.saturating_add(tao); - }); - // Step 7: Increase Total Tao reserves. - TotalStake::::mutate(|total| { - *total = total.saturating_add(tao); + *total = total.saturating_add(swap_result.tao_reserve_delta as u64); }); - // Step 8. Increase total subnet TAO volume. + + // Increase Total Tao reserves. + TotalStake::::mutate(|total| *total = total.saturating_add(tao)); + + // Increase total subnet TAO volume. SubnetVolume::::mutate(netuid, |total| { *total = total.saturating_add(tao.into()); }); - // Step 9. Return the alpha received. - alpha + + // Return the alpha received. + Ok(swap_result) } else { - 0 + // Step 3.b.1: Stable mechanism, just return the value 1:1 + Ok(SwapResult { + amount_paid_in: tao, + amount_paid_out: tao, + fee_paid: 0, + tao_reserve_delta: 0, + alpha_reserve_delta: 0, + }) } } - /// Swaps a subnet's Alpba token for TAO. + /// Swaps a subnet's Alpha token for TAO. /// /// Updates TaoIn, AlphaIn, and AlphaOut - pub fn swap_alpha_for_tao(netuid: u16, alpha: u64) -> u64 { - if let Some(tao) = Self::sim_swap_alpha_for_tao(netuid, alpha) { - // Step 4: Increase Alpha reserves. + pub fn swap_alpha_for_tao( + netuid: NetUid, + alpha: u64, + price_limit: u64, + ) -> Result { + // Step 1: Get the mechanism type for the subnet (0 for Stable, 1 for Dynamic) + let mechanism_id: u16 = SubnetMechanism::::get(netuid); + // Step 2: Swap alpha and attain tao + if mechanism_id == 1 { + let swap_result = + T::SwapInterface::swap(netuid.into(), OrderType::Sell, alpha, price_limit, false)?; + + // Increase only the protocol Alpha reserve. We only use the sum of + // (SubnetAlphaIn + SubnetAlphaInProvided) in alpha_reserve(), so it is irrelevant + // which one to increase. SubnetAlphaIn::::mutate(netuid, |total| { - *total = total.saturating_add(alpha); + *total = total.saturating_add(swap_result.alpha_reserve_delta as u64); }); - // Step 5: Decrease Alpha outstanding. + + // Decrease Alpha outstanding. + // TODO: Deprecate, not accurate in v3 anymore SubnetAlphaOut::::mutate(netuid, |total| { *total = total.saturating_sub(alpha); }); - // Step 6: Decrease tao reserves. - SubnetTAO::::mutate(netuid, |total| { - *total = total.saturating_sub(tao); - }); - // Step 7: Reduce total TAO reserves. + + // Decrease tao reserves. + Self::decrease_provided_tao_reserve( + netuid.into(), + swap_result.tao_reserve_delta.abs().try_into().unwrap_or(0), + ); + + // Reduce total TAO reserves. TotalStake::::mutate(|total| { - *total = total.saturating_sub(tao); + *total = total.saturating_sub(swap_result.amount_paid_out) }); - // Step 8. Increase total subnet TAO volume. + + // Increase total subnet TAO volume. SubnetVolume::::mutate(netuid, |total| { - *total = total.saturating_add(tao.into()); + *total = total.saturating_add(swap_result.amount_paid_out.into()) }); - // Step 9. Return the tao received. - tao + + // Return the tao received. + Ok(swap_result) } else { - 0 + // Step 3.b.1: Stable mechanism, just return the value 1:1 + Ok(SwapResult { + amount_paid_in: alpha, + amount_paid_out: alpha, + fee_paid: 0, + tao_reserve_delta: 0, + alpha_reserve_delta: 0, + }) } } @@ -779,16 +730,26 @@ impl Pallet { pub fn unstake_from_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, alpha: u64, - fee: u64, - ) -> u64 { - // Step 1: Decrease alpha on subneet + price_limit: u64, + ) -> Result { + // Decrease alpha on subneet let actual_alpha_decrease = Self::decrease_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, alpha); - // Step 2: Swap the alpha for TAO. - let tao: u64 = Self::swap_alpha_for_tao(netuid, actual_alpha_decrease); + // Swap the alpha for TAO. + let swap_result = Self::swap_alpha_for_tao(netuid, actual_alpha_decrease, price_limit)?; + + // Refund the unused alpha (in case if limit price is hit) + let refund = actual_alpha_decrease.saturating_sub( + swap_result + .amount_paid_in + .saturating_add(swap_result.fee_paid), + ); + if refund > 0 { + Self::increase_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, refund); + } // Step 3: Update StakingHotkeys if the hotkey's total alpha, across all subnets, is zero // TODO const: fix. @@ -798,38 +759,29 @@ impl Pallet { // }); // } - // Step 4. Reduce tao amount by staking fee and credit this fee to SubnetTAO - let tao_unstaked = tao.saturating_sub(fee); - let actual_fee = tao.saturating_sub(tao_unstaked); - SubnetTAO::::mutate(netuid, |total| { - *total = total.saturating_add(actual_fee); - }); - TotalStake::::mutate(|total| { - *total = total.saturating_add(actual_fee); - }); LastColdkeyHotkeyStakeBlock::::insert(coldkey, hotkey, Self::get_current_block_as_u64()); - // Step 5. Deposit and log the unstaking event. + // Deposit and log the unstaking event. Self::deposit_event(Event::StakeRemoved( coldkey.clone(), hotkey.clone(), - tao_unstaked, + swap_result.amount_paid_out, actual_alpha_decrease, netuid, - actual_fee, + swap_result.fee_paid, )); + log::debug!( - "StakeRemoved( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee: {:?} )", + "StakeRemoved( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee {} )", coldkey.clone(), hotkey.clone(), - tao_unstaked, + swap_result.amount_paid_out, actual_alpha_decrease, netuid, - actual_fee + swap_result.fee_paid ); - // Step 6: Return the amount of TAO unstaked. - tao_unstaked + Ok(swap_result.amount_paid_out) } /// Stakes TAO into a subnet for a given hotkey and coldkey pair. @@ -838,72 +790,81 @@ impl Pallet { pub(crate) fn stake_into_subnet( hotkey: &T::AccountId, coldkey: &T::AccountId, - netuid: u16, + netuid: NetUid, tao: u64, - fee: u64, - ) -> u64 { - // Step 1. Reduce tao amount by staking fee and credit this fee to SubnetTAO - // At this point tao was already withdrawn from the user balance and is considered - // available - let tao_staked = tao.saturating_sub(fee); - let actual_fee = tao.saturating_sub(tao_staked); - - // Step 2. Swap the tao to alpha. - let alpha: u64 = Self::swap_tao_for_alpha(netuid, tao_staked); - let mut actual_alpha = 0; - if (tao_staked > 0) && (alpha > 0) { - // Step 3: Increase the alpha on the hotkey account. - actual_alpha = Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, coldkey, netuid, alpha, - ); + price_limit: u64, + ) -> Result { + // Swap the tao to alpha. + let swap_result = Self::swap_tao_for_alpha(netuid, tao, price_limit)?; + + ensure!(swap_result.amount_paid_out > 0, Error::::AmountTooLow); + + ensure!( + Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, + netuid, + swap_result.amount_paid_out, + ), + Error::::InsufficientLiquidity + ); + + // Increase the alpha on the hotkey account. + if Self::increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, + coldkey, + netuid, + swap_result.amount_paid_out, + ) == 0 + || swap_result.amount_paid_out == 0 + { + return Ok(0); + } + + // Step 4: Update the list of hotkeys staking for this coldkey + let mut staking_hotkeys = StakingHotkeys::::get(coldkey); + if !staking_hotkeys.contains(hotkey) { + staking_hotkeys.push(hotkey.clone()); + StakingHotkeys::::insert(coldkey, staking_hotkeys.clone()); } - // Step 4. Increase Tao reserves by the fee amount. - SubnetTAO::::mutate(netuid, |total| { - *total = total.saturating_add(actual_fee); - }); - TotalStake::::mutate(|total| { - *total = total.saturating_add(actual_fee); - }); LastColdkeyHotkeyStakeBlock::::insert(coldkey, hotkey, Self::get_current_block_as_u64()); - // Step 5. Deposit and log the staking event. + // Deposit and log the staking event. Self::deposit_event(Event::StakeAdded( coldkey.clone(), hotkey.clone(), - tao_staked, - actual_alpha, + tao, + swap_result.amount_paid_out, netuid, - actual_fee, + swap_result.fee_paid, )); + log::debug!( - "StakeAdded( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee: {:?} )", + "StakeAdded( coldkey: {:?}, hotkey:{:?}, tao: {:?}, alpha:{:?}, netuid: {:?}, fee {} )", coldkey.clone(), hotkey.clone(), - tao_staked, - actual_alpha, + tao, + swap_result.amount_paid_out, netuid, - actual_fee + swap_result.fee_paid, ); - // Step 6: Return the amount of alpha staked - actual_alpha + Ok(swap_result.amount_paid_out) } pub fn get_alpha_share_pool( hotkey: ::AccountId, - netuid: u16, + netuid: NetUid, ) -> SharePool, HotkeyAlphaSharePoolDataOperations> { let ops = HotkeyAlphaSharePoolDataOperations::new(hotkey, netuid); SharePool::, HotkeyAlphaSharePoolDataOperations>::new(ops) } /// Validate add_stake user input - /// pub fn validate_add_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, stake_to_be_added: u64, max_amount: u64, allow_partial: bool, @@ -911,8 +872,20 @@ impl Pallet { // Ensure that the subnet exists. ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + // Ensure that the subnet is enabled. + Self::ensure_subtoken_enabled(netuid)?; + // Get the minimum balance (and amount) that satisfies the transaction - let min_amount = DefaultMinStake::::get().saturating_add(DefaultStakingFee::::get()); + let min_amount = { + let min_stake = DefaultMinStake::::get(); + let fee = T::SwapInterface::sim_swap(netuid.into(), OrderType::Buy, min_stake) + .map(|res| res.fee_paid) + .unwrap_or(T::SwapInterface::approx_fee_amount( + netuid.into(), + min_stake, + )); + min_stake.saturating_add(fee) + }; // Ensure that the stake_to_be_added is at least the min_amount ensure!(stake_to_be_added >= min_amount, Error::::AmountTooLow); @@ -935,16 +908,20 @@ impl Pallet { Error::::HotKeyAccountNotExists ); - let expected_alpha = Self::sim_swap_tao_for_alpha(netuid, stake_to_be_added); + let expected_alpha = + T::SwapInterface::sim_swap(netuid.into(), OrderType::Buy, stake_to_be_added) + .map_err(|_| Error::::InsufficientLiquidity)?; - // Ensure that we have adequate liquidity - ensure!(expected_alpha.is_some(), Error::::InsufficientLiquidity); + ensure!( + expected_alpha.amount_paid_out > 0, + Error::::InsufficientLiquidity + ); // Ensure hotkey pool is precise enough let try_stake_result = Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey, netuid, - expected_alpha.unwrap_or(0), + expected_alpha.amount_paid_out, ); ensure!(try_stake_result, Error::::InsufficientLiquidity); @@ -956,7 +933,7 @@ impl Pallet { pub fn validate_remove_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, alpha_unstaked: u64, max_amount: u64, allow_partial: bool, @@ -964,15 +941,17 @@ impl Pallet { // Ensure that the subnet exists. ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + // Ensure that the subnet is enabled. + // Self::ensure_subtoken_enabled(netuid)?; + // Ensure that the stake amount to be removed is above the minimum in tao equivalent. - if let Some(tao_equivalent) = Self::sim_swap_alpha_for_tao(netuid, alpha_unstaked) { - ensure!( - tao_equivalent > DefaultMinStake::::get(), + match T::SwapInterface::sim_swap(netuid.into(), OrderType::Sell, alpha_unstaked) { + Ok(res) => ensure!( + res.amount_paid_out > DefaultMinStake::::get(), Error::::AmountTooLow - ); - } else { - return Err(Error::::InsufficientLiquidity); - }; + ), + Err(_) => return Err(Error::::InsufficientLiquidity), + } // Ensure that if partial execution is not allowed, the amount will not cause // slippage over desired @@ -1003,7 +982,7 @@ impl Pallet { only_alpha: bool, ) -> Result<(), Error> { // Get all netuids (filter out root) - let subnets: Vec = Self::get_all_subnet_netuids(); + let subnets = Self::get_all_subnet_netuids(); // Ensure that the hotkey account exists this is only possible through registration. ensure!( @@ -1013,7 +992,7 @@ impl Pallet { let mut unstaking_any = false; for netuid in subnets.iter() { - if only_alpha && (*netuid == Self::get_root_netuid()) { + if only_alpha && netuid.is_root() { continue; } @@ -1039,8 +1018,8 @@ impl Pallet { destination_coldkey: &T::AccountId, origin_hotkey: &T::AccountId, destination_hotkey: &T::AccountId, - origin_netuid: u16, - destination_netuid: u16, + origin_netuid: NetUid, + destination_netuid: NetUid, alpha_amount: u64, max_amount: u64, maybe_allow_partial: Option, @@ -1097,15 +1076,14 @@ impl Pallet { ); // Ensure that the stake amount to be removed is above the minimum in tao equivalent. - let tao_equivalent_result = Self::sim_swap_alpha_for_tao(origin_netuid, alpha_amount); - if let Some(tao_equivalent) = tao_equivalent_result { - ensure!( - tao_equivalent > DefaultMinStake::::get(), - Error::::AmountTooLow - ); - } else { - return Err(Error::::InsufficientLiquidity); - } + let tao_equivalent = + T::SwapInterface::sim_swap(origin_netuid.into(), OrderType::Sell, alpha_amount) + .map(|res| res.amount_paid_out) + .map_err(|_| Error::::InsufficientLiquidity)?; + ensure!( + tao_equivalent > DefaultMinStake::::get(), + Error::::AmountTooLow + ); // Ensure that if partial execution is not allowed, the amount will not cause // slippage over desired @@ -1115,18 +1093,6 @@ impl Pallet { } } - let expected_alpha = - Self::sim_swap_tao_for_alpha(destination_netuid, tao_equivalent_result.unwrap_or(0)) - .unwrap_or(0); - - // Ensure that the amount being staked to the new hotkey is precise enough - let try_stake_result = Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet( - destination_hotkey, - destination_netuid, - expected_alpha, - ); - ensure!(try_stake_result, Error::::InsufficientLiquidity); - if check_transfer_toggle { // Ensure transfer is toggled. ensure!( @@ -1142,431 +1108,45 @@ impl Pallet { Ok(()) } - pub(crate) fn calculate_staking_fee( - origin: Option<(&T::AccountId, u16)>, - _origin_coldkey: &T::AccountId, - destination: Option<(&T::AccountId, u16)>, - _destination_coldkey: &T::AccountId, - alpha_estimate: U96F32, - ) -> u64 { - match origin { - // If origin is defined, we are removing/moving stake - Some((origin_hotkey, origin_netuid)) => { - if let Some((_destination_hotkey, destination_netuid)) = destination { - // This is a stake move/swap/transfer - if destination_netuid == origin_netuid { - // If destination is on the same subnet, use the default fee - return DefaultStakingFee::::get(); - } - } + pub fn increase_provided_tao_reserve(netuid: NetUid, tao: u64) { + SubnetTaoProvided::::mutate(netuid, |total| { + *total = total.saturating_add(tao); + }); + } - if origin_netuid == Self::get_root_netuid() - || SubnetMechanism::::get(origin_netuid) == 0 - { - // If the origin netuid is root, or the subnet mechanism is 0, use the default fee - DefaultStakingFee::::get() - } else { - // Otherwise, calculate the fee based on the alpha estimate - // Here we are using TotalHotkeyAlphaLastEpoch, which is exactly the value that - // was used to calculate AlphaDividendsPerSubnet - let tao_estimate = U96F32::saturating_from_num( - Self::sim_swap_alpha_for_tao( - origin_netuid, - alpha_estimate.saturating_to_num::(), - ) - .unwrap_or(0), - ); - let mut fee = tao_estimate - .saturating_mul( - U96F32::saturating_from_num(AlphaDividendsPerSubnet::::get( - origin_netuid, - &origin_hotkey, - )) - .safe_div(U96F32::saturating_from_num( - TotalHotkeyAlphaLastEpoch::::get(&origin_hotkey, origin_netuid), - )), - ) - .saturating_to_num::(); - - // 0.005% per epoch matches to 44% annual in compound interest. Do not allow the fee - // to be lower than that. (1.00005^(365*20) ~= 1.44) - let apr_20_percent = U96F32::saturating_from_num(0.00005); - fee = fee.max( - tao_estimate - .saturating_mul(apr_20_percent) - .saturating_to_num::(), - ); - - // We should at least get DefaultStakingFee anyway - fee.max(DefaultStakingFee::::get()) - } - } - // If origin is not defined, we are adding stake; use default fee - None => DefaultStakingFee::::get(), + pub fn decrease_provided_tao_reserve(netuid: NetUid, tao: u64) { + // First, decrease SubnetTaoProvided, then deduct the rest from SubnetTAO + let subnet_tao = SubnetTAO::::get(netuid); + let subnet_tao_provided = SubnetTaoProvided::::get(netuid); + let remainder = subnet_tao_provided.saturating_sub(tao); + let carry_over = tao.saturating_sub(subnet_tao_provided); + if carry_over == 0 { + SubnetTaoProvided::::set(netuid, remainder); + } else { + SubnetTaoProvided::::set(netuid, 0_u64); + SubnetTAO::::set(netuid, subnet_tao.saturating_sub(carry_over)); } } - // // Process staking job for on_finalize() hook. - // pub(crate) fn do_on_finalize(current_block_number: BlockNumberFor) { - // // We delay job execution - // const DELAY_IN_BLOCKS: u32 = 1u32; - // let actual_block_with_delay = current_block_number.saturating_sub(DELAY_IN_BLOCKS.into()); - // - // let stake_jobs = StakeJobs::::drain_prefix(actual_block_with_delay).collect::>(); - // - // // Sort jobs by job type - // let mut add_stake = vec![]; - // let mut remove_stake = vec![]; - // let mut add_stake_limit = vec![]; - // let mut remove_stake_limit = vec![]; - // let mut unstake_all = vec![]; - // let mut unstake_all_aplha = vec![]; - // - // for (_, job) in stake_jobs.into_iter() { - // match &job { - // StakeJob::AddStake { .. } => add_stake.push(job), - // StakeJob::RemoveStake { .. } => remove_stake.push(job), - // StakeJob::AddStakeLimit { .. } => add_stake_limit.push(job), - // StakeJob::RemoveStakeLimit { .. } => remove_stake_limit.push(job), - // StakeJob::UnstakeAll { .. } => unstake_all.push(job), - // StakeJob::UnstakeAllAlpha { .. } => unstake_all_aplha.push(job), - // } - // } - // // Reorder jobs based on the previous block hash - // let previous_block_hash = >::parent_hash(); - // let hash_bytes = previous_block_hash.as_ref(); - // let first_byte = hash_bytes.first().expect("hash operation is infallible"); - // // Extract the first bit - // let altered_order = (first_byte & 0b10000000) != 0; - // - // // Ascending sort by coldkey - // remove_stake_limit.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::RemoveStakeLimit { coldkey: a_key, .. }, - // StakeJob::RemoveStakeLimit { coldkey: b_key, .. }, - // ) => { - // let direct_order = a_key.cmp(b_key); // ascending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // remove_stake.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::RemoveStake { coldkey: a_key, .. }, - // StakeJob::RemoveStake { coldkey: b_key, .. }, - // ) => { - // let direct_order = a_key.cmp(b_key); // ascending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // unstake_all.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::UnstakeAll { coldkey: a_key, .. }, - // StakeJob::UnstakeAll { coldkey: b_key, .. }, - // ) => { - // let direct_order = a_key.cmp(b_key); // ascending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // unstake_all_aplha.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::UnstakeAllAlpha { coldkey: a_key, .. }, - // StakeJob::UnstakeAllAlpha { coldkey: b_key, .. }, - // ) => { - // let direct_order = a_key.cmp(b_key); // ascending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // // Descending sort by coldkey - // add_stake_limit.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::AddStakeLimit { coldkey: a_key, .. }, - // StakeJob::AddStakeLimit { coldkey: b_key, .. }, - // ) => { - // let direct_order = b_key.cmp(a_key); // descending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // add_stake.sort_by(|a, b| match (a, b) { - // ( - // StakeJob::AddStake { coldkey: a_key, .. }, - // StakeJob::AddStake { coldkey: b_key, .. }, - // ) => { - // let direct_order = b_key.cmp(a_key); // descending - // - // if altered_order { - // direct_order.reverse() - // } else { - // direct_order - // } - // } - // _ => sp_std::cmp::Ordering::Equal, // unreachable - // }); - // - // // direct job order - // let mut job_batches = vec![ - // remove_stake_limit, - // remove_stake, - // unstake_all, - // unstake_all_aplha, - // add_stake_limit, - // add_stake, - // ]; - // if altered_order { - // job_batches.reverse(); - // } - // - // for jobs in job_batches.into_iter() { - // for job in jobs.into_iter() { - // match job { - // StakeJob::RemoveStakeLimit { - // hotkey, - // coldkey, - // netuid, - // alpha_unstaked, - // limit_price, - // allow_partial, - // } => { - // let result = Self::do_remove_stake_limit( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // alpha_unstaked, - // limit_price, - // allow_partial, - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to remove aggregated limited stake: {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // limit_price, - // allow_partial, - // err - // ); - // Self::deposit_event(Event::FailedToRemoveAggregatedLimitedStake( - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // limit_price, - // allow_partial, - // )); - // } else { - // Self::deposit_event(Event::AggregatedLimitedStakeRemoved( - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // limit_price, - // allow_partial, - // )); - // } - // } - // StakeJob::RemoveStake { - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // } => { - // let result = Self::do_remove_stake( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // alpha_unstaked, - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to remove aggregated stake: {:?}, {:?}, {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // err - // ); - // Self::deposit_event(Event::FailedToRemoveAggregatedStake( - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // )); - // } else { - // Self::deposit_event(Event::AggregatedStakeRemoved( - // coldkey, - // hotkey, - // netuid, - // alpha_unstaked, - // )); - // } - // } - // StakeJob::UnstakeAll { hotkey, coldkey } => { - // let result = Self::do_unstake_all( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to unstake all: {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // err - // ); - // Self::deposit_event(Event::AggregatedUnstakeAllFailed(coldkey, hotkey)); - // } else { - // Self::deposit_event(Event::AggregatedUnstakeAllSucceeded( - // coldkey, hotkey, - // )); - // } - // } - // StakeJob::UnstakeAllAlpha { hotkey, coldkey } => { - // let result = Self::do_unstake_all_alpha( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to unstake all alpha: {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // err - // ); - // Self::deposit_event(Event::AggregatedUnstakeAllAlphaFailed( - // coldkey, hotkey, - // )); - // } else { - // Self::deposit_event(Event::AggregatedUnstakeAllAlphaSucceeded( - // coldkey, hotkey, - // )); - // } - // } - // StakeJob::AddStakeLimit { - // hotkey, - // coldkey, - // netuid, - // stake_to_be_added, - // limit_price, - // allow_partial, - // } => { - // let result = Self::do_add_stake_limit( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // stake_to_be_added, - // limit_price, - // allow_partial, - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to add aggregated limited stake: {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // limit_price, - // allow_partial, - // err - // ); - // Self::deposit_event(Event::FailedToAddAggregatedLimitedStake( - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // limit_price, - // allow_partial, - // )); - // } else { - // Self::deposit_event(Event::AggregatedLimitedStakeAdded( - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // limit_price, - // allow_partial, - // )); - // } - // } - // StakeJob::AddStake { - // hotkey, - // coldkey, - // netuid, - // stake_to_be_added, - // } => { - // let result = Self::do_add_stake( - // dispatch::RawOrigin::Signed(coldkey.clone()).into(), - // hotkey.clone(), - // netuid, - // stake_to_be_added, - // ); - // - // if let Err(err) = result { - // log::debug!( - // "Failed to add aggregated stake: {:?}, {:?}, {:?}, {:?}, {:?}", - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // err - // ); - // Self::deposit_event(Event::FailedToAddAggregatedStake( - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // )); - // } else { - // Self::deposit_event(Event::AggregatedStakeAdded( - // coldkey, - // hotkey, - // netuid, - // stake_to_be_added, - // )); - // } - // } - // } - // } - // } - // } + pub fn increase_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + SubnetAlphaInProvided::::mutate(netuid, |total| { + *total = total.saturating_add(alpha); + }); + } + + pub fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + // First, decrease SubnetAlphaInProvided, then deduct the rest from SubnetAlphaIn + let subnet_alpha = SubnetAlphaIn::::get(netuid); + let subnet_alpha_provided = SubnetAlphaInProvided::::get(netuid); + let remainder = subnet_alpha_provided.saturating_sub(alpha); + let carry_over = alpha.saturating_sub(subnet_alpha_provided); + if carry_over == 0 { + SubnetAlphaInProvided::::set(netuid, remainder); + } else { + SubnetAlphaInProvided::::set(netuid, 0_u64); + SubnetAlphaIn::::set(netuid, subnet_alpha.saturating_sub(carry_over)); + } + } } /////////////////////////////////////////// @@ -1574,13 +1154,13 @@ impl Pallet { #[derive(Debug)] pub struct HotkeyAlphaSharePoolDataOperations { - netuid: u16, + netuid: NetUid, hotkey: ::AccountId, _marker: sp_std::marker::PhantomData, } impl HotkeyAlphaSharePoolDataOperations { - fn new(hotkey: ::AccountId, netuid: u16) -> Self { + fn new(hotkey: ::AccountId, netuid: NetUid) -> Self { HotkeyAlphaSharePoolDataOperations { netuid, hotkey, diff --git a/pallets/subtensor/src/subnets/registration.rs b/pallets/subtensor/src/subnets/registration.rs index 5c698c1b33..a2eb180af1 100644 --- a/pallets/subtensor/src/subnets/registration.rs +++ b/pallets/subtensor/src/subnets/registration.rs @@ -2,12 +2,14 @@ use super::*; use sp_core::{H256, U256}; use sp_io::hashing::{keccak_256, sha2_256}; use sp_runtime::Saturating; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; use system::pallet_prelude::BlockNumberFor; const LOG_TARGET: &str = "runtime::subtensor::registration"; impl Pallet { - pub fn register_neuron(netuid: u16, hotkey: &T::AccountId) -> u16 { + pub fn register_neuron(netuid: NetUid, hotkey: &T::AccountId) -> u16 { // Init param let neuron_uid: u16; let block_number: u64 = Self::get_current_block_as_u64(); @@ -64,7 +66,7 @@ impl Pallet { /// pub fn do_burned_registration( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, hotkey: T::AccountId, ) -> DispatchResult { // --- 1. Check that the caller has signed the transaction. (the coldkey of the pairing) @@ -78,7 +80,7 @@ impl Pallet { // --- 2. Ensure the passed network is valid. ensure!( - netuid != Self::get_root_netuid(), + !netuid.is_root(), Error::::RegistrationNotPermittedOnRootSubnet ); ensure!( @@ -139,7 +141,9 @@ impl Pallet { Self::remove_balance_from_coldkey_account(&coldkey, registration_cost)?; // Tokens are swapped and then burned. - let burned_alpha: u64 = Self::swap_tao_for_alpha(netuid, actual_burn_amount); + let burned_alpha: u64 = + Self::swap_tao_for_alpha(netuid, actual_burn_amount, T::SwapInterface::max_price())? + .amount_paid_out; SubnetAlphaOut::::mutate(netuid, |total| *total = total.saturating_sub(burned_alpha)); // Actually perform the registration. @@ -213,7 +217,7 @@ impl Pallet { /// pub fn do_registration( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, block_number: u64, nonce: u64, work: Vec, @@ -237,7 +241,7 @@ impl Pallet { // --- 2. Ensure the passed network is valid. ensure!( - netuid != Self::get_root_netuid(), + !netuid.is_root(), Error::::RegistrationNotPermittedOnRootSubnet ); ensure!( @@ -406,7 +410,7 @@ impl Pallet { /// If all neurons are in immunity period, the neuron with the lowest pruning score is pruned. If there is a tie for /// the lowest pruning score, the immune neuron registered earliest is pruned. /// Ties for earliest registration are broken by the neuron with the lowest uid. - pub fn get_neuron_to_prune(netuid: u16) -> u16 { + pub fn get_neuron_to_prune(netuid: NetUid) -> u16 { let mut min_score: u16 = u16::MAX; let mut min_score_in_immunity: u16 = u16::MAX; let mut earliest_registration: u64 = u64::MAX; @@ -481,7 +485,7 @@ impl Pallet { /// was too high. pub fn hash_meets_difficulty(hash: &H256, difficulty: U256) -> bool { let bytes: &[u8] = hash.as_bytes(); - let num_hash: U256 = U256::from(bytes); + let num_hash: U256 = U256::from_little_endian(bytes); let (value, overflowed) = num_hash.overflowing_mul(difficulty); log::trace!( @@ -584,7 +588,7 @@ impl Pallet { /// Helper function for creating nonce and work. pub fn create_work_for_block_number( - netuid: u16, + netuid: NetUid, block_number: u64, start_nonce: u64, hotkey: &T::AccountId, diff --git a/pallets/subtensor/src/subnets/serving.rs b/pallets/subtensor/src/subnets/serving.rs index c8c89bc011..ae1c97cc7c 100644 --- a/pallets/subtensor/src/subnets/serving.rs +++ b/pallets/subtensor/src/subnets/serving.rs @@ -1,4 +1,5 @@ use super::*; +use subtensor_runtime_common::NetUid; impl Pallet { /// ---- The implementation for the extrinsic serve_axon which sets the ip endpoint information for a uid on a network. @@ -56,7 +57,7 @@ impl Pallet { /// pub fn do_serve_axon( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -160,7 +161,7 @@ impl Pallet { /// pub fn do_serve_prometheus( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -172,7 +173,7 @@ impl Pallet { // Check the ip signature validity. ensure!(Self::is_valid_ip_type(ip_type), Error::::InvalidIpType); ensure!( - Self::is_valid_ip_address(ip_type, ip), + Self::is_valid_ip_address(ip_type, ip, false), Error::::InvalidIpAddress ); @@ -220,7 +221,7 @@ impl Pallet { *********************************/ pub fn axon_passes_rate_limit( - netuid: u16, + netuid: NetUid, prev_axon_info: &AxonInfoOf, current_block: u64, ) -> bool { @@ -230,7 +231,7 @@ impl Pallet { } pub fn prometheus_passes_rate_limit( - netuid: u16, + netuid: NetUid, prev_prometheus_info: &PrometheusInfoOf, current_block: u64, ) -> bool { @@ -239,7 +240,7 @@ impl Pallet { rate_limit == 0 || last_serve == 0 || current_block.saturating_sub(last_serve) >= rate_limit } - pub fn get_axon_info(netuid: u16, hotkey: &T::AccountId) -> AxonInfoOf { + pub fn get_axon_info(netuid: NetUid, hotkey: &T::AccountId) -> AxonInfoOf { if let Some(axons) = Axons::::get(netuid, hotkey) { axons } else { @@ -256,7 +257,7 @@ impl Pallet { } } - pub fn get_prometheus_info(netuid: u16, hotkey: &T::AccountId) -> PrometheusInfoOf { + pub fn get_prometheus_info(netuid: NetUid, hotkey: &T::AccountId) -> PrometheusInfoOf { if let Some(prometheus) = Prometheus::::get(netuid, hotkey) { prometheus } else { @@ -276,17 +277,11 @@ impl Pallet { } // @todo (Parallax 2-1-2021) : Implement exclusion of private IP ranges - pub fn is_valid_ip_address(ip_type: u8, addr: u128) -> bool { - if !Self::is_valid_ip_type(ip_type) { - return false; - } - if addr == 0 { + pub fn is_valid_ip_address(ip_type: u8, addr: u128, allow_zero: bool) -> bool { + if !allow_zero && addr == 0 { return false; } if ip_type == 4 { - if addr == 0 { - return false; - } if addr >= u32::MAX as u128 { return false; } @@ -295,9 +290,6 @@ impl Pallet { } // Localhost } if ip_type == 6 { - if addr == 0x0 { - return false; - } if addr == u128::MAX { return false; } @@ -328,7 +320,7 @@ impl Pallet { pub fn validate_serve_axon( hotkey_id: &T::AccountId, - netuid: u16, + netuid: NetUid, version: u32, ip: u128, port: u16, @@ -346,7 +338,8 @@ impl Pallet { // Check the ip signature validity. ensure!(Self::is_valid_ip_type(ip_type), Error::::InvalidIpType); ensure!( - Self::is_valid_ip_address(ip_type, ip), + // allow axon to be served with a zero ip address for testing purposes + Self::is_valid_ip_address(ip_type, ip, true), Error::::InvalidIpAddress ); diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index b122bfa049..db3e319959 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -1,19 +1,8 @@ use super::*; -use frame_support::IterableStorageMap; use sp_core::Get; +use subtensor_runtime_common::NetUid; impl Pallet { - /// Retrieves the unique identifier (UID) for the root network. - /// - /// The root network is a special case and has a fixed UID of 0. - /// - /// # Returns: - /// * 'u16': The UID for the root network. - /// - pub fn get_root_netuid() -> u16 { - 0 - } - /// Fetches the total count of subnets. /// /// This function retrieves the total number of subnets present on the chain. @@ -32,7 +21,7 @@ impl Pallet { /// # Returns: /// * 'bool': Whether the subnet exists. /// - pub fn if_subnet_exist(netuid: u16) -> bool { + pub fn if_subnet_exist(netuid: NetUid) -> bool { NetworksAdded::::get(netuid) } @@ -44,8 +33,8 @@ impl Pallet { /// # Returns: /// * 'Vec': Netuids of all subnets. /// - pub fn get_all_subnet_netuids() -> Vec { - as IterableStorageMap>::iter() + pub fn get_all_subnet_netuids() -> Vec { + NetworksAdded::::iter() .map(|(netuid, _)| netuid) .collect() } @@ -61,7 +50,7 @@ impl Pallet { /// # Returns: /// * 'u16': The subnet mechanism /// - pub fn get_subnet_mechanism(netuid: u16) -> u16 { + pub fn get_subnet_mechanism(netuid: NetUid) -> u16 { SubnetMechanism::::get(netuid) } @@ -72,14 +61,14 @@ impl Pallet { /// /// # Returns /// * `u16` - The next available mechanism ID. - pub fn get_next_netuid() -> u16 { - let mut next_netuid = 1; // do not allow creation of root - let netuids: Vec = Self::get_all_subnet_netuids(); + pub fn get_next_netuid() -> NetUid { + let mut next_netuid = NetUid::from(1); // do not allow creation of root + let netuids = Self::get_all_subnet_netuids(); loop { if !netuids.contains(&next_netuid) { break next_netuid; } - next_netuid = next_netuid.saturating_add(1); + next_netuid = next_netuid.next(); } } @@ -103,7 +92,7 @@ impl Pallet { /// # Returns /// /// * `bool` - `true` if registrations are allowed for the subnet, `false` otherwise. - pub fn is_registration_allowed(netuid: u16) -> bool { + pub fn is_registration_allowed(netuid: NetUid) -> bool { Self::get_subnet_hyperparams(netuid) .map(|params| params.registration_allowed) .unwrap_or(false) @@ -113,7 +102,7 @@ impl Pallet { /// /// # Args: /// * 'origin': ('T::RuntimeOrigin'): The calling origin. Must be signed. - /// * `identity` (`Option`): Optional identity to be associated with the new subnetwork. + /// * `identity` (`Option`): Optional identity to be associated with the new subnetwork. /// /// # Event: /// * 'NetworkAdded': Emitted when a new network is successfully added. @@ -129,7 +118,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: &T::AccountId, mechid: u16, - identity: Option, + identity: Option, ) -> DispatchResult { // --- 1. Ensure the caller is a signed user. let coldkey = ensure_signed(origin)?; @@ -160,7 +149,7 @@ impl Pallet { ); // --- 5. Determine the netuid to register. - let netuid_to_register: u16 = Self::get_next_netuid(); + let netuid_to_register = Self::get_next_netuid(); // --- 6. Perform the lock operation. let actual_tao_lock_amount: u64 = @@ -228,7 +217,7 @@ impl Pallet { Error::::InvalidIdentity ); - SubnetIdentitiesV2::::insert(netuid_to_register, identity_value); + SubnetIdentitiesV3::::insert(netuid_to_register, identity_value); Self::deposit_event(Event::SubnetIdentitySet(netuid_to_register)); } @@ -245,7 +234,7 @@ impl Pallet { } /// Sets initial and custom parameters for a new network. - pub fn init_new_network(netuid: u16, tempo: u16) { + pub fn init_new_network(netuid: NetUid, tempo: u16) { // --- 1. Set network to 0 size. SubnetworkN::::insert(netuid, 0); @@ -340,7 +329,7 @@ impl Pallet { /// # Returns /// /// * `DispatchResult`: A result indicating the success or failure of the operation. - pub fn do_start_call(origin: T::RuntimeOrigin, netuid: u16) -> DispatchResult { + pub fn do_start_call(origin: T::RuntimeOrigin, netuid: NetUid) -> DispatchResult { ensure!( Self::if_subnet_exist(netuid), Error::::SubNetworkDoesNotExist @@ -402,7 +391,7 @@ impl Pallet { /// This function is rate-limited to one call per subnet per interval (e.g., one week). pub fn do_set_sn_owner_hotkey( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, hotkey: &T::AccountId, ) -> DispatchResult { // Ensure the caller is either root or subnet owner. @@ -437,7 +426,7 @@ impl Pallet { Ok(()) } - pub fn is_valid_subnet_for_emission(netuid: u16) -> bool { + pub fn is_valid_subnet_for_emission(netuid: NetUid) -> bool { FirstEmissionBlockNumber::::get(netuid).is_some() } } diff --git a/pallets/subtensor/src/subnets/symbols.rs b/pallets/subtensor/src/subnets/symbols.rs index 1aae9c3a0c..bd88839a6b 100644 --- a/pallets/subtensor/src/subnets/symbols.rs +++ b/pallets/subtensor/src/subnets/symbols.rs @@ -1,9 +1,10 @@ use super::*; +use subtensor_runtime_common::NetUid; /// Returns the Unicode symbol as a Vec for a given netuid. impl Pallet { - pub fn get_name_for_subnet(netuid: u16) -> Vec { - SubnetIdentitiesV2::::try_get(netuid) + pub fn get_name_for_subnet(netuid: NetUid) -> Vec { + SubnetIdentitiesV3::::try_get(netuid) .and_then(|identity| { if !identity.subnet_name.is_empty() { Ok(identity.subnet_name) @@ -12,7 +13,7 @@ impl Pallet { } }) .unwrap_or_else(|_| { - match netuid { + match u16::from(netuid) { 0 => b"root".to_vec(), // Τ (Upper case Tau) 1 => b"apex".to_vec(), // α (Alpha) 2 => b"omron".to_vec(), // β (Beta) @@ -457,8 +458,8 @@ impl Pallet { }) } - pub fn get_symbol_for_subnet(netuid: u16) -> Vec { - match netuid { + pub fn get_symbol_for_subnet(netuid: NetUid) -> Vec { + match u16::from(netuid) { // Greek Alphabet (Lowercase) 0 => b"\xCE\xA4".to_vec(), // Τ (Upper case Tau) 1 => b"\xCE\xB1".to_vec(), // α (Alpha) diff --git a/pallets/subtensor/src/subnets/uids.rs b/pallets/subtensor/src/subnets/uids.rs index c97252677c..fa25b0b9ca 100644 --- a/pallets/subtensor/src/subnets/uids.rs +++ b/pallets/subtensor/src/subnets/uids.rs @@ -1,10 +1,11 @@ use super::*; use frame_support::storage::IterableStorageDoubleMap; use sp_std::vec; +use subtensor_runtime_common::NetUid; impl Pallet { /// Returns the number of filled slots on a network. - pub fn get_subnetwork_n(netuid: u16) -> u16 { + pub fn get_subnetwork_n(netuid: NetUid) -> u16 { SubnetworkN::::get(netuid) } @@ -16,7 +17,7 @@ impl Pallet { } /// Resets the trust, emission, consensus, incentive, dividends of the neuron to default - pub fn clear_neuron(netuid: u16, neuron_uid: u16) { + pub fn clear_neuron(netuid: NetUid, neuron_uid: u16) { let neuron_index: usize = neuron_uid.into(); Emission::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); Trust::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); @@ -28,7 +29,7 @@ impl Pallet { /// Replace the neuron under this uid. pub fn replace_neuron( - netuid: u16, + netuid: NetUid, uid_to_replace: u16, new_hotkey: &T::AccountId, block_number: u64, @@ -82,7 +83,7 @@ impl Pallet { } /// Appends the uid to the network. - pub fn append_neuron(netuid: u16, new_hotkey: &T::AccountId, block_number: u64) { + pub fn append_neuron(netuid: NetUid, new_hotkey: &T::AccountId, block_number: u64) { // 1. Get the next uid. This is always equal to subnetwork_n. let next_uid: u16 = Self::get_subnetwork_n(netuid); log::debug!( @@ -117,20 +118,20 @@ impl Pallet { /// Returns true if the uid is set on the network. /// - pub fn is_uid_exist_on_network(netuid: u16, uid: u16) -> bool { + pub fn is_uid_exist_on_network(netuid: NetUid, uid: u16) -> bool { Keys::::contains_key(netuid, uid) } /// Returns true if the hotkey holds a slot on the network. /// - pub fn is_hotkey_registered_on_network(netuid: u16, hotkey: &T::AccountId) -> bool { + pub fn is_hotkey_registered_on_network(netuid: NetUid, hotkey: &T::AccountId) -> bool { Uids::::contains_key(netuid, hotkey) } /// Returs the hotkey under the network uid as a Result. Ok if the uid is taken. /// pub fn get_hotkey_for_net_and_uid( - netuid: u16, + netuid: NetUid, neuron_uid: u16, ) -> Result { Keys::::try_get(netuid, neuron_uid) @@ -140,7 +141,7 @@ impl Pallet { /// Returns the uid of the hotkey in the network as a Result. Ok if the hotkey has a slot. /// pub fn get_uid_for_net_and_hotkey( - netuid: u16, + netuid: NetUid, hotkey: &T::AccountId, ) -> Result { Uids::::try_get(netuid, hotkey) @@ -149,7 +150,7 @@ impl Pallet { /// Returns the stake of the uid on network or 0 if it doesnt exist. /// - pub fn get_stake_for_uid_and_subnetwork(netuid: u16, neuron_uid: u16) -> u64 { + pub fn get_stake_for_uid_and_subnetwork(netuid: NetUid, neuron_uid: u16) -> u64 { if let Ok(hotkey) = Self::get_hotkey_for_net_and_uid(netuid, neuron_uid) { Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid) } else { @@ -159,12 +160,13 @@ impl Pallet { /// Return a list of all networks a hotkey is registered on. /// - pub fn get_registered_networks_for_hotkey(hotkey: &T::AccountId) -> Vec { - let mut all_networks: Vec = vec![]; - for (network, is_registered) in - as IterableStorageDoubleMap>::iter_prefix( - hotkey, - ) + pub fn get_registered_networks_for_hotkey(hotkey: &T::AccountId) -> Vec { + let mut all_networks: Vec = vec![]; + for (network, is_registered) in as IterableStorageDoubleMap< + T::AccountId, + NetUid, + bool, + >>::iter_prefix(hotkey) { if is_registered { all_networks.push(network) @@ -176,10 +178,11 @@ impl Pallet { /// Return true if a hotkey is registered on any network. /// pub fn is_hotkey_registered_on_any_network(hotkey: &T::AccountId) -> bool { - for (_, is_registered) in - as IterableStorageDoubleMap>::iter_prefix( - hotkey, - ) + for (_, is_registered) in as IterableStorageDoubleMap< + T::AccountId, + NetUid, + bool, + >>::iter_prefix(hotkey) { if is_registered { return true; @@ -187,4 +190,10 @@ impl Pallet { } false } + + /// Return true if a hotkey is registered on specific network. + /// + pub fn is_hotkey_registered_on_specific_network(hotkey: &T::AccountId, netuid: NetUid) -> bool { + IsNetworkMember::::contains_key(hotkey, netuid) + } } diff --git a/pallets/subtensor/src/subnets/weights.rs b/pallets/subtensor/src/subnets/weights.rs index ec6c9949bc..427846938a 100644 --- a/pallets/subtensor/src/subnets/weights.rs +++ b/pallets/subtensor/src/subnets/weights.rs @@ -8,6 +8,7 @@ use sp_runtime::{ traits::{BlakeTwo256, Hash}, }; use sp_std::{collections::vec_deque::VecDeque, vec}; +use subtensor_runtime_common::NetUid; impl Pallet { /// ---- The implementation for committing weight hashes. @@ -40,7 +41,7 @@ impl Pallet { /// - Emitted upon successfully storing the weight hash. pub fn do_commit_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, commit_hash: H256, ) -> DispatchResult { // 1. Verify the caller's signature (hotkey). @@ -138,7 +139,7 @@ impl Pallet { /// pub fn do_batch_commit_weights( origin: T::RuntimeOrigin, - netuids: Vec>, + netuids: Vec>, commit_hashes: Vec, ) -> dispatch::DispatchResult { // --- 1. Check the caller's signature. This is the hotkey of a registered account. @@ -228,7 +229,7 @@ impl Pallet { /// - Emitted upon successfully storing the weight hash. pub fn do_commit_crv3_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, commit: BoundedVec>, reveal_round: u64, ) -> DispatchResult { @@ -338,7 +339,7 @@ impl Pallet { /// - The revealed hash does not match any committed hash. pub fn do_reveal_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, uids: Vec, values: Vec, salt: Vec, @@ -479,7 +480,7 @@ impl Pallet { /// - The input vectors are of mismatched lengths. pub fn do_batch_reveal_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, uids_list: Vec>, values_list: Vec>, salts_list: Vec>, @@ -675,7 +676,7 @@ impl Pallet { /// pub fn do_set_weights( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, uids: Vec, values: Vec, version_key: u64, @@ -691,10 +692,7 @@ impl Pallet { ); // --- Check that the netuid is not the root network. - ensure!( - netuid != Self::get_root_netuid(), - Error::::CanNotSetRootNetworkWeights - ); + ensure!(!netuid.is_root(), Error::::CanNotSetRootNetworkWeights); // --- 2. Check that the length of uid list and value list are equal for this network. ensure!( @@ -829,7 +827,7 @@ impl Pallet { /// pub fn do_batch_set_weights( origin: T::RuntimeOrigin, - netuids: Vec>, + netuids: Vec>, weights: Vec, Compact)>>, version_keys: Vec>, ) -> dispatch::DispatchResult { @@ -901,7 +899,7 @@ impl Pallet { /// Returns true if version_key is up-to-date. /// - pub fn check_version_key(netuid: u16, version_key: u64) -> bool { + pub fn check_version_key(netuid: NetUid, version_key: u64) -> bool { let network_version_key: u64 = WeightsVersionKey::::get(netuid); log::debug!( "check_version_key( network_version_key:{:?}, version_key:{:?} )", @@ -913,7 +911,7 @@ impl Pallet { /// Checks if the neuron has set weights within the weights_set_rate_limit. /// - pub fn check_rate_limit(netuid: u16, neuron_uid: u16, current_block: u64) -> bool { + pub fn check_rate_limit(netuid: NetUid, neuron_uid: u16, current_block: u64) -> bool { if Self::is_uid_exist_on_network(netuid, neuron_uid) { // --- 1. Ensure that the diff between current and last_set weights is greater than limit. let last_set_weights: u64 = Self::get_last_update_for_uid(netuid, neuron_uid); @@ -928,7 +926,7 @@ impl Pallet { } /// Checks for any invalid uids on this network. - pub fn contains_invalid_uids(netuid: u16, uids: &[u16]) -> bool { + pub fn contains_invalid_uids(netuid: NetUid, uids: &[u16]) -> bool { for uid in uids { if !Self::is_uid_exist_on_network(netuid, *uid) { log::debug!( @@ -960,7 +958,7 @@ impl Pallet { } /// Returns True if setting self-weight or has validator permit. - pub fn check_validator_permit(netuid: u16, uid: u16, uids: &[u16], weights: &[u16]) -> bool { + pub fn check_validator_permit(netuid: NetUid, uid: u16, uids: &[u16], weights: &[u16]) -> bool { // Check self weight. Allowed to set single value for self weight. if Self::is_self_weight(uid, uids, weights) { return true; @@ -970,7 +968,7 @@ impl Pallet { } /// Returns True if the uids and weights are have a valid length for uid on network. - pub fn check_length(netuid: u16, uid: u16, uids: &[u16], weights: &[u16]) -> bool { + pub fn check_length(netuid: NetUid, uid: u16, uids: &[u16], weights: &[u16]) -> bool { let subnet_n: usize = Self::get_subnetwork_n(netuid) as usize; let min_allowed_length: usize = Self::get_min_allowed_weights(netuid) as usize; let min_allowed: usize = { @@ -983,7 +981,7 @@ impl Pallet { // Check self weight. Allowed to set single value for self weight. // Or check that this is the root netuid. - if netuid != Self::get_root_netuid() && Self::is_self_weight(uid, uids, weights) { + if !netuid.is_root() && Self::is_self_weight(uid, uids, weights) { return true; } // Check if number of weights exceeds min. @@ -1008,7 +1006,7 @@ impl Pallet { } /// Returns False if the weights exceed the max_weight_limit for this network. - pub fn max_weight_limited(netuid: u16, uid: u16, uids: &[u16], weights: &[u16]) -> bool { + pub fn max_weight_limited(netuid: NetUid, uid: u16, uids: &[u16], weights: &[u16]) -> bool { // Allow self weights to exceed max weight limit. if Self::is_self_weight(uid, uids, weights) { return true; @@ -1039,13 +1037,13 @@ impl Pallet { } /// Returns False is the number of uids exceeds the allowed number of uids for this network. - pub fn check_len_uids_within_allowed(netuid: u16, uids: &[u16]) -> bool { + pub fn check_len_uids_within_allowed(netuid: NetUid, uids: &[u16]) -> bool { let subnetwork_n: u16 = Self::get_subnetwork_n(netuid); // we should expect at most subnetwork_n uids. uids.len() <= subnetwork_n as usize } - pub fn is_reveal_block_range(netuid: u16, commit_block: u64) -> bool { + pub fn is_reveal_block_range(netuid: NetUid, commit_block: u64) -> bool { let current_block: u64 = Self::get_current_block_as_u64(); let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); let current_epoch: u64 = Self::get_epoch_index(netuid, current_block); @@ -1055,16 +1053,16 @@ impl Pallet { current_epoch == commit_epoch.saturating_add(reveal_period) } - pub fn get_epoch_index(netuid: u16, block_number: u64) -> u64 { + pub fn get_epoch_index(netuid: NetUid, block_number: u64) -> u64 { let tempo: u64 = Self::get_tempo(netuid) as u64; let tempo_plus_one: u64 = tempo.saturating_add(1); - let netuid_plus_one: u64 = (netuid as u64).saturating_add(1); + let netuid_plus_one: u64 = (u16::from(netuid) as u64).saturating_add(1); let block_with_offset: u64 = block_number.saturating_add(netuid_plus_one); block_with_offset.checked_div(tempo_plus_one).unwrap_or(0) } - pub fn is_commit_expired(netuid: u16, commit_block: u64) -> bool { + pub fn is_commit_expired(netuid: NetUid, commit_block: u64) -> bool { let current_block: u64 = Self::get_current_block_as_u64(); let current_epoch: u64 = Self::get_epoch_index(netuid, current_block); let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); @@ -1073,11 +1071,11 @@ impl Pallet { current_epoch > commit_epoch.saturating_add(reveal_period) } - pub fn get_reveal_blocks(netuid: u16, commit_block: u64) -> (u64, u64) { + pub fn get_reveal_blocks(netuid: NetUid, commit_block: u64) -> (u64, u64) { let reveal_period: u64 = Self::get_reveal_period(netuid); let tempo: u64 = Self::get_tempo(netuid) as u64; let tempo_plus_one: u64 = tempo.saturating_add(1); - let netuid_plus_one: u64 = (netuid as u64).saturating_add(1); + let netuid_plus_one: u64 = (u16::from(netuid) as u64).saturating_add(1); let commit_epoch: u64 = Self::get_epoch_index(netuid, commit_block); let reveal_epoch: u64 = commit_epoch.saturating_add(reveal_period); @@ -1090,11 +1088,11 @@ impl Pallet { (first_reveal_block, last_reveal_block) } - pub fn set_reveal_period(netuid: u16, reveal_period: u64) { + pub fn set_reveal_period(netuid: NetUid, reveal_period: u64) { RevealPeriodEpochs::::insert(netuid, reveal_period); Self::deposit_event(Event::CommitRevealPeriodsSet(netuid, reveal_period)); } - pub fn get_reveal_period(netuid: u16) -> u64 { + pub fn get_reveal_period(netuid: NetUid) -> u64 { RevealPeriodEpochs::::get(netuid) } } diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index 54c7c01d8e..9cb79a1002 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -2,7 +2,6 @@ use super::*; use frame_support::weights::Weight; use sp_core::Get; use substrate_fixed::types::U64F64; - impl Pallet { /// Swaps the hotkey of a coldkey account. /// @@ -11,6 +10,7 @@ impl Pallet { /// * `origin` - The origin of the transaction, and also the coldkey account. /// * `old_hotkey` - The old hotkey to be swapped. /// * `new_hotkey` - The new hotkey to replace the old one. + /// * `netuid` - The hotkey swap in a subnet or all subnets. /// /// # Returns /// @@ -27,76 +27,98 @@ impl Pallet { origin: T::RuntimeOrigin, old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, + netuid: Option, ) -> DispatchResultWithPostInfo { // 1. Ensure the origin is signed and get the coldkey let coldkey = ensure_signed(origin)?; - // 2. Initialize the weight for this operation - let mut weight = T::DbWeight::get().reads(2); - - // 3. Ensure the new hotkey is different from the old one - ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); - - // 4. Ensure the new hotkey is not already registered on any network - ensure!( - !Self::is_hotkey_registered_on_any_network(new_hotkey), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - - // 5. Update the weight for the checks above - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); - - // 6. Ensure the coldkey owns the old hotkey + // 2. Ensure the coldkey owns the old hotkey ensure!( Self::coldkey_owns_hotkey(&coldkey, old_hotkey), Error::::NonAssociatedColdKey ); - // 7. Get the current block number + // 3. Initialize the weight for this operation + let mut weight = T::DbWeight::get().reads(2); + + // 4. Ensure the new hotkey is different from the old one + ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); + + // 5. Get the current block number let block: u64 = Self::get_current_block_as_u64(); - // 8. Ensure the transaction rate limit is not exceeded + // 6. Ensure the transaction rate limit is not exceeded ensure!( !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), Error::::HotKeySetTxRateLimitExceeded ); - // 9. Update the weight for reading the total networks - weight.saturating_accrue( - T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), + weight.saturating_accrue(T::DbWeight::get().reads(2)); + + // 7. Ensure the new hotkey is not already registered on any network + ensure!( + !Self::is_hotkey_registered_on_any_network(new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet ); - // 10. Get the cost for swapping the key + // 8. Swap LastTxBlock + // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. + let last_tx_block: u64 = LastTxBlock::::get(old_hotkey); + LastTxBlock::::insert(new_hotkey, last_tx_block); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 9. Swap LastTxBlockDelegateTake + // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. + let last_tx_block_delegate_take: u64 = LastTxBlockDelegateTake::::get(old_hotkey); + LastTxBlockDelegateTake::::insert(new_hotkey, last_tx_block_delegate_take); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 10. Swap LastTxBlockChildKeyTake + // LastTxBlockChildKeyTake( hotkey ) --> u64 -- the last transaction block for the hotkey child key take. + let last_tx_block_child_key_take: u64 = LastTxBlockChildKeyTake::::get(old_hotkey); + LastTxBlockChildKeyTake::::insert(new_hotkey, last_tx_block_child_key_take); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 11. fork for swap hotkey on a specific subnet case after do the common check + if let Some(netuid) = netuid { + return Self::swap_hotkey_on_subnet(&coldkey, old_hotkey, new_hotkey, netuid, weight); + }; + + // Start to do everything for swap hotkey on all subnets case + // 12. Get the cost for swapping the key let swap_cost = Self::get_key_swap_cost(); log::debug!("Swap cost: {:?}", swap_cost); - // 11. Ensure the coldkey has enough balance to pay for the swap + // 13. Ensure the coldkey has enough balance to pay for the swap ensure!( Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), Error::::NotEnoughBalanceToPaySwapHotKey ); - // 12. Remove the swap cost from the coldkey's account + weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 0)); + + // 14. Remove the swap cost from the coldkey's account let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; - // 13. Burn the tokens + // 18. Burn the tokens Self::burn_tokens(actual_burn_amount); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); - // 14. Perform the hotkey swap - let _ = Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); + // 19. Perform the hotkey swap + Self::perform_hotkey_swap_on_all_subnets(old_hotkey, new_hotkey, &coldkey, &mut weight)?; - // 15. Update the last transaction block for the coldkey + // 20. Update the last transaction block for the coldkey Self::set_last_tx_block(&coldkey, block); weight.saturating_accrue(T::DbWeight::get().writes(1)); - // 16. Emit an event for the hotkey swap + // 21. Emit an event for the hotkey swap Self::deposit_event(Event::HotkeySwapped { coldkey, old_hotkey: old_hotkey.clone(), new_hotkey: new_hotkey.clone(), }); - // 17. Return the weight of the operation + // 22. Return the weight of the operation Ok(Some(weight).into()) } @@ -134,87 +156,65 @@ impl Pallet { /// # Note /// This function performs extensive storage reads and writes, which can be computationally expensive. /// The accumulated weight should be carefully considered in the context of block limits. - pub fn perform_hotkey_swap( + pub fn perform_hotkey_swap_on_all_subnets( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight, ) -> DispatchResult { - // 1. Swap owner. + // 1. keep the old hotkey alpha values for the case where hotkey staked by multiple coldkeys. + let old_alpha_values: Vec<((T::AccountId, NetUid), U64F64)> = + Alpha::::iter_prefix((old_hotkey,)).collect(); + weight.saturating_accrue(T::DbWeight::get().reads(old_alpha_values.len() as u64)); + + // 2. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. Owner::::remove(old_hotkey); Owner::::insert(new_hotkey, coldkey.clone()); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - // 2. Swap OwnedHotkeys. + // 3. Swap OwnedHotkeys. // OwnedHotkeys( coldkey ) -> Vec -- the hotkeys that the coldkey owns. let mut hotkeys = OwnedHotkeys::::get(coldkey); // Add the new key if needed. if !hotkeys.contains(new_hotkey) { hotkeys.push(new_hotkey.clone()); } - // Remove the old key. + + // 4. Remove the old key. hotkeys.retain(|hk| *hk != *old_hotkey); OwnedHotkeys::::insert(coldkey, hotkeys); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - // 3. Swap total hotkey alpha for all subnets it exists on. - // TotalHotkeyAlpha( hotkey, netuid ) -> alpha -- the total alpha that the hotkey has on a specific subnet. - TotalHotkeyAlpha::::iter_prefix(old_hotkey) - .drain() - .for_each(|(netuid, old_alpha)| { - let new_total_hotkey_alpha = TotalHotkeyAlpha::::get(new_hotkey, netuid); - TotalHotkeyAlpha::::insert( - new_hotkey, - netuid, - old_alpha.saturating_add(new_total_hotkey_alpha), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - }); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - // 4. Swap total hotkey shares on all subnets it exists on. - // TotalHotkeyShares( hotkey, netuid ) -> alpha -- the total alpha that the hotkey has on a specific subnet. - TotalHotkeyShares::::iter_prefix(old_hotkey) - .drain() - .for_each(|(netuid, old_shares)| { - let new_total_hotkey_shares = TotalHotkeyShares::::get(new_hotkey, netuid); - TotalHotkeyShares::::insert( - new_hotkey, - netuid, - old_shares.saturating_add(new_total_hotkey_shares), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - }); + // 5. execute the hotkey swap on all subnets + for netuid in Self::get_all_subnet_netuids() { + Self::perform_hotkey_swap_on_one_subnet(old_hotkey, new_hotkey, weight, netuid); + } - // 5. Swap LastTxBlock + // 6. Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. - let last_tx_block: u64 = LastTxBlock::::get(old_hotkey); LastTxBlock::::remove(old_hotkey); - LastTxBlock::::insert(new_hotkey, last_tx_block); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 6. Swap LastTxBlockDelegateTake + // 7. Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. - let last_tx_block_delegate_take: u64 = LastTxBlockDelegateTake::::get(old_hotkey); LastTxBlockDelegateTake::::remove(old_hotkey); - LastTxBlockDelegateTake::::insert(new_hotkey, last_tx_block_delegate_take); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 7. Swap LastTxBlockChildKeyTake + // 8. Swap LastTxBlockChildKeyTake // LastTxBlockChildKeyTake( hotkey ) --> u64 -- the last transaction block for the hotkey child key take. - let last_tx_block_child_key_take: u64 = LastTxBlockChildKeyTake::::get(old_hotkey); LastTxBlockChildKeyTake::::remove(old_hotkey); - LastTxBlockChildKeyTake::::insert(new_hotkey, last_tx_block_child_key_take); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 8. Swap Senate members. + // 9. Swap Senate members. // Senate( hotkey ) --> ? if T::SenateMembers::is_member(old_hotkey) { T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - // 9. Swap delegates. + // 10. Swap delegates. // Delegates( hotkey ) -> take value -- the hotkey delegate take value. if Delegates::::contains_key(old_hotkey) { let old_delegate_take = Delegates::::get(old_hotkey); @@ -223,270 +223,373 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); } - // 9. swap PendingHotkeyEmissionOnNetuid - // (DEPRECATED.) - - // 10. Swap all subnet specific info. - let all_netuids: Vec = Self::get_all_subnet_netuids(); - all_netuids.iter().for_each(|netuid| { - // 10.1 Remove the previous hotkey and insert the new hotkey from membership. - // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. - let is_network_member: bool = IsNetworkMember::::get(old_hotkey, netuid); - IsNetworkMember::::remove(old_hotkey, netuid); - IsNetworkMember::::insert(new_hotkey, netuid, is_network_member); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - - // 10.2 Swap Uids + Keys. - // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. - // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. - if is_network_member { - // 10.2.1 Swap the UIDS - if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { - Uids::::remove(netuid, old_hotkey); - Uids::::insert(netuid, new_hotkey, old_uid); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - - // 10.2.2 Swap the keys. - Keys::::insert(netuid, old_uid, new_hotkey.clone()); - weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + // 11. Alpha already update in perform_hotkey_swap_on_one_subnet + // Update the StakingHotkeys for the case where hotkey staked by multiple coldkeys. + for ((coldkey, _netuid), _alpha) in old_alpha_values { + // Swap StakingHotkeys. + // StakingHotkeys( coldkey ) --> Vec -- the hotkeys that the coldkey stakes. + let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if staking_hotkeys.contains(old_hotkey) { + staking_hotkeys.retain(|hk| *hk != *old_hotkey && *hk != *new_hotkey); + if !staking_hotkeys.contains(new_hotkey) { + staking_hotkeys.push(new_hotkey.clone()); } + StakingHotkeys::::insert(&coldkey, staking_hotkeys); + weight.saturating_accrue(T::DbWeight::get().writes(1)); } + } - // 10.3 Swap Prometheus. - // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. - if is_network_member { - if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { - Prometheus::::remove(netuid, old_hotkey); - Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } + // Return successful after swapping all the relevant terms. + Ok(()) + } + + pub fn swap_senate_member( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + Ok(()) + } + + fn swap_hotkey_on_subnet( + coldkey: &T::AccountId, + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid: NetUid, + init_weight: Weight, + ) -> DispatchResultWithPostInfo { + // 1. Ensure coldkey not swap hotkey too frequently + let mut weight: Weight = init_weight; + let block: u64 = Self::get_current_block_as_u64(); + let hotkey_swap_interval = T::HotkeySwapOnSubnetInterval::get(); + let last_hotkey_swap_block = LastHotkeySwapOnNetuid::::get(netuid, coldkey); + + ensure!( + last_hotkey_swap_block.saturating_add(hotkey_swap_interval) < block, + Error::::HotKeySwapOnSubnetIntervalNotPassed + ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(3, 0)); + + // 2. Ensure the hotkey not registered on the network before. + ensure!( + !Self::is_hotkey_registered_on_specific_network(new_hotkey, netuid), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); + + // 3. Get the cost for swapping the key on the subnet + let swap_cost = T::KeySwapOnSubnetCost::get(); + log::debug!("Swap cost in subnet {:?}: {:?}", netuid, swap_cost); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); + + // 4. Ensure the coldkey has enough balance to pay for the swap + ensure!( + Self::can_remove_balance_from_coldkey_account(coldkey, swap_cost), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + + // 5. Remove the swap cost from the coldkey's account + let actual_burn_amount = Self::remove_balance_from_coldkey_account(coldkey, swap_cost)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); + + // 6. Burn the tokens + Self::burn_tokens(actual_burn_amount); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 7. Swap owner. + // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. + // Owner::::remove(old_hotkey); + Owner::::insert(new_hotkey, coldkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 8. Swap OwnedHotkeys. + // OwnedHotkeys( coldkey ) -> Vec -- the hotkeys that the coldkey owns. + let mut hotkeys = OwnedHotkeys::::get(coldkey); + // Add the new key if needed. + if !hotkeys.contains(new_hotkey) { + hotkeys.push(new_hotkey.clone()); + OwnedHotkeys::::insert(coldkey, hotkeys); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + } + + // 9. Perform the hotkey swap + Self::perform_hotkey_swap_on_one_subnet(old_hotkey, new_hotkey, &mut weight, netuid); + + // 10. Update the last transaction block for the coldkey + Self::set_last_tx_block(coldkey, block); + LastHotkeySwapOnNetuid::::insert(netuid, coldkey, block); + weight.saturating_accrue(T::DbWeight::get().writes(2)); + + // 11. Emit an event for the hotkey swap + Self::deposit_event(Event::HotkeySwappedOnSubnet { + coldkey: coldkey.clone(), + old_hotkey: old_hotkey.clone(), + new_hotkey: new_hotkey.clone(), + netuid, + }); + + Ok(Some(weight).into()) + } + + // do hotkey swap public part for both swap all subnets and just swap one subnet + pub fn perform_hotkey_swap_on_one_subnet( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + netuid: NetUid, + ) { + // 1. Swap total hotkey alpha for all subnets it exists on. + // TotalHotkeyAlpha( hotkey, netuid ) -> alpha -- the total alpha that the hotkey has on a specific subnet. + let alpha = TotalHotkeyAlpha::::take(old_hotkey, netuid); + + TotalHotkeyAlpha::::mutate(new_hotkey, netuid, |value| { + *value = value.saturating_add(alpha) + }); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 2. Swap total hotkey shares on all subnets it exists on. + // TotalHotkeyShares( hotkey, netuid ) -> alpha -- the total alpha that the hotkey has on a specific subnet. + let share = TotalHotkeyShares::::take(old_hotkey, netuid); + // TotalHotkeyAlpha::::remove(old_hotkey, netuid); + TotalHotkeyShares::::mutate(new_hotkey, netuid, |value| { + *value = value.saturating_add(share) + }); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 3. Swap all subnet specific info. + + // 3.1 Remove the previous hotkey and insert the new hotkey from membership. + // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. + let is_network_member: bool = IsNetworkMember::::get(old_hotkey, netuid); + IsNetworkMember::::remove(old_hotkey, netuid); + IsNetworkMember::::insert(new_hotkey, netuid, is_network_member); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 3.2 Swap Uids + Keys. + // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. + // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. + if is_network_member { + // 3.2.1 Swap the UIDS + if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { + Uids::::remove(netuid, old_hotkey); + Uids::::insert(netuid, new_hotkey, old_uid); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 3.2.2 Swap the keys. + Keys::::insert(netuid, old_uid, new_hotkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); } + } - // 10.4. Swap axons. - // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. - if is_network_member { - if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { - Axons::::remove(netuid, old_hotkey); - Axons::::insert(netuid, new_hotkey, old_axon_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } + // 3.3 Swap Prometheus. + // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. + if is_network_member { + if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { + Prometheus::::remove(netuid, old_hotkey); + Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } + } - // 10.5 Swap WeightCommits - // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. - if is_network_member { - if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { - WeightCommits::::remove(netuid, old_hotkey); - WeightCommits::::insert(netuid, new_hotkey, old_weight_commits); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } + // 3.4. Swap axons. + // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. + if is_network_member { + if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { + Axons::::remove(netuid, old_hotkey); + Axons::::insert(netuid, new_hotkey, old_axon_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } + } - // 10.6. Swap the subnet loaded emission. - // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. - if is_network_member { - if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { - for emission in old_loaded_emission.iter_mut() { - if emission.0 == *old_hotkey { - emission.0 = new_hotkey.clone(); - } - } - LoadedEmission::::remove(netuid); - LoadedEmission::::insert(netuid, old_loaded_emission); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } + // 3.5 Swap WeightCommits + // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. + if is_network_member { + if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { + WeightCommits::::remove(netuid, old_hotkey); + WeightCommits::::insert(netuid, new_hotkey, old_weight_commits); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } + } - // 10.7. Swap neuron TLS certificates. - // NeuronCertificates( netuid, hotkey ) -> Vec -- the neuron certificate for the hotkey. - if is_network_member { - if let Ok(old_neuron_certificates) = - NeuronCertificates::::try_get(netuid, old_hotkey) - { - NeuronCertificates::::remove(netuid, old_hotkey); - NeuronCertificates::::insert(netuid, new_hotkey, old_neuron_certificates); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + // 3.6. Swap the subnet loaded emission. + // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. + if is_network_member { + if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { + for emission in old_loaded_emission.iter_mut() { + if emission.0 == *old_hotkey { + emission.0 = new_hotkey.clone(); + } } + LoadedEmission::::remove(netuid); + LoadedEmission::::insert(netuid, old_loaded_emission); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - }); - - // 11. Swap Alpha - // Alpha( hotkey, coldkey, netuid ) -> alpha - let old_alpha_values: Vec<((T::AccountId, u16), U64F64)> = - Alpha::::iter_prefix((old_hotkey,)).collect(); - // Clear the entire old prefix here. - let _ = Alpha::::clear_prefix((old_hotkey,), old_alpha_values.len() as u32, None); - weight.saturating_accrue(T::DbWeight::get().reads(old_alpha_values.len() as u64)); - weight.saturating_accrue(T::DbWeight::get().writes(old_alpha_values.len() as u64)); - - // Insert the new alpha values. - for ((coldkey, netuid), alpha) in old_alpha_values { - let new_alpha = Alpha::::get((new_hotkey, &coldkey, netuid)); - Alpha::::insert( - (new_hotkey, &coldkey, netuid), - new_alpha.saturating_add(alpha), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + } - // Swap StakingHotkeys. - // StakingHotkeys( coldkey ) --> Vec -- the hotkeys that the coldkey stakes. - let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if staking_hotkeys.contains(old_hotkey) { - staking_hotkeys.retain(|hk| *hk != *old_hotkey && *hk != *new_hotkey); - staking_hotkeys.push(new_hotkey.clone()); - StakingHotkeys::::insert(&coldkey, staking_hotkeys); - weight.saturating_accrue(T::DbWeight::get().writes(1)); + // 3.7. Swap neuron TLS certificates. + // NeuronCertificates( netuid, hotkey ) -> Vec -- the neuron certificate for the hotkey. + if is_network_member { + if let Ok(old_neuron_certificates) = + NeuronCertificates::::try_get(netuid, old_hotkey) + { + NeuronCertificates::::remove(netuid, old_hotkey); + NeuronCertificates::::insert(netuid, new_hotkey, old_neuron_certificates); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } - - // 12. Swap ChildKeys. + // 4. Swap ChildKeys. // ChildKeys( parent, netuid ) --> Vec<(proportion,child)> -- the child keys of the parent. - for netuid in Self::get_all_subnet_netuids() { - // Get the children of the old hotkey for this subnet - let my_children: Vec<(u64, T::AccountId)> = ChildKeys::::get(old_hotkey, netuid); - // Remove the old hotkey's child entries - ChildKeys::::remove(old_hotkey, netuid); - // Insert the same child entries for the new hotkey - ChildKeys::::insert(new_hotkey, netuid, my_children.clone()); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - for (_, child_key_i) in my_children { - // For each child, update their parent list - let mut child_parents: Vec<(u64, T::AccountId)> = - ParentKeys::::get(child_key_i.clone(), netuid); - for parent in child_parents.iter_mut() { - // If the parent is the old hotkey, replace it with the new hotkey - if parent.1 == *old_hotkey { - parent.1 = new_hotkey.clone(); - } + let my_children: Vec<(u64, T::AccountId)> = ChildKeys::::get(old_hotkey, netuid); + // Remove the old hotkey's child entries + ChildKeys::::remove(old_hotkey, netuid); + // Insert the same child entries for the new hotkey + ChildKeys::::insert(new_hotkey, netuid, my_children.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + for (_, child_key_i) in my_children { + // For each child, update their parent list + let mut child_parents: Vec<(u64, T::AccountId)> = + ParentKeys::::get(child_key_i.clone(), netuid); + for parent in child_parents.iter_mut() { + // If the parent is the old hotkey, replace it with the new hotkey + if parent.1 == *old_hotkey { + parent.1 = new_hotkey.clone(); } - // Update the child's parent list - ParentKeys::::insert(child_key_i, netuid, child_parents); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + // Update the child's parent list + ParentKeys::::insert(child_key_i, netuid, child_parents); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + // } - // 13. Swap ParentKeys. + // 5. Swap ParentKeys. // ParentKeys( child, netuid ) --> Vec<(proportion,parent)> -- the parent keys of the child. - for netuid in Self::get_all_subnet_netuids() { - // Get the parents of the old hotkey for this subnet - let parents: Vec<(u64, T::AccountId)> = ParentKeys::::get(old_hotkey, netuid); - // Remove the old hotkey's parent entries - ParentKeys::::remove(old_hotkey, netuid); - // Insert the same parent entries for the new hotkey - ParentKeys::::insert(new_hotkey, netuid, parents.clone()); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - for (_, parent_key_i) in parents { - // For each parent, update their children list - let mut parent_children: Vec<(u64, T::AccountId)> = - ChildKeys::::get(parent_key_i.clone(), netuid); - for child in parent_children.iter_mut() { - // If the child is the old hotkey, replace it with the new hotkey - if child.1 == *old_hotkey { - child.1 = new_hotkey.clone(); - } + let parents: Vec<(u64, T::AccountId)> = ParentKeys::::get(old_hotkey, netuid); + // Remove the old hotkey's parent entries + ParentKeys::::remove(old_hotkey, netuid); + // Insert the same parent entries for the new hotkey + ParentKeys::::insert(new_hotkey, netuid, parents.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + for (_, parent_key_i) in parents { + // For each parent, update their children list + let mut parent_children: Vec<(u64, T::AccountId)> = + ChildKeys::::get(parent_key_i.clone(), netuid); + for child in parent_children.iter_mut() { + // If the child is the old hotkey, replace it with the new hotkey + if child.1 == *old_hotkey { + child.1 = new_hotkey.clone(); } - // Update the parent's children list - ChildKeys::::insert(parent_key_i, netuid, parent_children); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + // Update the parent's children list + ChildKeys::::insert(parent_key_i, netuid, parent_children); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } - // 14. Swap PendingChildKeys. + // 6. Swap PendingChildKeys. // PendingChildKeys( netuid, parent ) --> Vec<(proportion,child), cool_down_block> - for netuid in Self::get_all_subnet_netuids() { + if PendingChildKeys::::contains_key(netuid, old_hotkey) { + let (children, cool_down_block) = PendingChildKeys::::get(netuid, old_hotkey); + PendingChildKeys::::remove(netuid, old_hotkey); + PendingChildKeys::::insert(netuid, new_hotkey, (children, cool_down_block)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // Also check for others with our hotkey as a child + for (hotkey, (children, cool_down_block)) in PendingChildKeys::::iter_prefix(netuid) { weight.saturating_accrue(T::DbWeight::get().reads(1)); - if PendingChildKeys::::contains_key(netuid, old_hotkey) { - let (children, cool_down_block) = PendingChildKeys::::get(netuid, old_hotkey); - PendingChildKeys::::remove(netuid, old_hotkey); - PendingChildKeys::::insert(netuid, new_hotkey, (children, cool_down_block)); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } - // Also check for others with our hotkey as a child - for (hotkey, (children, cool_down_block)) in PendingChildKeys::::iter_prefix(netuid) + if let Some(potential_idx) = + children.iter().position(|(_, child)| *child == *old_hotkey) { - weight.saturating_accrue(T::DbWeight::get().reads(1)); + let mut new_children = children.clone(); + let entry_to_remove = new_children.remove(potential_idx); + new_children.push((entry_to_remove.0, new_hotkey.clone())); // Keep the proportion. - if let Some(potential_idx) = - children.iter().position(|(_, child)| *child == *old_hotkey) - { - let mut new_children = children.clone(); - let entry_to_remove = new_children.remove(potential_idx); - new_children.push((entry_to_remove.0, new_hotkey.clone())); // Keep the proportion. - - PendingChildKeys::::remove(netuid, hotkey.clone()); - PendingChildKeys::::insert(netuid, hotkey, (new_children, cool_down_block)); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } + PendingChildKeys::::remove(netuid, hotkey.clone()); + PendingChildKeys::::insert(netuid, hotkey, (new_children, cool_down_block)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } - // 15. Swap SubnetOwnerHotkey + // 7. Swap SubnetOwnerHotkey // SubnetOwnerHotkey( netuid ) --> hotkey -- the hotkey that is the owner of the subnet. - for netuid in Self::get_all_subnet_netuids() { - if let Ok(old_subnet_owner_hotkey) = SubnetOwnerHotkey::::try_get(netuid) { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if old_subnet_owner_hotkey == *old_hotkey { - SubnetOwnerHotkey::::insert(netuid, new_hotkey); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } + if let Ok(old_subnet_owner_hotkey) = SubnetOwnerHotkey::::try_get(netuid) { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if old_subnet_owner_hotkey == *old_hotkey { + SubnetOwnerHotkey::::insert(netuid, new_hotkey); + weight.saturating_accrue(T::DbWeight::get().writes(1)); } } - // 16. Swap dividend records - TotalHotkeyAlphaLastEpoch::::iter_prefix(old_hotkey) - .drain() - .for_each(|(netuid, old_alpha)| { - // 16.1 Swap TotalHotkeyAlphaLastEpoch - let new_total_hotkey_alpha = - TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid); - TotalHotkeyAlphaLastEpoch::::insert( - new_hotkey, - netuid, - old_alpha.saturating_add(new_total_hotkey_alpha), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - - // 16.2 Swap AlphaDividendsPerSubnet - let old_hotkey_alpha_dividends = - AlphaDividendsPerSubnet::::get(netuid, old_hotkey); - let new_hotkey_alpha_dividends = - AlphaDividendsPerSubnet::::get(netuid, new_hotkey); - AlphaDividendsPerSubnet::::remove(netuid, old_hotkey); - AlphaDividendsPerSubnet::::insert( - netuid, - new_hotkey, - old_hotkey_alpha_dividends.saturating_add(new_hotkey_alpha_dividends), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - - // 16.3 Swap TaoDividendsPerSubnet - let old_hotkey_tao_dividends = TaoDividendsPerSubnet::::get(netuid, old_hotkey); - let new_hotkey_tao_dividends = TaoDividendsPerSubnet::::get(netuid, new_hotkey); - TaoDividendsPerSubnet::::remove(netuid, old_hotkey); - TaoDividendsPerSubnet::::insert( - netuid, - new_hotkey, - old_hotkey_tao_dividends.saturating_add(new_hotkey_tao_dividends), - ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - }); + // 8. Swap dividend records + // 8.1 Swap TotalHotkeyAlphaLastEpoch + let old_alpha = TotalHotkeyAlphaLastEpoch::::take(old_hotkey, netuid); + let new_total_hotkey_alpha = TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid); + TotalHotkeyAlphaLastEpoch::::insert( + new_hotkey, + netuid, + old_alpha.saturating_add(new_total_hotkey_alpha), + ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + + // 8.2 Swap AlphaDividendsPerSubnet + let old_hotkey_alpha_dividends = AlphaDividendsPerSubnet::::get(netuid, old_hotkey); + let new_hotkey_alpha_dividends = AlphaDividendsPerSubnet::::get(netuid, new_hotkey); + AlphaDividendsPerSubnet::::remove(netuid, old_hotkey); + AlphaDividendsPerSubnet::::insert( + netuid, + new_hotkey, + old_hotkey_alpha_dividends.saturating_add(new_hotkey_alpha_dividends), + ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + + // 8.3 Swap TaoDividendsPerSubnet + let old_hotkey_tao_dividends = TaoDividendsPerSubnet::::get(netuid, old_hotkey); + let new_hotkey_tao_dividends = TaoDividendsPerSubnet::::get(netuid, new_hotkey); + TaoDividendsPerSubnet::::remove(netuid, old_hotkey); + TaoDividendsPerSubnet::::insert( + netuid, + new_hotkey, + old_hotkey_tao_dividends.saturating_add(new_hotkey_tao_dividends), + ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - // Return successful after swapping all the relevant terms. - Ok(()) - } + // 9. Swap Alpha + // Alpha( hotkey, coldkey, netuid ) -> alpha + let old_alpha_values: Vec<((T::AccountId, NetUid), U64F64)> = + Alpha::::iter_prefix((old_hotkey,)).collect(); + weight.saturating_accrue(T::DbWeight::get().reads(old_alpha_values.len() as u64)); + weight.saturating_accrue(T::DbWeight::get().writes(old_alpha_values.len() as u64)); - pub fn swap_senate_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if T::SenateMembers::is_member(old_hotkey) { - T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + // Insert the new alpha values. + for ((coldkey, netuid_alpha), alpha) in old_alpha_values { + if netuid == netuid_alpha { + let new_alpha = Alpha::::take((new_hotkey, &coldkey, netuid)); + Alpha::::remove((old_hotkey, &coldkey, netuid)); + Alpha::::insert( + (new_hotkey, &coldkey, netuid), + alpha.saturating_add(new_alpha), + ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap StakingHotkeys. + // StakingHotkeys( coldkey ) --> Vec -- the hotkeys that the coldkey stakes. + let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if staking_hotkeys.contains(old_hotkey) && !staking_hotkeys.contains(new_hotkey) { + staking_hotkeys.push(new_hotkey.clone()); + StakingHotkeys::::insert(&coldkey, staking_hotkeys); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + } + } } - Ok(()) } } diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 1a9016f13f..f323bbdf0a 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -1,10 +1,12 @@ #![allow(clippy::indexing_slicing)] #![allow(clippy::unwrap_used)] #![allow(clippy::arithmetic_side_effects)] +use super::mock; use super::mock::*; use approx::assert_abs_diff_eq; use frame_support::{assert_err, assert_noop, assert_ok}; use substrate_fixed::types::{I64F64, I96F32, U96F32}; +use subtensor_swap_interface::SwapHandler; use crate::{utils::rate_limiting::TransactionType, *}; use sp_core::U256; @@ -28,7 +30,7 @@ fn test_do_set_child_singular_success() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -52,7 +54,7 @@ fn test_do_set_child_singular_network_does_not_exist() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 999; // Non-existent network + let netuid = NetUid::from(999); // Non-existent network let proportion: u64 = 1000; // Attempt to set child @@ -75,7 +77,7 @@ fn test_do_set_child_singular_invalid_child() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -105,7 +107,7 @@ fn test_do_set_child_singular_non_associated_coldkey() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey with a different coldkey @@ -133,7 +135,7 @@ fn test_do_set_child_singular_root_network() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = SubtensorModule::get_root_netuid(); // Root network + let netuid = NetUid::ROOT; // Root network let proportion: u64 = 1000; // Add network and register hotkey @@ -167,7 +169,7 @@ fn test_do_set_child_singular_old_children_cleanup() { let hotkey = U256::from(2); let old_child = U256::from(3); let new_child = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -205,7 +207,7 @@ fn test_do_set_child_singular_new_children_assignment() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -238,7 +240,7 @@ fn test_do_set_child_singular_proportion_edge_cases() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -279,7 +281,7 @@ fn test_do_set_child_singular_multiple_children() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion1: u64 = 500; let proportion2: u64 = 500; @@ -318,7 +320,7 @@ fn test_do_set_child_singular_multiple_children() { #[test] fn test_add_singular_child() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let child = U256::from(1); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -371,7 +373,7 @@ fn test_add_singular_child() { #[test] fn test_get_stake_for_hotkey_on_subnet() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let parent = U256::from(1); let child = U256::from(2); let coldkey1 = U256::from(3); @@ -423,7 +425,7 @@ fn test_do_revoke_child_singular_success() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey add_network(netuid, 13, 0); @@ -452,7 +454,7 @@ fn test_do_set_empty_children_network_does_not_exist() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 999; // Non-existent network + let netuid = NetUid::from(999); // Non-existent network // Attempt to revoke child assert_err!( SubtensorModule::do_schedule_children( @@ -477,7 +479,7 @@ fn test_do_revoke_child_singular_non_associated_coldkey() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey with a different coldkey add_network(netuid, 13, 0); @@ -508,7 +510,7 @@ fn test_do_revoke_child_singular_child_not_associated() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -539,7 +541,7 @@ fn test_do_schedule_children_multiple_success() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion1: u64 = 1000; let proportion2: u64 = 2000; @@ -579,7 +581,7 @@ fn test_do_schedule_children_multiple_network_does_not_exist() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child1 = U256::from(3); - let netuid: u16 = 999; // Non-existent network + let netuid = NetUid::from(999); // Non-existent network let proportion: u64 = 1000; // Attempt to set children @@ -606,7 +608,7 @@ fn test_do_schedule_children_multiple_invalid_child() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -638,7 +640,7 @@ fn test_do_schedule_children_multiple_non_associated_coldkey() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey with a different coldkey @@ -670,7 +672,7 @@ fn test_do_schedule_children_multiple_root_network() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = SubtensorModule::get_root_netuid(); // Root network + let netuid = NetUid::ROOT; // Root network let proportion: u64 = 1000; // Add network and register hotkey @@ -705,7 +707,7 @@ fn test_do_schedule_children_multiple_old_children_cleanup() { let old_child = U256::from(3); let new_child1 = U256::from(4); let new_child2 = U256::from(5); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -751,7 +753,7 @@ fn test_do_schedule_children_multiple_proportion_edge_cases() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -792,7 +794,7 @@ fn test_do_schedule_children_multiple_overwrite_existing() { let child1 = U256::from(3); let child2 = U256::from(4); let child3 = U256::from(5); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -850,7 +852,7 @@ fn test_childkey_take_functionality() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -926,7 +928,7 @@ fn test_childkey_take_rate_limiting() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -1030,6 +1032,7 @@ fn test_multiple_networks_childkey_take() { // Create 10 networks and set up neurons (skip network 0) for netuid in 1..NUM_NETWORKS { + let netuid = NetUid::from(netuid); // Add network add_network(netuid, 13, 0); @@ -1037,7 +1040,7 @@ fn test_multiple_networks_childkey_take() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Set a unique childkey take value for each network - let take_value = (netuid + 1) * 100; // Values will be 200, 300, ..., 1000 + let take_value = u16::from(netuid.next()) * 100; // Values will be 200, 300, ..., 1000 assert_ok!(SubtensorModule::set_childkey_take( RuntimeOrigin::signed(coldkey), hotkey, @@ -1060,8 +1063,8 @@ fn test_multiple_networks_childkey_take() { // Verify all networks have different childkey take values for i in 1..NUM_NETWORKS { for j in (i + 1)..NUM_NETWORKS { - let take_i = SubtensorModule::get_childkey_take(&hotkey, i); - let take_j = SubtensorModule::get_childkey_take(&hotkey, j); + let take_i = SubtensorModule::get_childkey_take(&hotkey, i.into()); + let take_j = SubtensorModule::get_childkey_take(&hotkey, j.into()); assert_ne!( take_i, take_j, "Childkey take values should be different for networks {} and {}", @@ -1071,8 +1074,12 @@ fn test_multiple_networks_childkey_take() { } // Attempt to set childkey take again (should fail due to rate limit) - let result = - SubtensorModule::set_childkey_take(RuntimeOrigin::signed(coldkey), hotkey, 1, 1100); + let result = SubtensorModule::set_childkey_take( + RuntimeOrigin::signed(coldkey), + hotkey, + 1.into(), + 1100, + ); assert_noop!(result, Error::::TxChildkeyTakeRateLimitExceeded); // Advance blocks to bypass rate limit @@ -1082,12 +1089,12 @@ fn test_multiple_networks_childkey_take() { assert_ok!(SubtensorModule::set_childkey_take( RuntimeOrigin::signed(coldkey), hotkey, - 1, + 1.into(), 1100 )); // Verify the new take value - let new_take = SubtensorModule::get_childkey_take(&hotkey, 1); + let new_take = SubtensorModule::get_childkey_take(&hotkey, 1.into()); assert_eq!(new_take, 1100, "Childkey take not updated after rate limit"); }); } @@ -1103,7 +1110,7 @@ fn test_do_schedule_children_multiple_empty_list() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -1133,7 +1140,7 @@ fn test_do_revoke_children_multiple_success() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion1: u64 = 1000; let proportion2: u64 = 2000; @@ -1179,7 +1186,7 @@ fn test_do_revoke_children_multiple_network_does_not_exist() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 999; // Non-existent network + let netuid = NetUid::from(999); // Non-existent network // Attempt to revoke children assert_err!( SubtensorModule::do_schedule_children( @@ -1206,7 +1213,7 @@ fn test_do_revoke_children_multiple_non_associated_coldkey() { let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey with a different coldkey add_network(netuid, 13, 0); @@ -1241,7 +1248,7 @@ fn test_do_revoke_children_multiple_partial_revocation() { let child1 = U256::from(3); let child2 = U256::from(4); let child3 = U256::from(5); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -1298,7 +1305,7 @@ fn test_do_revoke_children_multiple_non_existent_children() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child1 = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -1334,7 +1341,7 @@ fn test_do_revoke_children_multiple_empty_list() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // Add network and register hotkey add_network(netuid, 13, 0); @@ -1365,7 +1372,7 @@ fn test_do_revoke_children_multiple_complex_scenario() { let child1 = U256::from(3); let child2 = U256::from(4); let child3 = U256::from(5); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion1: u64 = 1000; let proportion2: u64 = 2000; let proportion3: u64 = 3000; @@ -1434,7 +1441,7 @@ fn test_children_stake_values() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let coldkey = U256::from(1); let hotkey = U256::from(2); @@ -1507,7 +1514,7 @@ fn test_children_stake_values() { #[test] fn test_get_parents_chain() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey = U256::from(1); let num_keys: usize = 5; let proportion = u64::MAX / 2; // 50% stake allocation @@ -1651,7 +1658,7 @@ fn test_get_parents_chain() { #[test] fn test_get_stake_for_hotkey_on_subnet_basic() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -1676,7 +1683,7 @@ fn test_get_stake_for_hotkey_on_subnet_basic() { #[test] fn test_get_stake_for_hotkey_on_subnet_multiple_coldkeys() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let coldkey1 = U256::from(2); let coldkey2 = U256::from(3); @@ -1714,7 +1721,7 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { let parent = U256::from(1); let child = U256::from(2); let coldkey = U256::from(3); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, parent, coldkey, 0); register_ok_neuron(netuid, child, coldkey, 0); @@ -1751,7 +1758,7 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_parents_single_child() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let parent1 = U256::from(1); let parent2 = U256::from(2); @@ -1806,7 +1813,7 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let parent = U256::from(1); let child1 = U256::from(2); @@ -1870,7 +1877,7 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let parent = U256::from(1); let child1 = U256::from(2); @@ -1934,7 +1941,7 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let parent = U256::from(1); let child1 = U256::from(2); @@ -2128,8 +2135,8 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { #[test] fn test_get_stake_for_hotkey_on_subnet_multiple_networks() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -2165,7 +2172,7 @@ fn test_do_set_child_below_min_stake() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -2200,48 +2207,59 @@ fn test_do_remove_stake_clears_pending_childkeys() { let coldkey = U256::from(1); let hotkey = U256::from(2); let child = U256::from(3); - let netuid: u16 = 0; - let child_netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey add_network(netuid, 13, 0); - add_network(child_netuid, 13, 0); - register_ok_neuron(child_netuid, hotkey, coldkey, 0); + register_ok_neuron(netuid, hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 10_000_000_000_000); + + let reserve = 1_000_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); // Set non-default value for childkey stake threshold StakeThreshold::::set(1_000_000_000_000); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, - &coldkey, + assert_ok!(SubtensorModule::do_add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get() * 2 + )); + + let alpha = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); + + println!( + "StakeThreshold::::get() = {:?}", + StakeThreshold::::get() ); + println!("alpha = {:?}", alpha); // Attempt to set child assert_ok!(SubtensorModule::do_schedule_children( RuntimeOrigin::signed(coldkey), hotkey, - child_netuid, + netuid, vec![(proportion, child)] )); // Check that pending child exists - let pending_before = PendingChildKeys::::get(child_netuid, hotkey); + let pending_before = PendingChildKeys::::get(netuid, hotkey); assert!(!pending_before.0.is_empty()); assert!(pending_before.1 > 0); // Remove stake - let _ = SubtensorModule::do_remove_stake( + assert_ok!(SubtensorModule::do_remove_stake( RuntimeOrigin::signed(coldkey), hotkey, netuid, - 100_000_000_000, - ); + alpha, + )); // Assert that pending child is removed - let pending_after = PendingChildKeys::::get(child_netuid, hotkey); + let pending_after = PendingChildKeys::::get(netuid, hotkey); close( pending_after.0.len() as u64, 0, @@ -2262,7 +2280,7 @@ fn test_do_set_child_cooldown_period() { let coldkey = U256::from(1); let parent = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -2335,7 +2353,7 @@ fn test_do_set_pending_children_runs_in_epoch() { let coldkey = U256::from(1); let parent = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey @@ -2400,22 +2418,27 @@ fn test_revoke_child_no_min_stake_check() { let coldkey = U256::from(1); let parent = U256::from(2); let child = U256::from(3); - let root: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey - add_network(root, 13, 0); + add_network(NetUid::ROOT, 13, 0); add_network(netuid, 13, 0); register_ok_neuron(netuid, parent, coldkey, 0); + let reserve = 1_000_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(NetUid::ROOT, reserve, reserve); + // Set minimum stake for setting children StakeThreshold::::put(1_000_000_000_000); + + let (_, fee) = mock::swap_tao_to_alpha(NetUid::ROOT, StakeThreshold::::get()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &parent, &coldkey, - root, - StakeThreshold::::get(), + NetUid::ROOT, + StakeThreshold::::get() + fee, ); // Schedule parent-child relationship @@ -2434,8 +2457,8 @@ fn test_revoke_child_no_min_stake_check() { SubtensorModule::decrease_stake_for_hotkey_and_coldkey_on_subnet( &parent, &coldkey, - root, - StakeThreshold::::get(), + NetUid::ROOT, + StakeThreshold::::get() + fee, ); // Ensure the childkeys are applied @@ -2474,20 +2497,24 @@ fn test_do_set_child_registration_disabled() { let coldkey = U256::from(1); let parent = U256::from(2); let child = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion: u64 = 1000; // Add network and register hotkey add_network(netuid, 13, 0); register_ok_neuron(netuid, parent, coldkey, 0); + let reserve = 1_000_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Set minimum stake for setting children StakeThreshold::::put(1_000_000_000_000); + let (_, fee) = mock::swap_tao_to_alpha(netuid, StakeThreshold::::get()); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get() + fee, ); // Disable subnet registrations @@ -2506,7 +2533,7 @@ fn test_do_set_child_registration_disabled() { &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get() + fee, ); // Ensure the childkeys are applied @@ -2532,7 +2559,7 @@ fn test_set_children_rate_limit_fail_then_succeed() { let hotkey = U256::from(2); let child = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo = 13; // Add network and register hotkey @@ -2587,7 +2614,7 @@ fn test_childkey_set_weights_single_parent() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); Tempo::::insert(netuid, 1); // Define hotkeys @@ -2696,7 +2723,7 @@ fn test_set_weights_no_parent() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let hotkey: U256 = U256::from(2); let spare_hk: U256 = U256::from(3); @@ -2806,13 +2833,14 @@ fn test_childkey_take_drain() { let miner_coldkey = U256::from(5); let miner_hotkey = U256::from(6); let nominator = U256::from(7); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let subnet_tempo = 10; let stake = 100_000_000_000; let proportion: u64 = u64::MAX / 2; // Add network, register hotkeys, and setup network parameters add_network(netuid, subnet_tempo, 0); + mock::setup_reserves(netuid, stake * 10_000, stake * 10_000); register_ok_neuron(netuid, child_hotkey, child_coldkey, 0); register_ok_neuron(netuid, parent_hotkey, parent_coldkey, 1); register_ok_neuron(netuid, miner_hotkey, miner_coldkey, 1); @@ -2922,7 +2950,7 @@ fn test_parent_child_chain_emission() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); Tempo::::insert(netuid, 1); // Setup large LPs to prevent slippage @@ -2955,10 +2983,15 @@ fn test_parent_child_chain_emission() { let stake_b = 100_000_000_000_u64; let stake_c = 50_000_000_000_u64; let total_tao: I96F32 = I96F32::from_num(stake_a + stake_b + stake_c); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.to_num::(), - )); + let total_alpha: I96F32 = I96F32::from_num( + SubtensorModule::swap_tao_for_alpha( + netuid, + total_tao.to_num::(), + ::SwapInterface::max_price(), + ) + .unwrap() + .amount_paid_out, + ); // Set the stakes directly // This avoids needing to swap tao to alpha, impacting the initial stake distribution. @@ -3131,7 +3164,7 @@ fn test_parent_child_chain_emission() { #[test] fn test_parent_child_chain_epoch() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Set owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); @@ -3154,12 +3187,12 @@ fn test_parent_child_chain_epoch() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); + // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); + let total_tao = I96F32::from_num(300_000 + 100_000 + 50_000); + let (total_alpha, _) = mock::swap_tao_to_alpha(netuid, total_tao.to_num()); + let total_alpha = I96F32::from_num(total_alpha); // Set the stakes directly // This avoids needing to swap tao to alpha, impacting the initial stake distribution. @@ -3183,21 +3216,28 @@ fn test_parent_child_chain_epoch() { ); // Get old stakes - let stake_a: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); - let stake_b: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); - let stake_c: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c); + let stake_a = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); + let stake_b = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); + let stake_c = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c); // Assert initial stake is correct - let rel_stake_a = I96F32::from_num(stake_a) / total_tao; - let rel_stake_b = I96F32::from_num(stake_b) / total_tao; - let rel_stake_c = I96F32::from_num(stake_c) / total_tao; + let rel_stake_a = I96F32::from_num(stake_a) / total_alpha; + let rel_stake_b = I96F32::from_num(stake_b) / total_alpha; + let rel_stake_c = I96F32::from_num(stake_c) / total_alpha; log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3 log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9 log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9 - assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao); - assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao); - assert_eq!(rel_stake_c, I96F32::from_num(50_000) / total_tao); + + assert!(rel_stake_a > I96F32::from_num(0)); + assert!(rel_stake_b > I96F32::from_num(0)); + assert!(rel_stake_c > I96F32::from_num(0)); + + // because of the fee we allow slightly higher range + let epsilon = I96F32::from_num(0.00001); + assert!((rel_stake_a - (I96F32::from_num(300_000) / total_tao)).abs() <= epsilon); + assert!((rel_stake_b - (I96F32::from_num(100_000) / total_tao)).abs() <= epsilon); + assert!((rel_stake_c - (I96F32::from_num(50_000) / total_tao)).abs() <= epsilon); // Set parent-child relationships // A -> B (50% of A's stake) @@ -3207,7 +3247,7 @@ fn test_parent_child_chain_epoch() { mock_set_children(&coldkey_b, &hotkey_b, netuid, &[(u64::MAX / 2, hotkey_c)]); // Set CHK take rate to 1/9 - let chk_take: I96F32 = I96F32::from_num(1_f64 / 9_f64); + let chk_take = I96F32::from_num(1_f64 / 9_f64); let chk_take_u16: u16 = (chk_take * I96F32::from_num(u16::MAX)).saturating_to_num::(); ChildkeyTake::::insert(hotkey_b, netuid, chk_take_u16); ChildkeyTake::::insert(hotkey_c, netuid, chk_take_u16); @@ -3215,9 +3255,9 @@ fn test_parent_child_chain_epoch() { // Set the weight of root TAO to be 0%, so only alpha is effective. SubtensorModule::set_tao_weight(0); - let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed) + let hardcoded_emission = I96F32::from_num(1_000_000); // 1 million (adjust as needed) - let hotkey_emission: Vec<(U256, u64, u64)> = + let hotkey_emission = SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::()); log::info!("hotkey_emission: {:?}", hotkey_emission); let total_emission: I96F32 = hotkey_emission @@ -3226,7 +3266,7 @@ fn test_parent_child_chain_epoch() { .sum(); // Verify emissions match expected from CHK arrangements - let em_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places + let em_eps = I96F32::from_num(1e-4); // 4 decimal places // A's pending emission: assert!( ((I96F32::from_num(hotkey_emission[0].2) / total_emission) - @@ -3262,8 +3302,9 @@ fn test_parent_child_chain_epoch() { #[test] fn test_dividend_distribution_with_children() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); + mock::setup_reserves(netuid, 1_000_000_000_000_000, 1_000_000_000_000_000); // Set owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); @@ -3286,11 +3327,9 @@ fn test_dividend_distribution_with_children() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); + let total_tao = I96F32::from_num(300_000 + 100_000 + 50_000); + let (total_alpha, _) = mock::swap_tao_to_alpha(netuid, total_tao.to_num()); + let total_alpha = I96F32::from_num(total_alpha); // Set the stakes directly // This avoids needing to swap tao to alpha, impacting the initial stake distribution. @@ -3314,21 +3353,22 @@ fn test_dividend_distribution_with_children() { ); // Get old stakes - let stake_a: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); - let stake_b: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); - let stake_c: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c); + let stake_a = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); + let stake_b = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); + let stake_c = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c); // Assert initial stake is correct - let rel_stake_a = I96F32::from_num(stake_a) / total_tao; - let rel_stake_b = I96F32::from_num(stake_b) / total_tao; - let rel_stake_c = I96F32::from_num(stake_c) / total_tao; + let rel_stake_a = I96F32::from_num(stake_a) / total_alpha; + let rel_stake_b = I96F32::from_num(stake_b) / total_alpha; + let rel_stake_c = I96F32::from_num(stake_c) / total_alpha; log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3 log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9 log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9 - assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao); - assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao); - assert_eq!(rel_stake_c, I96F32::from_num(50_000) / total_tao); + let epsilon = I96F32::from_num(0.00001); + assert!((rel_stake_a - I96F32::from_num(300_000) / total_tao).abs() <= epsilon); + assert!((rel_stake_b - I96F32::from_num(100_000) / total_tao).abs() <= epsilon); + assert!((rel_stake_c - I96F32::from_num(50_000) / total_tao).abs() <= epsilon); // Set parent-child relationships // A -> B (50% of A's stake) @@ -3487,16 +3527,16 @@ fn test_dividend_distribution_with_children() { #[test] fn test_dynamic_parent_child_relationships() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Define hotkeys and coldkeys - let parent: U256 = U256::from(1); - let child1: U256 = U256::from(2); - let child2: U256 = U256::from(3); - let coldkey_parent: U256 = U256::from(100); - let coldkey_child1: U256 = U256::from(101); - let coldkey_child2: U256 = U256::from(102); + let parent = U256::from(1); + let child1 = U256::from(2); + let child2 = U256::from(3); + let coldkey_parent = U256::from(100); + let coldkey_child1 = U256::from(101); + let coldkey_child2 = U256::from(102); // Register neurons with varying stakes register_ok_neuron(netuid, parent, coldkey_parent, 0); @@ -3513,12 +3553,13 @@ fn test_dynamic_parent_child_relationships() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_child1, 50_000 + 1_000); SubtensorModule::add_balance_to_coldkey_account(&coldkey_child2, 30_000 + 1_000); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(500_000 + 50_000 + 30_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); + let total_tao = I96F32::from_num(500_000 + 50_000 + 30_000); + let (total_alpha, _) = mock::swap_tao_to_alpha(netuid, total_tao.to_num()); + let total_alpha = I96F32::from_num(total_alpha); log::info!("total_alpha: {:?}", total_alpha); // Set the stakes directly @@ -3553,16 +3594,17 @@ fn test_dynamic_parent_child_relationships() { let total_stake_0: u64 = stake_parent_0 + stake_child1_0 + stake_child2_0; // Assert initial stake is correct - let rel_stake_parent_0 = I96F32::from_num(stake_parent_0) / total_tao; - let rel_stake_child1_0 = I96F32::from_num(stake_child1_0) / total_tao; - let rel_stake_child2_0 = I96F32::from_num(stake_child2_0) / total_tao; + let rel_stake_parent_0 = I96F32::from_num(stake_parent_0) / total_alpha; + let rel_stake_child1_0 = I96F32::from_num(stake_child1_0) / total_alpha; + let rel_stake_child2_0 = I96F32::from_num(stake_child2_0) / total_alpha; log::info!("rel_stake_parent_0: {:?}", rel_stake_parent_0); log::info!("rel_stake_child1_0: {:?}", rel_stake_child1_0); log::info!("rel_stake_child2_0: {:?}", rel_stake_child2_0); - assert_eq!(rel_stake_parent_0, I96F32::from_num(500_000) / total_tao); - assert_eq!(rel_stake_child1_0, I96F32::from_num(50_000) / total_tao); - assert_eq!(rel_stake_child2_0, I96F32::from_num(30_000) / total_tao); + let epsilon = I96F32::from_num(0.00001); + assert!((rel_stake_parent_0 - I96F32::from_num(500_000) / total_tao).abs() <= epsilon); + assert!((rel_stake_child1_0 - I96F32::from_num(50_000) / total_tao).abs() <= epsilon); + assert!((rel_stake_child2_0 - I96F32::from_num(30_000) / total_tao).abs() <= epsilon); mock_set_children(&coldkey_parent, &parent, netuid, &[(u64::MAX / 2, child1)]); @@ -3742,7 +3784,7 @@ fn test_do_set_child_as_sn_owner_not_enough_stake() { let proportion: u64 = 1000; - let netuid: u16 = add_dynamic_network(&sn_owner_hotkey, &coldkey); + let netuid = add_dynamic_network(&sn_owner_hotkey, &coldkey); register_ok_neuron(netuid, child_hotkey, child_coldkey, 0); // Verify stake of sn_owner_hotkey is NOT enough @@ -3787,10 +3829,11 @@ fn test_do_set_child_as_sn_owner_not_enough_stake() { #[test] fn test_dividend_distribution_with_children_same_coldkey_owner() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Set SN owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); // Define hotkeys and coldkeys let hotkey_a: U256 = U256::from(1); @@ -3806,11 +3849,9 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); + let total_tao = 300_000 + 100_000; + let total_alpha = I96F32::from_num(mock::swap_tao_to_alpha(netuid, total_tao).0); + let total_tao = I96F32::from_num(total_tao); // Set the stakes directly // This avoids needing to swap tao to alpha, impacting the initial stake distribution. @@ -3832,13 +3873,14 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { let stake_b: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); // Assert initial stake is correct - let rel_stake_a = I96F32::from_num(stake_a) / total_tao; - let rel_stake_b = I96F32::from_num(stake_b) / total_tao; + let rel_stake_a = I96F32::from_num(stake_a) / total_alpha; + let rel_stake_b = I96F32::from_num(stake_b) / total_alpha; log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.75 -> 3/4 log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.25 -> 1/4 - assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao); - assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao); + let epsilon = I96F32::from_num(0.0001); + assert!((rel_stake_a - I96F32::from_num(300_000) / total_tao).abs() <= epsilon); + assert!((rel_stake_b - I96F32::from_num(100_000) / total_tao).abs() <= epsilon); // Set parent-child relationships // A -> B (50% of A's stake) @@ -3949,23 +3991,24 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { } #[test] -fn test_pending_cooldown_one_day() { +fn test_pending_cooldown_as_expected() { let curr_block = 1; - - let expected_cooldown = if cfg!(feature = "fast-blocks") { - 15 - } else { - 7_200 - }; + // TODO: Fix when CHK splitting patched + // let expected_cooldown = if cfg!(feature = "fast-blocks") { + // 15 + // } else { + // 7200 + // }; new_test_ext(curr_block).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let proportion1: u64 = 1000; let proportion2: u64 = 2000; + let expected_cooldown = PendingChildKeyCooldown::::get(); // Add network and register hotkey add_network(netuid, 13, 0); @@ -3995,7 +4038,7 @@ fn test_do_set_childkey_take_success() { // Setup let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let take = 5000; // Add network and register hotkey @@ -4024,7 +4067,7 @@ fn test_do_set_childkey_take_non_associated_coldkey() { let coldkey = U256::from(1); let hotkey = U256::from(2); let hotkey2 = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let take = 5000; // Add network and register hotkey @@ -4045,7 +4088,7 @@ fn test_do_set_childkey_take_invalid_take_value() { // Setup let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let take = SubtensorModule::get_max_childkey_take() + 1; // Add network and register hotkey @@ -4066,7 +4109,7 @@ fn test_do_set_childkey_take_rate_limit_exceeded() { // Setup let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let initial_take = 3000; let higher_take = 5000; let lower_take = 1000; diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 1345f36b7d..285c318ba2 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -1,10 +1,12 @@ #![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] use super::mock::*; +use crate::tests::mock; use crate::*; use alloc::collections::BTreeMap; use approx::assert_abs_diff_eq; use frame_support::assert_ok; +use pallet_subtensor_swap::position::PositionId; use sp_core::U256; use substrate_fixed::types::{I64F64, I96F32, U96F32}; @@ -48,10 +50,10 @@ fn test_dynamic_function_various_values() { for &tao_in in tao_in_values.iter() { for &alpha_emission in alpha_emission_values.iter() { // Set the price. - SubnetMechanism::::insert(1, 1); - SubnetTAO::::insert(1, (price * 1_000_000_000.0) as u64); - SubnetAlphaIn::::insert(1, 1_000_000_000); - let (tao_in_emission, alpha_in_emission, alpha_out_emission) = SubtensorModule::get_dynamic_tao_emission( 1, tao_in, alpha_emission); + SubnetMechanism::::insert(NetUid::from(1), 1); + SubnetTAO::::insert(NetUid::from(1), (price * 1_000_000_000.0) as u64); + SubnetAlphaIn::::insert(NetUid::from(1), 1_000_000_000); + let (tao_in_emission, alpha_in_emission, alpha_out_emission) = SubtensorModule::get_dynamic_tao_emission(1.into(), tao_in, alpha_emission); assert!(tao_in_emission <= tao_in, "tao_in_emission is greater than tao_in"); assert!(alpha_in_emission <= alpha_emission, "alpha_in_emission is greater than alpha_emission"); assert!(alpha_out_emission <= 2 * alpha_emission, "alpha_out_emission is greater than 2 * alpha_emission"); @@ -86,7 +88,7 @@ fn test_coinbase_basecase() { #[test] fn test_coinbase_tao_issuance_base() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let emission: u64 = 1_234_567; add_network(netuid, 1, 0); assert_eq!(SubnetTAO::::get(netuid), 0); @@ -101,7 +103,7 @@ fn test_coinbase_tao_issuance_base() { #[test] fn test_coinbase_tao_issuance_base_low() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let emission: u64 = 1; add_network(netuid, 1, 0); assert_eq!(SubnetTAO::::get(netuid), 0); @@ -122,9 +124,9 @@ fn test_coinbase_tao_issuance_base_low() { #[test] fn test_coinbase_tao_issuance_multiple() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; - let netuid3: u16 = 3; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); + let netuid3 = NetUid::from(3); let emission: u64 = 3_333_333; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -150,8 +152,8 @@ fn test_coinbase_tao_issuance_multiple() { #[test] fn test_coinbase_tao_issuance_different_prices() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let emission: u64 = 100_000_000; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -183,7 +185,7 @@ fn test_coinbase_tao_issuance_different_prices() { #[test] fn test_coinbase_moving_prices() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Set price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); @@ -239,7 +241,7 @@ fn test_coinbase_moving_prices() { #[test] fn test_update_moving_price_initial() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Set current price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); @@ -264,7 +266,7 @@ fn test_update_moving_price_initial() { #[test] fn test_update_moving_price_after_time() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // Set current price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); @@ -293,8 +295,8 @@ fn test_update_moving_price_after_time() { #[test] fn test_coinbase_alpha_issuance_base() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let emission: u64 = 1_000_000; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -322,8 +324,8 @@ fn test_coinbase_alpha_issuance_base() { #[test] fn test_coinbase_alpha_issuance_different() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let emission: u64 = 1_000_000; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -357,8 +359,8 @@ fn test_coinbase_alpha_issuance_different() { #[test] fn test_coinbase_alpha_issuance_with_cap_trigger() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let emission: u64 = 1_000_000; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -398,8 +400,8 @@ fn test_coinbase_alpha_issuance_with_cap_trigger() { #[test] fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { new_test_ext(1).execute_with(|| { - let netuid1: u16 = 1; - let netuid2: u16 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let emission: u64 = 1_000_000; add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -437,8 +439,9 @@ fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { #[test] fn test_owner_cut_base() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_subnet_owner_cut(0); SubtensorModule::run_coinbase(U96F32::from_num(0)); @@ -453,37 +456,44 @@ fn test_owner_cut_base() { #[test] fn test_pending_swapped() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let emission: u64 = 1_000_000; add_network(netuid, 1, 0); + mock::setup_reserves(netuid, 1_000_000, 1); SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight and no root. - SubnetTAO::::insert(0, 1_000_000_000); // Add root weight. + SubnetTAO::::insert(NetUid::ROOT, 1_000_000_000); // Add root weight. SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight with 1 root. SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 SubtensorModule::run_coinbase(U96F32::from_num(0)); - assert_eq!(PendingAlphaSwapped::::get(netuid), 125000000); // 1 TAO / ( 1 + 3 ) = 0.25 * 1 / 2 = 125000000 - assert_eq!( + // 1 TAO / ( 1 + 3 ) = 0.25 * 1 / 2 = 125000000 + assert_abs_diff_eq!( + PendingAlphaSwapped::::get(netuid), + 125000000, + epsilon = 1 + ); + assert_abs_diff_eq!( PendingEmission::::get(netuid), - 1_000_000_000 - 125000000 + 1_000_000_000 - 125000000, + epsilon = 1 ); // 1 - swapped. - assert_eq!(PendingRootDivs::::get(netuid), 125000000); // swapped * (price = 1) + assert_abs_diff_eq!(PendingRootDivs::::get(netuid), 125000000, epsilon = 1); // swapped * (price = 1) }); } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_drain_base --exact --show-output --nocapture #[test] fn test_drain_base() { - new_test_ext(1).execute_with(|| SubtensorModule::drain_pending_emission(0, 0, 0, 0, 0)); + new_test_ext(1).execute_with(|| SubtensorModule::drain_pending_emission(0.into(), 0, 0, 0, 0)); } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_drain_base_with_subnet --exact --show-output --nocapture #[test] fn test_drain_base_with_subnet() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); SubtensorModule::drain_pending_emission(netuid, 0, 0, 0, 0) }); @@ -493,7 +503,7 @@ fn test_drain_base_with_subnet() { #[test] fn test_drain_base_with_subnet_with_single_staker_not_registered() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -516,7 +526,7 @@ fn test_drain_base_with_subnet_with_single_staker_not_registered() { #[test] fn test_drain_base_with_subnet_with_single_staker_registered() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -540,8 +550,7 @@ fn test_drain_base_with_subnet_with_single_staker_registered() { #[test] fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { new_test_ext(1).execute_with(|| { - let root: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); @@ -553,7 +562,7 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, - root, + NetUid::ROOT, stake_before, ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -567,8 +576,11 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); let stake_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - let root_after = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, root); + let root_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + ); close(stake_before + pending_alpha, stake_after, 10); // Registered gets all alpha emission. close(stake_before + pending_tao, root_after, 10); // Registered gets all tao emission }); @@ -578,7 +590,7 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { #[test] fn test_drain_base_with_subnet_with_two_stakers_registered() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); @@ -613,8 +625,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered() { #[test] fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { new_test_ext(1).execute_with(|| { - let root: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); @@ -634,7 +645,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey, - root, + NetUid::ROOT, stake_before, ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -646,7 +657,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, &coldkey, - root, + NetUid::ROOT, stake_before, ); let pending_tao: u64 = 1_000_000_000; @@ -654,12 +665,18 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); - let root_after1 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, root); + let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &coldkey, + NetUid::ROOT, + ); let stake_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid); - let root_after2 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, root); + let root_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &coldkey, + NetUid::ROOT, + ); close(stake_before + pending_alpha / 2, stake_after1, 10); // Registered gets 1/2 emission close(stake_before + pending_alpha / 2, stake_after2, 10); // Registered gets 1/2 emission. close(stake_before + pending_tao / 2, root_after1, 10); // Registered gets 1/2 tao emission @@ -671,8 +688,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { #[test] fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_amounts() { new_test_ext(1).execute_with(|| { - let root: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); @@ -692,7 +708,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey, - root, + NetUid::ROOT, 2 * stake_before, // Hotkey 1 has twice as much root weight. ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -704,7 +720,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, &coldkey, - root, + NetUid::ROOT, stake_before, ); let pending_tao: u64 = 1_000_000_000; @@ -712,12 +728,18 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); - let root_after1 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, root); + let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &coldkey, + NetUid::ROOT, + ); let stake_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid); - let root_after2 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, root); + let root_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &coldkey, + NetUid::ROOT, + ); let expected_stake = I96F32::from_num(stake_before) + (I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0)); assert_abs_diff_eq!(expected_stake.to_num::(), stake_after1, epsilon = 10); // Registered gets 50% of alpha emission @@ -738,8 +760,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_amounts_half_tao_weight() { new_test_ext(1).execute_with(|| { - let root: u16 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); @@ -759,7 +780,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey, - root, + NetUid::ROOT, 2 * stake_before, // Hotkey 1 has twice as much root weight. ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -771,7 +792,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, &coldkey, - root, + NetUid::ROOT, stake_before, ); let pending_tao: u64 = 1_000_000_000; @@ -779,12 +800,18 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); - let root_after1 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, root); + let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &coldkey, + NetUid::ROOT, + ); let stake_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid); - let root_after2 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, root); + let root_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &coldkey, + NetUid::ROOT, + ); let expected_stake = I96F32::from_num(stake_before) + I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0); assert_abs_diff_eq!(expected_stake.to_num::(), stake_after1, epsilon = 10); @@ -806,7 +833,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am #[test] fn test_drain_alpha_childkey_parentkey() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); let parent = U256::from(1); let child = U256::from(2); @@ -848,9 +875,8 @@ fn test_drain_alpha_childkey_parentkey() { fn test_get_root_children() { new_test_ext(1).execute_with(|| { // Init netuid 1 - let root: u16 = 0; - let alpha: u16 = 1; - add_network(root, 1, 0); + let alpha = NetUid::from(1); + add_network(NetUid::ROOT, 1, 0); add_network(alpha, 1, 0); // Set TAO weight to 1. @@ -878,14 +904,14 @@ fn test_get_root_children() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold, - root, + NetUid::ROOT, alice_root_stake, ); let bob_root_stake: u64 = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold, - root, + NetUid::ROOT, alice_root_stake, ); @@ -906,16 +932,16 @@ fn test_get_root_children() { ); // Set Bob as 100% child of Alice on root. - // mock_set_children_no_epochs( root, &alice, &[(u64::MAX, bob)]); + // mock_set_children_no_epochs( NetUid::ROOT, &alice, &[(u64::MAX, bob)]); mock_set_children_no_epochs(alpha, &alice, &[(u64::MAX, bob)]); // Assert Alice and Bob stake on root and netuid assert_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, root), + SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, NetUid::ROOT), alice_root_stake ); assert_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, root), + SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, NetUid::ROOT), bob_root_stake ); assert_eq!( @@ -929,7 +955,7 @@ fn test_get_root_children() { // Assert Alice and Bob inherited stakes assert_eq!( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&alice, root), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&alice, NetUid::ROOT), alice_root_stake ); assert_eq!( @@ -937,7 +963,7 @@ fn test_get_root_children() { 0 ); assert_eq!( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&bob, root), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&bob, NetUid::ROOT), bob_root_stake ); assert_eq!( @@ -972,9 +998,8 @@ fn test_get_root_children() { fn test_get_root_children_drain() { new_test_ext(1).execute_with(|| { // Init netuid 1 - let root: u16 = 0; - let alpha: u16 = 1; - add_network(root, 1, 0); + let alpha = NetUid::from(1); + add_network(NetUid::ROOT, 1, 0); add_network(alpha, 1, 0); // Set TAO weight to 1. SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1. @@ -999,14 +1024,14 @@ fn test_get_root_children_drain() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, - root, + NetUid::ROOT, alice_root_stake, ); let bob_root_stake: u64 = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, - root, + NetUid::ROOT, alice_root_stake, ); // Add stake for Alice and Bob on netuid. @@ -1062,11 +1087,11 @@ fn test_get_root_children_drain() { // Alice and Bob both made half of the dividends. assert_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, root), + SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, NetUid::ROOT), alice_root_stake + pending_root / 2 ); assert_eq!( - SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, root), + SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, NetUid::ROOT), bob_root_stake + pending_root / 2 ); @@ -1096,9 +1121,8 @@ fn test_get_root_children_drain() { fn test_get_root_children_drain_half_proportion() { new_test_ext(1).execute_with(|| { // Init netuid 1 - let root: u16 = 0; - let alpha: u16 = 1; - add_network(root, 1, 0); + let alpha = NetUid::from(1); + add_network(NetUid::ROOT, 1, 0); add_network(alpha, 1, 0); // Set TAO weight to 1. SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1. @@ -1123,14 +1147,14 @@ fn test_get_root_children_drain_half_proportion() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, - root, + NetUid::ROOT, alice_root_stake, ); let bob_root_stake: u64 = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, - root, + NetUid::ROOT, alice_root_stake, ); // Add stake for Alice and Bob on netuid. @@ -1179,9 +1203,8 @@ fn test_get_root_children_drain_half_proportion() { fn test_get_root_children_drain_with_take() { new_test_ext(1).execute_with(|| { // Init netuid 1 - let root: u16 = 0; - let alpha: u16 = 1; - add_network(root, 1, 0); + let alpha = NetUid::from(1); + add_network(NetUid::ROOT, 1, 0); add_network(alpha, 1, 0); // Set TAO weight to 1. SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1. @@ -1206,14 +1229,14 @@ fn test_get_root_children_drain_with_take() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, - root, + NetUid::ROOT, alice_root_stake, ); let bob_root_stake: u64 = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, - root, + NetUid::ROOT, alice_root_stake, ); // Add stake for Alice and Bob on netuid. @@ -1257,9 +1280,8 @@ fn test_get_root_children_drain_with_take() { fn test_get_root_children_drain_with_half_take() { new_test_ext(1).execute_with(|| { // Init netuid 1 - let root: u16 = 0; - let alpha: u16 = 1; - add_network(root, 1, 0); + let alpha = NetUid::from(1); + add_network(NetUid::ROOT, 1, 0); add_network(alpha, 1, 0); // Set TAO weight to 1. SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1. @@ -1284,14 +1306,14 @@ fn test_get_root_children_drain_with_half_take() { SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, - root, + NetUid::ROOT, alice_root_stake, ); let bob_root_stake: u64 = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, - root, + NetUid::ROOT, alice_root_stake, ); // Add stake for Alice and Bob on netuid. @@ -1339,9 +1361,8 @@ fn test_get_root_children_drain_with_half_take() { // fn test_get_root_children_with_weights() { // new_test_ext(1).execute_with(|| { // // Init netuid 1 -// let root: u16 = 0; -// let alpha: u16 = 1; -// add_network(root, 1, 0); +// let alpha = NetUid::from(1); +// add_network(NetUid::ROOT, 1, 0); // add_network(alpha, 1, 0); // // Set TAO weight to 1. // SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1. @@ -1365,14 +1386,14 @@ fn test_get_root_children_drain_with_half_take() { // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &alice, // &cold, -// root, +// NetUid::ROOT, // alice_root_stake, // ); // let bob_root_stake: u64 = 1_000_000_000; // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &bob, // &cold, -// root, +// NetUid::ROOT, // alice_root_stake, // ); // // Add stake for Alice and Bob on netuid. @@ -1955,7 +1976,7 @@ fn test_drain_pending_emission_zero_emission() { #[test] fn test_run_coinbase_not_started() { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let tempo = 2; let sn_owner_hk = U256::from(7); @@ -1977,6 +1998,9 @@ fn test_run_coinbase_not_started() { // Set weight-set limit to 0. SubtensorModule::set_weights_set_rate_limit(netuid, 0); + let reserve = init_stake * 1000; + mock::setup_reserves(netuid, reserve, reserve); + register_ok_neuron(netuid, hotkey, coldkey, 0); register_ok_neuron(netuid, miner_hk, miner_ck, 0); register_ok_neuron(netuid, sn_owner_hk, sn_owner_ck, 0); @@ -2037,7 +2061,7 @@ fn test_run_coinbase_not_started() { #[test] fn test_run_coinbase_not_started_start_after() { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let tempo = 2; let sn_owner_hk = U256::from(7); @@ -2131,3 +2155,44 @@ fn test_run_coinbase_not_started_start_after() { log::info!("new_stake: {}", new_stake); }); } + +/// Test that coinbase updates protocol position liquidity +/// cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_v3_liquidity_update --exact --show-output +#[test] +fn test_coinbase_v3_liquidity_update() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Force the swap to initialize + SubtensorModule::swap_tao_for_alpha(netuid, 0, 1_000_000_000_000).unwrap(); + + let protocol_account_id = pallet_subtensor_swap::Pallet::::protocol_account_id(); + let position = pallet_subtensor_swap::Positions::::get(( + netuid, + protocol_account_id, + PositionId::from(1), + )) + .unwrap(); + let liquidity_before = position.liquidity; + + // Enable emissions and run coinbase (which will increase position liquidity) + let emission: u64 = 1_234_567; + FirstEmissionBlockNumber::::insert(netuid, 0); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(0.5)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); + + let position_after = pallet_subtensor_swap::Positions::::get(( + netuid, + protocol_account_id, + PositionId::from(1), + )) + .unwrap(); + let liquidity_after = position_after.liquidity; + + assert!(liquidity_before < liquidity_after); + }); +} diff --git a/pallets/subtensor/src/tests/consensus.rs b/pallets/subtensor/src/tests/consensus.rs index e1db49203e..b11cd44e06 100644 --- a/pallets/subtensor/src/tests/consensus.rs +++ b/pallets/subtensor/src/tests/consensus.rs @@ -118,7 +118,7 @@ fn distribute_nodes( } #[allow(dead_code)] -fn uid_stats(netuid: u16, uid: u16) { +fn uid_stats(netuid: NetUid, uid: u16) { log::info!( "stake: {:?}", SubtensorModule::get_total_stake_for_hotkey(&(U256::from(uid))) @@ -148,7 +148,7 @@ fn uid_stats(netuid: u16, uid: u16) { #[allow(clippy::too_many_arguments)] fn init_run_epochs( - netuid: u16, + netuid: NetUid, n: u16, validators: &[u16], servers: &[u16], @@ -401,7 +401,7 @@ fn split_graph( // Test consensus guarantees with an epoch on a graph with 4096 nodes, of which the first 128 are validators, the graph is split into a major and minor set, each setting specific weight on itself and the complement on the other. Asserts that the major emission ratio >= major stake ratio. // #[test] // fn test_consensus_guarantees() { -// let netuid: u16 = 0; +// let netuid = NetUid::from(0); // let network_n: u16 = 512; // let validators_n: u16 = 64; // let epochs: u16 = 1; @@ -486,7 +486,7 @@ fn split_graph( #[test] #[ignore] // Not an automated test! fn map_consensus_guarantees() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let network_n: u16 = 512; let validators_n: u16 = 64; let epochs: u16 = 1; diff --git a/pallets/subtensor/src/tests/delegate_info.rs b/pallets/subtensor/src/tests/delegate_info.rs index fa9aa942f7..8168755439 100644 --- a/pallets/subtensor/src/tests/delegate_info.rs +++ b/pallets/subtensor/src/tests/delegate_info.rs @@ -5,6 +5,7 @@ use frame_support::assert_ok; use scale_info::prelude::collections::HashMap; use sp_core::U256; use substrate_fixed::types::U64F64; +use subtensor_runtime_common::NetUid; #[test] fn test_return_per_1000_tao() { @@ -110,7 +111,7 @@ fn test_get_delegated() { delegatee_4, ]; let to_stakes = [to_stake_0, to_stake_1, to_stake_2, to_stake_3, to_stake_4]; - let mut expected_stake_map: HashMap>> = + let mut expected_stake_map: HashMap>> = HashMap::new(); for (i, to_stake) in to_stakes.iter().enumerate() { @@ -147,15 +148,10 @@ fn test_get_delegated() { if let Some(expected_under_delegate) = coldkey_stakes_map.get(&delegate_info.delegate_ss58) { - if let Some(expected_stake) = - expected_under_delegate.get(&u16::from(*netuid)) - { + if let Some(expected_stake) = expected_under_delegate.get(&netuid.0) { assert_eq!(u64::from(*staked), *expected_stake); } else { - panic!( - "Netuid {} not found in expected stake map", - u16::from(*netuid) - ); + panic!("Netuid {} not found in expected stake map", netuid.0); }; } else { panic!( diff --git a/pallets/subtensor/src/tests/difficulty.rs b/pallets/subtensor/src/tests/difficulty.rs index d6c151b64f..78ac8620c9 100644 --- a/pallets/subtensor/src/tests/difficulty.rs +++ b/pallets/subtensor/src/tests/difficulty.rs @@ -1,6 +1,7 @@ #![allow(clippy::unwrap_used)] use sp_core::U256; +use subtensor_runtime_common::NetUid; use super::mock::*; @@ -9,7 +10,7 @@ use super::mock::*; fn test_registration_difficulty_adjustment() { new_test_ext(1).execute_with(|| { // Create Net 1 - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let modality: u16 = 1; add_network(netuid, tempo, modality); diff --git a/pallets/subtensor/src/tests/emission.rs b/pallets/subtensor/src/tests/emission.rs index c4d8d51e3c..ecd2df544b 100644 --- a/pallets/subtensor/src/tests/emission.rs +++ b/pallets/subtensor/src/tests/emission.rs @@ -1,3 +1,5 @@ +use subtensor_runtime_common::NetUid; + use super::mock::*; // 1. Test Zero Tempo @@ -7,7 +9,7 @@ use super::mock::*; fn test_zero_tempo() { new_test_ext(1).execute_with(|| { assert_eq!( - SubtensorModule::blocks_until_next_epoch(1, 0, 100), + SubtensorModule::blocks_until_next_epoch(1.into(), 0, 100), u64::MAX ); }); @@ -19,9 +21,15 @@ fn test_zero_tempo() { #[test] fn test_regular_case() { new_test_ext(1).execute_with(|| { - assert_eq!(SubtensorModule::blocks_until_next_epoch(1, 10, 5), 3); - assert_eq!(SubtensorModule::blocks_until_next_epoch(2, 20, 15), 2); - assert_eq!(SubtensorModule::blocks_until_next_epoch(3, 30, 25), 1); + assert_eq!(SubtensorModule::blocks_until_next_epoch(1.into(), 10, 5), 3); + assert_eq!( + SubtensorModule::blocks_until_next_epoch(2.into(), 20, 15), + 2 + ); + assert_eq!( + SubtensorModule::blocks_until_next_epoch(3.into(), 30, 25), + 1 + ); }); } @@ -32,11 +40,11 @@ fn test_regular_case() { fn test_boundary_conditions() { new_test_ext(1).execute_with(|| { assert_eq!( - SubtensorModule::blocks_until_next_epoch(u16::MAX, u16::MAX, u64::MAX), + SubtensorModule::blocks_until_next_epoch(u16::MAX.into(), u16::MAX, u64::MAX), 0 ); assert_eq!( - SubtensorModule::blocks_until_next_epoch(u16::MAX, u16::MAX, 0), + SubtensorModule::blocks_until_next_epoch(u16::MAX.into(), u16::MAX, 0), u16::MAX as u64 ); }); @@ -49,7 +57,7 @@ fn test_boundary_conditions() { fn test_overflow_handling() { new_test_ext(1).execute_with(|| { assert_eq!( - SubtensorModule::blocks_until_next_epoch(u16::MAX, u16::MAX, u64::MAX - 1), + SubtensorModule::blocks_until_next_epoch(u16::MAX.into(), u16::MAX, u64::MAX - 1), 1 ); }); @@ -61,8 +69,14 @@ fn test_overflow_handling() { #[test] fn test_epoch_alignment() { new_test_ext(1).execute_with(|| { - assert_eq!(SubtensorModule::blocks_until_next_epoch(1, 10, 9), 10); - assert_eq!(SubtensorModule::blocks_until_next_epoch(2, 20, 21), 17); + assert_eq!( + SubtensorModule::blocks_until_next_epoch(1.into(), 10, 9), + 10 + ); + assert_eq!( + SubtensorModule::blocks_until_next_epoch(2.into(), 20, 21), + 17 + ); }); } @@ -72,9 +86,9 @@ fn test_epoch_alignment() { #[test] fn test_different_network_ids() { new_test_ext(1).execute_with(|| { - assert_eq!(SubtensorModule::blocks_until_next_epoch(1, 10, 5), 3); - assert_eq!(SubtensorModule::blocks_until_next_epoch(2, 10, 5), 2); - assert_eq!(SubtensorModule::blocks_until_next_epoch(3, 10, 5), 1); + assert_eq!(SubtensorModule::blocks_until_next_epoch(1.into(), 10, 5), 3); + assert_eq!(SubtensorModule::blocks_until_next_epoch(2.into(), 10, 5), 2); + assert_eq!(SubtensorModule::blocks_until_next_epoch(3.into(), 10, 5), 1); }); } @@ -85,7 +99,7 @@ fn test_different_network_ids() { fn test_large_tempo_values() { new_test_ext(1).execute_with(|| { assert_eq!( - SubtensorModule::blocks_until_next_epoch(1, u16::MAX - 1, 100), + SubtensorModule::blocks_until_next_epoch(1.into(), u16::MAX - 1, 100), u16::MAX as u64 - 103 ); }); @@ -98,7 +112,7 @@ fn test_large_tempo_values() { fn test_consecutive_blocks() { new_test_ext(1).execute_with(|| { let tempo = 10; - let netuid = 1; + let netuid = NetUid::from(1); let mut last_result = SubtensorModule::blocks_until_next_epoch(netuid, tempo, 0); for i in 1..tempo - 1 { let current_result = SubtensorModule::blocks_until_next_epoch(netuid, tempo, i as u64); @@ -114,9 +128,12 @@ fn test_consecutive_blocks() { #[test] fn test_wrap_around_behavior() { new_test_ext(1).execute_with(|| { - assert_eq!(SubtensorModule::blocks_until_next_epoch(1, 10, u64::MAX), 9); assert_eq!( - SubtensorModule::blocks_until_next_epoch(1, 10, u64::MAX - 1), + SubtensorModule::blocks_until_next_epoch(1.into(), 10, u64::MAX), + 9 + ); + assert_eq!( + SubtensorModule::blocks_until_next_epoch(1.into(), 10, u64::MAX - 1), 10 ); }); diff --git a/pallets/subtensor/src/tests/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index 2557709912..2b8fdac910 100644 --- a/pallets/subtensor/src/tests/epoch.rs +++ b/pallets/subtensor/src/tests/epoch.rs @@ -4,19 +4,19 @@ clippy::unwrap_used )] -use super::mock::*; -use crate::epoch::math::{fixed, u16_proportion_to_fixed}; -use crate::*; +use std::time::Instant; use approx::assert_abs_diff_eq; use frame_support::{assert_err, assert_ok}; - -// use frame_system::Config; use rand::{Rng, SeedableRng, distributions::Uniform, rngs::StdRng, seq::SliceRandom, thread_rng}; use sp_core::{Get, U256}; -// use sp_runtime::DispatchError; -use std::time::Instant; use substrate_fixed::types::I32F32; +use subtensor_swap_interface::SwapHandler; + +use super::mock::*; +use crate::epoch::math::{fixed, u16_proportion_to_fixed}; +use crate::tests::math::{assert_mat_compare, vec_to_fixed, vec_to_mat_fixed}; +use crate::*; // Normalizes (sum to 1 except 0) the input vector directly in-place. #[allow(dead_code)] @@ -111,7 +111,7 @@ fn distribute_nodes( } #[allow(dead_code)] -fn uid_stats(netuid: u16, uid: u16) { +fn uid_stats(netuid: NetUid, uid: u16) { log::info!( "stake: {:?}", SubtensorModule::get_total_stake_for_hotkey(&(U256::from(uid))) @@ -141,7 +141,7 @@ fn uid_stats(netuid: u16, uid: u16) { #[allow(clippy::too_many_arguments)] fn init_run_epochs( - netuid: u16, + netuid: NetUid, n: u16, validators: &[u16], servers: &[u16], @@ -402,7 +402,7 @@ fn init_run_epochs( // Test consensus guarantees with an epoch on a graph with 4096 nodes, of which the first 128 are validators, the graph is split into a major and minor set, each setting specific weight on itself and the complement on the other. Asserts that the major emission ratio >= major stake ratio. // #[test] // fn test_consensus_guarantees() { -// let netuid: u16 = 0; +// let netuid = NetUid::from(0); // let network_n: u16 = 512; // let validators_n: u16 = 64; // let epochs: u16 = 1; @@ -493,7 +493,7 @@ fn init_run_epochs( // fn test_overflow() { // new_test_ext(1).execute_with(|| { // log::info!("test_overflow:"); -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // add_network(netuid, 1, 0); // SubtensorModule::set_max_allowed_uids(netuid, 3); // SubtensorModule::increase_stake_on_coldkey_hotkey_account( @@ -557,21 +557,27 @@ fn init_run_epochs( fn test_1_graph() { new_test_ext(1).execute_with(|| { log::info!("test_1_graph:"); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey = U256::from(0); let hotkey = U256::from(0); let uid: u16 = 0; - let stake_amount: u64 = 1; + let stake_amount: u64 = 1_000_000_000; add_network(netuid, u16::MAX - 1, 0); // set higher tempo to avoid built-in epoch, then manual epoch instead SubtensorModule::set_max_allowed_uids(netuid, 1); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake_amount); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, + SubtensorModule::add_balance_to_coldkey_account( &coldkey, - netuid, - stake_amount, + stake_amount + ExistentialDeposit::get(), ); - SubtensorModule::append_neuron(netuid, &hotkey, 0); + register_ok_neuron(netuid, hotkey, coldkey, 1); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + stake_amount + )); + assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 1); run_to_block(1); // run to next block to ensure weights are set on nodes after their registration block assert_ok!(SubtensorModule::set_weights( @@ -603,7 +609,7 @@ fn test_10_graph() { new_test_ext(1).execute_with(|| { log::info!("test_10_graph"); // Function for adding a nodes to the graph. - pub fn add_node(netuid: u16, coldkey: U256, hotkey: U256, uid: u16, stake_amount: u64) { + pub fn add_node(netuid: NetUid, coldkey: U256, hotkey: U256, uid: u16, stake_amount: u64) { log::info!( "+Add net:{:?} coldkey:{:?} hotkey:{:?} uid:{:?} stake_amount: {:?} subn: {:?}", netuid, @@ -625,7 +631,7 @@ fn test_10_graph() { // Build the graph with 10 items // each with 1 stake and self weights. let n: usize = 10; - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, u16::MAX - 1, 0); // set higher tempo to avoid built-in epoch, then manual epoch instead SubtensorModule::set_max_allowed_uids(netuid, n as u16); for i in 0..10 { @@ -667,7 +673,7 @@ fn test_10_graph() { // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::epoch::test_512_graph --exact --show-output --nocapture #[test] fn test_512_graph() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let network_n: u16 = 512; let validators_n: u16 = 64; let max_stake_per_validator: u64 = 328_125_000_000_000; // 21_000_000_000_000_000 / 64 @@ -740,7 +746,7 @@ fn test_512_graph() { // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::epoch::test_512_graph_random_weights --exact --show-output --nocapture #[test] fn test_512_graph_random_weights() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let network_n: u16 = 512; let validators_n: u16 = 64; let epochs: u16 = 1; @@ -846,7 +852,7 @@ fn test_512_graph_random_weights() { // Test an epoch on a graph with 4096 nodes, of which the first 256 are validators setting non-self weights, and the rest servers setting only self-weights. // #[test] // fn test_4096_graph() { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let network_n: u16 = 4096; // let validators_n: u16 = 256; // let epochs: u16 = 1; @@ -923,7 +929,7 @@ fn test_512_graph_random_weights() { // #[test] // fn test_16384_graph_sparse() { // new_test_ext(1).execute_with(|| { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let n: u16 = 16384; // let validators_n: u16 = 512; // let validators: Vec = (0..validators_n).collect(); @@ -989,7 +995,7 @@ fn test_bonds() { new_test_ext(1).execute_with(|| { let sparse: bool = true; let n: u16 = 8; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let max_stake: u64 = 4; let stakes: Vec = vec![1, 2, 3, 4, 0, 0, 0, 0]; @@ -1300,11 +1306,15 @@ fn test_set_alpha_disabled() { migrations::migrate_create_root_network::migrate_create_root_network::(); SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey,)); + let fee = ::SwapInterface::approx_fee_amount( + netuid.into(), + DefaultMinStake::::get(), + ); assert_ok!(SubtensorModule::add_stake( signer.clone(), hotkey, netuid, - DefaultMinStake::::get() + DefaultStakingFee::::get() + DefaultMinStake::::get() + fee )); // Only owner can set alpha values assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); @@ -1312,7 +1322,7 @@ fn test_set_alpha_disabled() { // Explicitly set to false SubtensorModule::set_liquid_alpha_enabled(netuid, false); assert_err!( - SubtensorModule::do_set_alpha_values(signer.clone(), netuid, 12_u16, u16::MAX), + SubtensorModule::do_set_alpha_values(signer.clone(), netuid, 1638_u16, u16::MAX), Error::::LiquidAlphaDisabled ); @@ -1320,7 +1330,7 @@ fn test_set_alpha_disabled() { assert_ok!(SubtensorModule::do_set_alpha_values( signer.clone(), netuid, - 12_u16, + 1638_u16, u16::MAX )); }); @@ -1333,7 +1343,7 @@ fn test_active_stake() { System::set_block_number(0); let sparse: bool = true; let n: u16 = 4; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 1; let block_number: u64 = System::block_number(); let stake: u64 = 1; @@ -1540,7 +1550,7 @@ fn test_outdated_weights() { new_test_ext(1).execute_with(|| { let sparse: bool = true; let n: u16 = 4; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 0; let mut block_number: u64 = System::block_number(); let stake: u64 = 1; @@ -1727,7 +1737,7 @@ fn test_zero_weights() { new_test_ext(1).execute_with(|| { let sparse: bool = true; let n: u16 = 2; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = u16::MAX - 1; // high tempo to skip automatic epochs in on_initialize, use manual epochs instead let mut block_number: u64 = 0; let stake: u64 = 1; @@ -1921,7 +1931,7 @@ fn test_deregistered_miner_bonds() { new_test_ext(1).execute_with(|| { let sparse: bool = true; let n: u16 = 4; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let high_tempo: u16 = u16::MAX - 1; // high tempo to skip automatic epochs in on_initialize, use manual epochs instead let stake: u64 = 1; @@ -2098,7 +2108,7 @@ fn test_deregistered_miner_bonds() { // Test that epoch assigns validator permits to highest stake uids that are over the stake threshold, varies uid interleaving and stake values. #[test] fn test_validator_permits() { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = u16::MAX - 1; // high tempo to skip automatic epochs in on_initialize, use manual epochs instead for interleave in 0..3 { for (network_n, validators_n) in [(2, 1), (4, 2), (8, 4)] { @@ -2226,8 +2236,8 @@ fn test_validator_permits() { #[test] fn test_get_set_alpha() { new_test_ext(1).execute_with(|| { - let netuid = 1; - let alpha_low: u16 = 12_u16; + let netuid = NetUid::from(1); + let alpha_low: u16 = 1638_u16; let alpha_high: u16 = u16::MAX - 10; let hotkey: U256 = U256::from(1); @@ -2248,11 +2258,17 @@ fn test_get_set_alpha() { assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); SubtokenEnabled::::insert(netuid, true); + + let fee = ::SwapInterface::approx_fee_amount( + netuid.into(), + DefaultMinStake::::get(), + ); + assert_ok!(SubtensorModule::add_stake( signer.clone(), hotkey, netuid, - DefaultMinStake::::get() + DefaultStakingFee::::get() + DefaultMinStake::::get() + fee )); assert_ok!(SubtensorModule::do_set_alpha_values( @@ -2315,7 +2331,7 @@ fn test_get_set_alpha() { )); // 2. Alpha high too low - let alpha_high_too_low = (u16::MAX as u32 * 4 / 5) as u16 - 1; // One less than the minimum acceptable value + let alpha_high_too_low = (u16::MAX as u32 / 40) as u16 - 1; // One less than the minimum acceptable value assert_err!( SubtensorModule::do_set_alpha_values( signer.clone(), @@ -2352,7 +2368,7 @@ fn test_get_set_alpha() { alpha_high )); - let alpha_low_too_high = (u16::MAX as u32 * 4 / 5) as u16 + 1; // One more than the maximum acceptable value + let alpha_low_too_high = alpha_high + 1; // alpha_low should be <= alpha_high assert_err!( SubtensorModule::do_set_alpha_values( signer.clone(), @@ -2377,7 +2393,7 @@ fn test_blocks_since_last_step() { new_test_ext(1).execute_with(|| { System::set_block_number(0); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 7200; add_network(netuid, tempo, 0); @@ -2478,7 +2494,7 @@ fn test_can_set_self_weight_as_subnet_owner() { #[test] fn test_epoch_outputs_single_staker_registered_no_weights() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let high_tempo: u16 = u16::MAX - 1; // Don't run automatically. add_network(netuid, high_tempo, 0); @@ -2553,7 +2569,7 @@ fn test_epoch_outputs_single_staker_registered_no_weights() { // ``` // #[test] // fn _map_consensus_guarantees() { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let network_n: u16 = 512; // let validators_n: u16 = 64; // let epochs: u16 = 1; @@ -2630,7 +2646,7 @@ pub fn assert_approx_eq(left: I32F32, right: I32F32, epsilon: I32F32) { } // test Yuma 3 scenarios over a sequence of epochs. -fn setup_yuma_3_scenario(netuid: u16, n: u16, sparse: bool, max_stake: u64, stakes: Vec) { +fn setup_yuma_3_scenario(netuid: NetUid, n: u16, sparse: bool, max_stake: u64, stakes: Vec) { let block_number = System::block_number(); let tempo: u16 = 1; // high tempo to skip automatic epochs in on_initialize, use manual epochs instead add_network(netuid, tempo, 0); @@ -2643,7 +2659,7 @@ fn setup_yuma_3_scenario(netuid: u16, n: u16, sparse: bool, max_stake: u64, stak SubtensorModule::set_min_allowed_weights(netuid, 1); SubtensorModule::set_max_weight_limit(netuid, u16::MAX); SubtensorModule::set_bonds_penalty(netuid, 0); - SubtensorModule::set_alpha_sigmoid_steepness(netuid, 10); + SubtensorModule::set_alpha_sigmoid_steepness(netuid, 1000); SubtensorModule::set_bonds_moving_average(netuid, 975_000); // === Register @@ -2690,7 +2706,7 @@ fn setup_yuma_3_scenario(netuid: u16, n: u16, sparse: bool, max_stake: u64, stak run_epoch(netuid, sparse); } -fn run_epoch(netuid: u16, sparse: bool) { +fn run_epoch(netuid: NetUid, sparse: bool) { next_block_no_epoch(netuid); if sparse { SubtensorModule::epoch(netuid, 1_000_000_000); @@ -2700,7 +2716,7 @@ fn run_epoch(netuid: u16, sparse: bool) { } fn run_epoch_and_check_bonds_dividends( - netuid: u16, + netuid: NetUid, sparse: bool, target_bonds: &[Vec], target_dividends: &[f32], @@ -2727,7 +2743,7 @@ fn run_epoch_and_check_bonds_dividends( } } -fn set_yuma_3_weights(netuid: u16, weights: Vec>, indices: Vec) { +fn set_yuma_3_weights(netuid: NetUid, weights: Vec>, indices: Vec) { for (uid, weight) in weights.iter().enumerate() { assert_ok!(SubtensorModule::set_weights( RuntimeOrigin::signed(U256::from(uid as u64)), @@ -2744,7 +2760,7 @@ fn test_yuma_3_kappa_moves_first() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { let n: u16 = 5; // 3 validators, 2 servers - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_stake: u64 = 8; // Validator A: kappa / Big validator (0.8) - moves first @@ -2847,7 +2863,7 @@ fn test_yuma_3_kappa_moves_second() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { let n: u16 = 5; // 3 validators, 2 servers - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_stake: u64 = 8; // Validator A: kappa / Big validator (0.8) - moves second @@ -2949,7 +2965,7 @@ fn test_yuma_3_kappa_moves_last() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { let n: u16 = 5; // 3 validators, 2 servers - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_stake: u64 = 8; // Validator A: kappa / Big validator (0.8) - moves last @@ -3051,7 +3067,7 @@ fn test_yuma_3_one_epoch_switch() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { let n: u16 = 5; // 3 validators, 2 servers - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_stake: u64 = 8; // Equal stake validators @@ -3136,7 +3152,7 @@ fn test_yuma_3_one_epoch_switch() { fn test_yuma_3_liquid_alpha_disabled() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let n: u16 = 5; // 3 validators, 2 servers let max_stake: u64 = 8; @@ -3225,7 +3241,7 @@ fn test_yuma_3_liquid_alpha_disabled() { fn test_yuma_3_stable_miner() { for sparse in [true, false].iter() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let n: u16 = 6; // 3 validators, 3 servers let max_stake: u64 = 8; @@ -3340,7 +3356,7 @@ fn test_yuma_3_bonds_reset() { new_test_ext(1).execute_with(|| { let sparse: bool = true; let n: u16 = 5; // 3 validators, 2 servers - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_stake: u64 = 8; // "Case 8 - big vali moves late, then late" @@ -3480,3 +3496,45 @@ fn test_yuma_3_bonds_reset() { } }) } + +#[test] +fn test_liquid_alpha_equal_values_against_itself() { + new_test_ext(1).execute_with(|| { + // check Liquid alpha disabled against Liquid Alpha enabled with alpha_low == alpha_high + let netuid: NetUid = NetUid::from(1); + let alpha_low = u16::MAX / 10; + let alpha_high = u16::MAX / 10; + let epsilon = I32F32::from_num(1e-3); + let weights: Vec> = vec_to_mat_fixed( + &[0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0.4, 0.5], + 4, + false, + ); + let bonds: Vec> = vec_to_mat_fixed( + &[0.1, 0.1, 0.5, 0., 0., 0.4, 0.5, 0.1, 0.1, 0., 0.4, 0.2], + 4, + false, + ); + let consensus: Vec = vec_to_fixed(&[0.3, 0.2, 0.1, 0.4]); + + // set both alpha values to 0.1 and bonds moving average to 0.9 + AlphaValues::::insert(netuid, (alpha_low, alpha_high)); + SubtensorModule::set_bonds_moving_average(netuid.into(), 900_000); + + // compute bonds with liquid alpha enabled + SubtensorModule::set_liquid_alpha_enabled(netuid.into(), true); + let new_bonds_liquid_alpha_on = + SubtensorModule::compute_bonds(netuid.into(), &weights, &bonds, &consensus); + + // compute bonds with liquid alpha disabled + SubtensorModule::set_liquid_alpha_enabled(netuid.into(), false); + let new_bonds_liquid_alpha_off = + SubtensorModule::compute_bonds(netuid.into(), &weights, &bonds, &consensus); + + assert_mat_compare( + &new_bonds_liquid_alpha_on, + &new_bonds_liquid_alpha_off, + epsilon, + ); + }); +} diff --git a/pallets/subtensor/src/tests/evm.rs b/pallets/subtensor/src/tests/evm.rs index fd0ea51061..a65e69c207 100644 --- a/pallets/subtensor/src/tests/evm.rs +++ b/pallets/subtensor/src/tests/evm.rs @@ -32,7 +32,7 @@ fn sign_evm_message>(pair: &ecdsa::Pair, message: M) -> ecdsa::Si #[test] fn test_associate_evm_key_success() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -58,9 +58,8 @@ fn test_associate_evm_key_success() { let signature = sign_evm_message(&pair, message); assert_ok!(SubtensorModule::associate_evm_key( - RuntimeOrigin::signed(coldkey), + RuntimeOrigin::signed(hotkey), netuid, - hotkey, evm_key, block_number, signature, @@ -81,7 +80,7 @@ fn test_associate_evm_key_success() { #[test] fn test_associate_evm_key_different_block_number_success() { new_test_ext(100).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -105,9 +104,8 @@ fn test_associate_evm_key_different_block_number_success() { let signature = sign_evm_message(&pair, message); assert_ok!(SubtensorModule::associate_evm_key( - RuntimeOrigin::signed(coldkey), + RuntimeOrigin::signed(hotkey), netuid, - hotkey, evm_key, block_number, signature, @@ -125,47 +123,10 @@ fn test_associate_evm_key_different_block_number_success() { }); } -#[test] -fn test_associate_evm_key_coldkey_does_not_own_hotkey() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - - let tempo: u16 = 2; - let modality: u16 = 2; - - add_network(netuid, tempo, modality); - - let coldkey = U256::from(1); - let hotkey = U256::from(2); - - let pair = ecdsa::Pair::generate().0; - let public = pair.public(); - let evm_key = public_to_evm_key(&public); - let block_number = frame_system::Pallet::::block_number(); - let hashed_block_number = keccak_256(block_number.encode().as_ref()); - let hotkey_bytes = hotkey.encode(); - - let message = [hotkey_bytes.as_ref(), hashed_block_number.as_ref()].concat(); - let signature = sign_evm_message(&pair, message); - - assert_err!( - SubtensorModule::associate_evm_key( - RuntimeOrigin::signed(coldkey), - netuid, - hotkey, - evm_key, - block_number, - signature, - ), - Error::::NonAssociatedColdKey - ); - }); -} - #[test] fn test_associate_evm_key_hotkey_not_registered_in_subnet() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -188,9 +149,8 @@ fn test_associate_evm_key_hotkey_not_registered_in_subnet() { assert_err!( SubtensorModule::associate_evm_key( - RuntimeOrigin::signed(coldkey), + RuntimeOrigin::signed(hotkey), netuid, - hotkey, evm_key, block_number, signature, @@ -203,7 +163,7 @@ fn test_associate_evm_key_hotkey_not_registered_in_subnet() { #[test] fn test_associate_evm_key_using_wrong_hash_function() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -229,9 +189,8 @@ fn test_associate_evm_key_using_wrong_hash_function() { assert_err!( SubtensorModule::associate_evm_key( - RuntimeOrigin::signed(coldkey), + RuntimeOrigin::signed(hotkey), netuid, - hotkey, evm_key, block_number, signature, diff --git a/pallets/subtensor/src/tests/math.rs b/pallets/subtensor/src/tests/math.rs index 01e02742b7..1db3622373 100644 --- a/pallets/subtensor/src/tests/math.rs +++ b/pallets/subtensor/src/tests/math.rs @@ -41,7 +41,7 @@ fn assert_vec_compare_u16(va: &[u16], vb: &[u16]) { } } -fn assert_mat_compare(ma: &[Vec], mb: &[Vec], epsilon: I32F32) { +pub fn assert_mat_compare(ma: &[Vec], mb: &[Vec], epsilon: I32F32) { assert!(ma.len() == mb.len()); for row in 0..ma.len() { assert!(ma[row].len() == mb[row].len()); @@ -72,7 +72,7 @@ fn assert_sparse_mat_compare( } } -fn vec_to_fixed(vector: &[f32]) -> Vec { +pub fn vec_to_fixed(vector: &[f32]) -> Vec { vector.iter().map(|x| I32F32::from_num(*x)).collect() } @@ -365,7 +365,7 @@ fn test_math_vec_to_fixed() { } // Reshape vector to matrix with specified number of rows, cast to I32F32. -fn vec_to_mat_fixed(vector: &[f32], rows: usize, transpose: bool) -> Vec> { +pub fn vec_to_mat_fixed(vector: &[f32], rows: usize, transpose: bool) -> Vec> { assert!( vector.len() % rows == 0, "Vector of len {:?} cannot reshape to {rows} rows.", diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 1dfac06ad5..adb4601724 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -37,8 +37,8 @@ fn test_initialise_ti() { new_test_ext(1).execute_with(|| { pallet_balances::TotalIssuance::::put(1000); - crate::SubnetTAO::::insert(1, 100); - crate::SubnetTAO::::insert(2, 5); + crate::SubnetTAO::::insert(NetUid::from(1), 100); + crate::SubnetTAO::::insert(NetUid::from(2), 5); // Ensure values are NOT initialized prior to running migration assert!(crate::TotalIssuance::::get() == 0); @@ -59,11 +59,11 @@ fn test_initialise_ti() { fn test_migration_transfer_nets_to_foundation() { new_test_ext(1).execute_with(|| { // Create subnet 1 - add_network(1, 1, 0); + add_network(1.into(), 1, 0); // Create subnet 11 - add_network(11, 1, 0); + add_network(11.into(), 1, 0); - log::info!("{:?}", SubtensorModule::get_subnet_owner(1)); + log::info!("{:?}", SubtensorModule::get_subnet_owner(1.into())); //assert_eq!(SubtensorModule::::get_subnet_owner(1), ); // Run the migration to transfer ownership @@ -71,7 +71,7 @@ fn test_migration_transfer_nets_to_foundation() { hex_literal::hex!["feabaafee293d3b76dae304e2f9d885f77d2b17adab9e17e921b321eccd61c77"]; crate::migrations::migrate_transfer_ownership_to_foundation::migrate_transfer_ownership_to_foundation::(hex); - log::info!("new owner: {:?}", SubtensorModule::get_subnet_owner(1)); + log::info!("new owner: {:?}", SubtensorModule::get_subnet_owner(1.into())); }) } @@ -79,13 +79,13 @@ fn test_migration_transfer_nets_to_foundation() { fn test_migration_delete_subnet_3() { new_test_ext(1).execute_with(|| { // Create subnet 3 - add_network(3, 1, 0); - assert!(SubtensorModule::if_subnet_exist(3)); + add_network(3.into(), 1, 0); + assert!(SubtensorModule::if_subnet_exist(3.into())); // Run the migration to transfer ownership crate::migrations::migrate_delete_subnet_3::migrate_delete_subnet_3::(); - assert!(!SubtensorModule::if_subnet_exist(3)); + assert!(!SubtensorModule::if_subnet_exist(3.into())); }) } @@ -93,13 +93,13 @@ fn test_migration_delete_subnet_3() { fn test_migration_delete_subnet_21() { new_test_ext(1).execute_with(|| { // Create subnet 21 - add_network(21, 1, 0); - assert!(SubtensorModule::if_subnet_exist(21)); + add_network(21.into(), 1, 0); + assert!(SubtensorModule::if_subnet_exist(21.into())); // Run the migration to transfer ownership crate::migrations::migrate_delete_subnet_21::migrate_delete_subnet_21::(); - assert!(!SubtensorModule::if_subnet_exist(21)); + assert!(!SubtensorModule::if_subnet_exist(21.into())); }) } @@ -115,7 +115,7 @@ fn test_migrate_commit_reveal_2() { let storage_prefix_interval = twox_128("WeightCommitRevealInterval".as_bytes()); let storage_prefix_commits = twox_128("WeightCommits".as_bytes()); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let interval_value: u64 = 50u64; // Construct the full key for WeightCommitRevealInterval @@ -385,7 +385,7 @@ fn test_migrate_commit_reveal_2() { fn test_migrate_subnet_volume() { new_test_ext(1).execute_with(|| { // Setup initial state - let netuid_1: u16 = 1; + let netuid_1 = NetUid::from(1); add_network(netuid_1, 1, 0); // SubnetValue for netuid 1 key @@ -422,7 +422,7 @@ fn test_migrate_subnet_volume() { #[test] fn test_migrate_set_first_emission_block_number() { new_test_ext(1).execute_with(|| { - let netuids: [u16; 3] = [1, 2, 3]; + let netuids: [NetUid; 3] = [1.into(), 2.into(), 3.into()]; let block_number = 100; for netuid in netuids.iter() { add_network(*netuid, 1, 0); @@ -433,7 +433,7 @@ fn test_migrate_set_first_emission_block_number() { let expected_weight: Weight = ::DbWeight::get().reads(3) + ::DbWeight::get().writes(netuids.len() as u64); assert_eq!(weight, expected_weight); - assert_eq!(FirstEmissionBlockNumber::::get(0), None); + assert_eq!(FirstEmissionBlockNumber::::get(NetUid::ROOT), None); for netuid in netuids.iter() { assert_eq!(FirstEmissionBlockNumber::::get(netuid), Some(block_number)); } @@ -443,13 +443,13 @@ fn test_migrate_set_first_emission_block_number() { #[test] fn test_migrate_set_subtoken_enable() { new_test_ext(1).execute_with(|| { - let netuids: [u16; 3] = [1, 2, 3]; + let netuids: [NetUid; 3] = [1.into(), 2.into(), 3.into()]; let block_number = 100; for netuid in netuids.iter() { add_network(*netuid, 1, 0); } - let new_netuid = 4; + let new_netuid = NetUid::from(4); add_network_without_emission_block(new_netuid, 1, 0); let weight = @@ -470,7 +470,7 @@ fn test_migrate_set_subtoken_enable() { fn test_migrate_remove_zero_total_hotkey_alpha() { new_test_ext(1).execute_with(|| { const MIGRATION_NAME: &str = "migrate_remove_zero_total_hotkey_alpha"; - let netuid = 1u16; + let netuid = NetUid::from(1u16); let hotkey_zero = U256::from(100u64); let hotkey_nonzero = U256::from(101u64); @@ -524,7 +524,7 @@ fn test_migrate_revealed_commitments() { // Example keys for the DoubleMap: // Key1 (netuid) uses Identity (no hash) // Key2 (account) uses Twox64Concat - let netuid: u16 = 123; + let netuid = NetUid::from(123); let account_id: u64 = 999; // Or however your test `AccountId` is represented // Construct the full storage key for `RevealedCommitments(netuid, account_id)` diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index d5d302d5c1..d47fbc1ea6 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -1,8 +1,11 @@ #![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] -use crate::utils::rate_limiting::TransactionType; + +use core::num::NonZeroU64; + +use frame_support::PalletId; use frame_support::derive_impl; use frame_support::dispatch::DispatchResultWithPostInfo; -use frame_support::traits::{Contains, Everything, InsideBoth}; +use frame_support::traits::{Contains, Everything, InherentBuilder, InsideBoth}; use frame_support::weights::Weight; use frame_support::weights::constants::RocksDbWeight; use frame_support::{ @@ -10,7 +13,7 @@ use frame_support::{ traits::{Hooks, PrivilegeCmp}, }; use frame_system as system; -use frame_system::{EnsureNever, EnsureRoot, RawOrigin, limits}; +use frame_system::{EnsureNever, EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase}; use pallet_collective::MemberCount; use sp_core::{ConstU64, Get, H256, U256, offchain::KeyTypeId}; use sp_runtime::Perbill; @@ -19,7 +22,10 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, }; use sp_std::cmp::Ordering; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler}; +use crate::utils::rate_limiting::TransactionType; use crate::*; type Block = frame_system::mocking::MockBlock; @@ -39,6 +45,7 @@ frame_support::construct_runtime!( Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 9, Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 10, Drand: pallet_drand::{Pallet, Call, Storage, Event} = 11, + Swap: pallet_subtensor_swap::{Pallet, Call, Storage, Event} = 12, } ); @@ -54,8 +61,6 @@ pub type BalanceCall = pallet_balances::Call; #[allow(dead_code)] pub type TestRuntimeCall = frame_system::Call; -pub type Index = u64; - pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test"); #[allow(dead_code)] @@ -155,7 +160,7 @@ parameter_types! { pub const TransactionByteFee: Balance = 100; pub const SDebug:u64 = 1; pub const InitialRho: u16 = 30; - pub const InitialAlphaSigmoidSteepness: u16 = 10; + pub const InitialAlphaSigmoidSteepness: i16 = 1000; pub const InitialKappa: u16 = 32_767; pub const InitialTempo: u16 = 360; pub const SelfOwnership: u64 = 2; @@ -213,6 +218,9 @@ parameter_types! { pub const InitialTaoWeight: u64 = 0; // 100% global weight. pub const InitialEmaPriceHalvingPeriod: u64 = 201_600_u64; // 4 weeks pub const DurationOfStartCall: u64 = 7 * 24 * 60 * 60 / 12; // Default as 7 days + pub const InitialKeySwapOnSubnetCost: u64 = 10_000_000; + pub const HotkeySwapOnSubnetInterval: u64 = 15; // 15 block, should be bigger than subnet number, then trigger clean up for all subnets + } // Configure collective pallet for council @@ -441,6 +449,30 @@ impl crate::Config for Test { type InitialTaoWeight = InitialTaoWeight; type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod; type DurationOfStartCall = DurationOfStartCall; + type SwapInterface = Swap; + type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost; + type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval; +} + +// Swap-related parameter types +parameter_types! { + pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap"); + pub const SwapMaxFeeRate: u16 = 10000; // 15.26% + pub const SwapMaxPositions: u32 = 100; + pub const SwapMinimumLiquidity: u64 = 1_000; + pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(100).unwrap(); +} + +impl pallet_subtensor_swap::Config for Test { + type RuntimeEvent = RuntimeEvent; + type SubnetInfo = SubtensorModule; + type BalanceOps = SubtensorModule; + type ProtocolId = SwapProtocolId; + type MaxFeeRate = SwapMaxFeeRate; + type MaxPositions = SwapMaxPositions; + type MinimumLiquidity = SwapMinimumLiquidity; + type MinimumReserve = SwapMinimumReserve; + type WeightInfo = (); } pub struct OriginPrivilegeCmp; @@ -526,14 +558,6 @@ mod test_crypto { pub type TestAuthId = test_crypto::TestAuthId; -impl frame_system::offchain::SendTransactionTypes for Test -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; -} - impl pallet_drand::Config for Test { type RuntimeEvent = RuntimeEvent; type AuthorityId = TestAuthId; @@ -549,17 +573,36 @@ impl frame_system::offchain::SigningTypes for Test { pub type UncheckedExtrinsic = sp_runtime::testing::TestXt; -impl frame_system::offchain::CreateSignedTransaction> for Test { - fn create_transaction>( - call: RuntimeCall, +impl frame_system::offchain::CreateTransactionBase for Test +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateInherent for Test +where + RuntimeCall: From, +{ + fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic { + UncheckedExtrinsic::new_inherent(call) + } +} + +impl frame_system::offchain::CreateSignedTransaction for Test +where + RuntimeCall: From, +{ + fn create_signed_transaction< + C: frame_system::offchain::AppCrypto, + >( + call: >::RuntimeCall, _public: Self::Public, _account: Self::AccountId, - nonce: Index, - ) -> Option<( - RuntimeCall, - ::SignaturePayload, - )> { - Some((call, (nonce, ()))) + nonce: Self::Nonce, + ) -> Option { + Some(UncheckedExtrinsic::new_signed(call, nonce.into(), (), ())) } } @@ -632,7 +675,7 @@ pub(crate) fn run_to_block_ext(n: u64, enable_events: bool) { } #[allow(dead_code)] -pub(crate) fn next_block_no_epoch(netuid: u16) -> u64 { +pub(crate) fn next_block_no_epoch(netuid: NetUid) -> u64 { // high tempo to skip automatic epochs in on_initialize let high_tempo: u16 = u16::MAX - 1; let old_tempo: u16 = SubtensorModule::get_tempo(netuid); @@ -645,7 +688,7 @@ pub(crate) fn next_block_no_epoch(netuid: u16) -> u64 { } #[allow(dead_code)] -pub(crate) fn run_to_block_no_epoch(netuid: u16, n: u64) { +pub(crate) fn run_to_block_no_epoch(netuid: NetUid, n: u64) { // high tempo to skip automatic epochs in on_initialize let high_tempo: u16 = u16::MAX - 1; let old_tempo: u16 = SubtensorModule::get_tempo(netuid); @@ -656,7 +699,7 @@ pub(crate) fn run_to_block_no_epoch(netuid: u16, n: u64) { } #[allow(dead_code)] -pub(crate) fn step_epochs(count: u16, netuid: u16) { +pub(crate) fn step_epochs(count: u16, netuid: NetUid) { for _ in 0..count { let blocks_to_next_epoch = SubtensorModule::blocks_until_next_epoch( netuid, @@ -690,7 +733,7 @@ pub(crate) fn next_block() -> u64 { #[allow(dead_code)] pub fn register_ok_neuron( - netuid: u16, + netuid: NetUid, hotkey_account_id: U256, coldkey_account_id: U256, start_nonce: u64, @@ -721,7 +764,7 @@ pub fn register_ok_neuron( } #[allow(dead_code)] -pub fn add_network(netuid: u16, tempo: u16, _modality: u16) { +pub fn add_network(netuid: NetUid, tempo: u16, _modality: u16) { SubtensorModule::init_new_network(netuid, tempo); SubtensorModule::set_network_registration_allowed(netuid, true); SubtensorModule::set_network_pow_registration_allowed(netuid, true); @@ -730,14 +773,14 @@ pub fn add_network(netuid: u16, tempo: u16, _modality: u16) { } #[allow(dead_code)] -pub fn add_network_without_emission_block(netuid: u16, tempo: u16, _modality: u16) { +pub fn add_network_without_emission_block(netuid: NetUid, tempo: u16, _modality: u16) { SubtensorModule::init_new_network(netuid, tempo); SubtensorModule::set_network_registration_allowed(netuid, true); SubtensorModule::set_network_pow_registration_allowed(netuid, true); } #[allow(dead_code)] -pub fn add_network_disable_subtoken(netuid: u16, tempo: u16, _modality: u16) { +pub fn add_network_disable_subtoken(netuid: NetUid, tempo: u16, _modality: u16) { SubtensorModule::init_new_network(netuid, tempo); SubtensorModule::set_network_registration_allowed(netuid, true); SubtensorModule::set_network_pow_registration_allowed(netuid, true); @@ -745,7 +788,7 @@ pub fn add_network_disable_subtoken(netuid: u16, tempo: u16, _modality: u16) { } #[allow(dead_code)] -pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> u16 { +pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost); @@ -762,7 +805,7 @@ pub fn add_dynamic_network(hotkey: &U256, coldkey: &U256) -> u16 { } #[allow(dead_code)] -pub fn add_dynamic_network_without_emission_block(hotkey: &U256, coldkey: &U256) -> u16 { +pub fn add_dynamic_network_without_emission_block(hotkey: &U256, coldkey: &U256) -> NetUid { let netuid = SubtensorModule::get_next_netuid(); let lock_cost = SubtensorModule::get_network_lock_cost(); SubtensorModule::add_balance_to_coldkey_account(coldkey, lock_cost); @@ -778,20 +821,20 @@ pub fn add_dynamic_network_without_emission_block(hotkey: &U256, coldkey: &U256) // Helper function to set up a neuron with stake #[allow(dead_code)] -pub fn setup_neuron_with_stake(netuid: u16, hotkey: U256, coldkey: U256, stake: u64) { +pub fn setup_neuron_with_stake(netuid: NetUid, hotkey: U256, coldkey: U256, stake: u64) { register_ok_neuron(netuid, hotkey, coldkey, stake); increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake, netuid); } #[allow(dead_code)] -pub fn wait_set_pending_children_cooldown(netuid: u16) { +pub fn wait_set_pending_children_cooldown(netuid: NetUid) { let cooldown = DefaultPendingCooldown::::get(); step_block(cooldown as u16); // Wait for cooldown to pass step_epochs(1, netuid); // Run next epoch } #[allow(dead_code)] -pub fn wait_and_set_pending_children(netuid: u16) { +pub fn wait_and_set_pending_children(netuid: NetUid) { let original_block = System::block_number(); wait_set_pending_children_cooldown(netuid); SubtensorModule::do_set_pending_children(netuid); @@ -802,7 +845,7 @@ pub fn wait_and_set_pending_children(netuid: u16) { pub fn mock_schedule_children( coldkey: &U256, parent: &U256, - netuid: u16, + netuid: NetUid, child_vec: &[(u64, U256)], ) { // Set minimum stake for setting children @@ -818,13 +861,13 @@ pub fn mock_schedule_children( } #[allow(dead_code)] -pub fn mock_set_children(coldkey: &U256, parent: &U256, netuid: u16, child_vec: &[(u64, U256)]) { +pub fn mock_set_children(coldkey: &U256, parent: &U256, netuid: NetUid, child_vec: &[(u64, U256)]) { mock_schedule_children(coldkey, parent, netuid, child_vec); wait_and_set_pending_children(netuid); } #[allow(dead_code)] -pub fn mock_set_children_no_epochs(netuid: u16, parent: &U256, child_vec: &[(u64, U256)]) { +pub fn mock_set_children_no_epochs(netuid: NetUid, parent: &U256, child_vec: &[(u64, U256)]) { let backup_block = SubtensorModule::get_current_block_as_u64(); PendingChildKeys::::insert(netuid, parent, (child_vec, 0)); System::set_block_number(1); @@ -834,7 +877,7 @@ pub fn mock_set_children_no_epochs(netuid: u16, parent: &U256, child_vec: &[(u64 // Helper function to wait for the rate limit #[allow(dead_code)] -pub fn step_rate_limit(transaction_type: &TransactionType, netuid: u16) { +pub fn step_rate_limit(transaction_type: &TransactionType, netuid: NetUid) { // Check rate limit let limit = SubtensorModule::get_rate_limit_on_subnet(transaction_type, netuid); @@ -849,10 +892,16 @@ pub fn increase_stake_on_coldkey_hotkey_account( coldkey: &U256, hotkey: &U256, tao_staked: u64, - netuid: u16, + netuid: NetUid, ) { - let fee = 0; - SubtensorModule::stake_into_subnet(hotkey, coldkey, netuid, tao_staked, fee); + SubtensorModule::stake_into_subnet( + hotkey, + coldkey, + netuid, + tao_staked, + ::SwapInterface::max_price(), + ) + .unwrap(); } /// Increases the stake on the hotkey account under its owning coldkey. @@ -861,7 +910,7 @@ pub fn increase_stake_on_coldkey_hotkey_account( /// * `hotkey` - The hotkey account ID. /// * `increment` - The amount to be incremented. #[allow(dead_code)] -pub fn increase_stake_on_hotkey_account(hotkey: &U256, increment: u64, netuid: u16) { +pub fn increase_stake_on_hotkey_account(hotkey: &U256, increment: u64, netuid: NetUid) { increase_stake_on_coldkey_hotkey_account( &SubtensorModule::get_owning_coldkey_for_hotkey(hotkey), hotkey, @@ -869,3 +918,59 @@ pub fn increase_stake_on_hotkey_account(hotkey: &U256, increment: u64, netuid: u netuid, ); } + +pub(crate) fn setup_reserves(netuid: NetUid, tao: u64, alpha: u64) { + SubnetTAO::::set(netuid, tao); + SubnetAlphaIn::::set(netuid, alpha); +} + +pub(crate) fn swap_tao_to_alpha(netuid: NetUid, tao: u64) -> (u64, u64) { + if netuid.is_root() { + return (tao, 0); + } + + let result = ::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + tao, + ::SwapInterface::max_price(), + true, + ); + + assert_ok!(&result); + + let result = result.unwrap(); + + // we don't want to have silent 0 comparissons in tests + assert!(result.amount_paid_out > 0); + + (result.amount_paid_out, result.fee_paid) +} + +pub(crate) fn swap_alpha_to_tao(netuid: NetUid, alpha: u64) -> (u64, u64) { + if netuid.is_root() { + return (alpha, 0); + } + + println!( + "::SwapInterface::min_price() = {:?}", + ::SwapInterface::min_price() + ); + + let result = ::SwapInterface::swap( + netuid.into(), + OrderType::Sell, + alpha, + ::SwapInterface::min_price(), + true, + ); + + assert_ok!(&result); + + let result = result.unwrap(); + + // we don't want to have silent 0 comparissons in tests + assert!(result.amount_paid_out > 0); + + (result.amount_paid_out, result.fee_paid) +} diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index 161749a923..60fafacc22 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -22,5 +22,6 @@ mod staking2; mod subnet; mod swap_coldkey; mod swap_hotkey; +mod swap_hotkey_with_subnet; mod uids; mod weights; diff --git a/pallets/subtensor/src/tests/move_stake.rs b/pallets/subtensor/src/tests/move_stake.rs index dd85ab9075..34b03da6af 100644 --- a/pallets/subtensor/src/tests/move_stake.rs +++ b/pallets/subtensor/src/tests/move_stake.rs @@ -1,9 +1,16 @@ -use super::mock::*; -use crate::*; +#![allow(clippy::unwrap_used)] + use approx::assert_abs_diff_eq; use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::RawOrigin; use sp_core::{Get, U256}; +use sp_runtime::traits::TxBaseImplication; use substrate_fixed::types::{U64F64, U96F32}; +use subtensor_swap_interface::SwapHandler; + +use super::mock; +use super::mock::*; +use crate::*; // 1. test_do_move_success // Description: Test a successful move of stake between two hotkeys in the same subnet @@ -13,17 +20,23 @@ fn test_do_move_success() { new_test_ext(1).execute_with(|| { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let coldkey = U256::from(1); let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid.into(), + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -31,6 +44,8 @@ fn test_do_move_success() { ); // Perform the move + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid, alpha); + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, tao_equivalent); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -55,8 +70,8 @@ fn test_do_move_success() { &coldkey, netuid ), - stake_amount - 2 * fee, - epsilon = stake_amount / 1000 + expected_alpha, + epsilon = 1000 ); }); } @@ -75,7 +90,9 @@ fn test_do_move_different_subnets() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + + mock::setup_reserves(origin_netuid, stake_amount * 100, stake_amount * 100); + mock::setup_reserves(destination_netuid, stake_amount * 100, stake_amount * 100); // Set up initial stake and subnets SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); @@ -85,8 +102,9 @@ fn test_do_move_different_subnets() { &coldkey, origin_netuid, stake_amount, - fee, - ); + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -112,19 +130,16 @@ fn test_do_move_different_subnets() { ), 0 ); - let alpha_fee: U96F32 = - U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = U96F32::from_num(alpha) - * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid); + let fee = + ::SwapInterface::approx_fee_amount(destination_netuid.into(), alpha); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, &coldkey, destination_netuid ), - (expected_value - alpha_fee).to_num::(), - epsilon = (expected_value / 1000).to_num::() + alpha - (2 * fee), + epsilon = alpha / 1000 ); }); } @@ -141,9 +156,11 @@ fn test_do_move_nonexistent_subnet() { let coldkey = U256::from(1); let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); - let nonexistent_netuid = 99; // Assuming this subnet doesn't exist + let nonexistent_netuid = NetUid::from(99); // Assuming this subnet doesn't exist let stake_amount = 1_000_000; - let fee = 0; + + let reserve = stake_amount * 1000; + mock::setup_reserves(origin_netuid, reserve, reserve); // Set up initial stake SubtensorModule::stake_into_subnet( @@ -151,8 +168,9 @@ fn test_do_move_nonexistent_subnet() { &coldkey, origin_netuid, stake_amount, - fee, - ); + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -173,14 +191,13 @@ fn test_do_move_nonexistent_subnet() { ); // Check that the stake remains unchanged - assert_abs_diff_eq!( + assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, origin_netuid ), - stake_amount, - epsilon = 100 + alpha, ); }); } @@ -240,14 +257,22 @@ fn test_do_move_nonexistent_destination_hotkey() { let coldkey = U256::from(1); let origin_hotkey = U256::from(2); let nonexistent_destination_hotkey = U256::from(99); // Assuming this hotkey doesn't exist - let netuid = 1; + let netuid = NetUid::from(1); let stake_amount = 1_000_000; - let fee = 0; + + let reserve = stake_amount * 1000; + mock::setup_reserves(netuid, reserve, reserve); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); - let alpha = - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, fee); + let alpha = SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); // Attempt to move stake from a non-existent origin hotkey add_network(netuid, 1, 0); @@ -270,8 +295,9 @@ fn test_do_move_nonexistent_destination_hotkey() { &coldkey, netuid ), - stake_amount + alpha ); + assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &nonexistent_destination_hotkey, @@ -296,10 +322,18 @@ fn test_do_move_all_stake() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + + mock::setup_reserves(netuid, stake_amount * 10, stake_amount * 10); // Set up initial stake - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -327,14 +361,15 @@ fn test_do_move_all_stake() { ), 0 ); + let fee = ::SwapInterface::approx_fee_amount(netuid.into(), alpha); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, &coldkey, netuid ), - stake_amount - 2 * fee, - epsilon = stake_amount / 1000 + alpha - (2 * fee), + epsilon = alpha / 1000 ); }); } @@ -349,10 +384,17 @@ fn test_do_move_half_stake() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + mock::setup_reserves(netuid, stake_amount * 100, stake_amount * 100); // Set up initial stake - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -381,6 +423,7 @@ fn test_do_move_half_stake() { alpha / 2, epsilon = alpha / 1000 ); + let fee = ::SwapInterface::approx_fee_amount(netuid.into(), alpha); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, @@ -406,10 +449,16 @@ fn test_do_move_partial_stake() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let total_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, total_stake, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + total_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -417,6 +466,8 @@ fn test_do_move_partial_stake() { ); // Move partial stake + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid, alpha); + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, tao_equivalent); SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); assert_ok!(SubtensorModule::do_move_stake( @@ -443,8 +494,8 @@ fn test_do_move_partial_stake() { &coldkey, netuid ), - total_stake - 2 * fee, - epsilon = total_stake / 1000 + expected_alpha, + epsilon = 1000 ); }); } @@ -462,14 +513,21 @@ fn test_do_move_multiple_times() { let hotkey1 = U256::from(2); let hotkey2 = U256::from(3); let initial_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey1); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey2); - SubtensorModule::stake_into_subnet(&hotkey1, &coldkey, netuid, initial_stake, fee); + SubtensorModule::stake_into_subnet( + &hotkey1, + &coldkey, + netuid, + initial_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); // Move stake multiple times + let mut expected_alpha: u64 = 0; for _ in 0..3 { let alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey, netuid, @@ -485,6 +543,9 @@ fn test_do_move_multiple_times() { let alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, &coldkey, netuid, ); + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid, alpha2); + // we need expected_alpha before the last move, so we call it within the loop + expected_alpha = mock::swap_tao_to_alpha(netuid, tao_equivalent).0; assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), hotkey2, @@ -498,8 +559,8 @@ fn test_do_move_multiple_times() { // Check final stake distribution assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid), - initial_stake - 7 * fee, - epsilon = initial_stake / 1000 + expected_alpha, + epsilon = 1000, ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid), @@ -518,12 +579,21 @@ fn test_do_move_wrong_origin() { let wrong_coldkey = U256::from(99); let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); - let netuid = 1; + let netuid = NetUid::from(1); let stake_amount = DefaultMinStake::::get() * 10; - let fee = 0; + + let reserve = stake_amount * 1000; + mock::setup_reserves(netuid, reserve, reserve); // Set up initial stake - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -553,7 +623,7 @@ fn test_do_move_wrong_origin() { &coldkey, netuid ), - stake_amount + alpha ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -578,11 +648,17 @@ fn test_do_move_same_hotkey_fails() { let coldkey = U256::from(1); let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); @@ -620,12 +696,18 @@ fn test_do_move_event_emission() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, stake_amount, 0); // use 0 fee for precision + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -634,6 +716,7 @@ fn test_do_move_event_emission() { // Move stake and capture events System::reset_events(); + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid, alpha); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -651,7 +734,7 @@ fn test_do_move_event_emission() { netuid, destination_hotkey, netuid, - stake_amount - fee - 1, // Should be TAO equivalent + tao_equivalent, // Should be TAO equivalent ) .into(), ); @@ -672,7 +755,6 @@ fn test_do_move_storage_updates() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // Set up initial stake SubtensorModule::stake_into_subnet( @@ -680,8 +762,9 @@ fn test_do_move_storage_updates() { &coldkey, origin_netuid, stake_amount, - fee, - ); + ::SwapInterface::max_price(), + ) + .unwrap(); // Move stake SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); @@ -692,6 +775,8 @@ fn test_do_move_storage_updates() { origin_netuid, ); + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, alpha); + let (alpha2, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -710,18 +795,15 @@ fn test_do_move_storage_updates() { ), 0 ); - let alpha_fee = - U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let alpha2 = U96F32::from_num(alpha) * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, &coldkey, destination_netuid ), - (alpha2 - alpha_fee).to_num::(), - epsilon = alpha / 1000 + alpha2, + epsilon = 2 ); }); } @@ -738,18 +820,24 @@ fn test_do_move_max_values() { let origin_hotkey = U256::from(2); let destination_hotkey = U256::from(3); let max_stake = u64::MAX; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = 0; + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); // Set up initial stake with maximum value SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); // Add lots of liquidity to bypass low liquidity check - SubnetTAO::::insert(netuid, u64::MAX / 1000); - SubnetAlphaIn::::insert(netuid, u64::MAX / 1000); + let reserve = u64::MAX / 1000; + mock::setup_reserves(netuid, reserve, reserve); - SubtensorModule::stake_into_subnet(&origin_hotkey, &coldkey, netuid, max_stake, fee); + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + max_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, @@ -757,6 +845,7 @@ fn test_do_move_max_values() { ); // Move maximum stake + let (_, fee) = mock::swap_alpha_to_tao(netuid, alpha); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -775,14 +864,15 @@ fn test_do_move_max_values() { ), 0 ); + let alpha_after_fee = alpha - fee; assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, &coldkey, netuid ), - alpha, - epsilon = alpha / 1_000_000 + alpha_after_fee, + epsilon = alpha_after_fee / 100_000 ); }); } @@ -794,13 +884,15 @@ fn test_moving_too_little_unstakes() { let hotkey_account_id = U256::from(533453); let coldkey_account_id = U256::from(55453); let amount = DefaultMinStake::::get(); - let fee = DefaultStakingFee::::get(); //add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); - let netuid2: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid2 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give it some $$$ in his coldkey balance + + let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount + fee); assert_ok!(SubtensorModule::add_stake( @@ -831,7 +923,6 @@ fn test_do_transfer_success() { let subnet_owner_coldkey = U256::from(1001); let subnet_owner_hotkey = U256::from(1002); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = DefaultStakingFee::::get(); // 2. Define the origin coldkey, destination coldkey, and hotkey to be used. let origin_coldkey = U256::from(1); @@ -842,7 +933,14 @@ fn test_do_transfer_success() { // 3. Set up initial stake: (origin_coldkey, hotkey) on netuid. SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); SubtensorModule::create_account_if_non_existent(&destination_coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &origin_coldkey, netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &origin_coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &origin_coldkey, @@ -850,6 +948,8 @@ fn test_do_transfer_success() { ); // 4. Transfer the entire stake to the destination coldkey on the same subnet (netuid, netuid). + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid, alpha); + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, tao_equivalent); assert_ok!(SubtensorModule::do_transfer_stake( RuntimeOrigin::signed(origin_coldkey), destination_coldkey, @@ -874,8 +974,8 @@ fn test_do_transfer_success() { &destination_coldkey, netuid ), - stake_amount - fee, - epsilon = stake_amount / 1000 + expected_alpha, + epsilon = 1000 ); }); } @@ -886,7 +986,7 @@ fn test_do_transfer_nonexistent_subnet() { let origin_coldkey = U256::from(1); let destination_coldkey = U256::from(2); let hotkey = U256::from(3); - let nonexistent_netuid = 9999; + let nonexistent_netuid = NetUid::from(9999); let stake_amount = DefaultMinStake::::get() * 5; assert_noop!( @@ -941,7 +1041,14 @@ fn test_do_transfer_insufficient_stake() { let stake_amount = DefaultMinStake::::get() * 10; SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &origin_coldkey, netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &origin_coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = stake_amount * 2; assert_noop!( @@ -970,11 +1077,18 @@ fn test_do_transfer_wrong_origin() { let destination_coldkey = U256::from(2); let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&origin_coldkey, stake_amount + fee); - SubtensorModule::stake_into_subnet(&hotkey, &origin_coldkey, netuid, stake_amount, fee); + SubtensorModule::stake_into_subnet( + &hotkey, + &origin_coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); assert_noop!( SubtensorModule::do_transfer_stake( @@ -1003,7 +1117,14 @@ fn test_do_transfer_minimum_stake_check() { let stake_amount = DefaultMinStake::::get(); SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &origin_coldkey, netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &origin_coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); assert_err!( SubtensorModule::do_transfer_stake( @@ -1033,7 +1154,6 @@ fn test_do_transfer_different_subnets() { let destination_coldkey = U256::from(2); let hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); // 3. Create accounts if needed. SubtensorModule::create_account_if_non_existent(&origin_coldkey, &hotkey); @@ -1048,8 +1168,9 @@ fn test_do_transfer_different_subnets() { &origin_coldkey, origin_netuid, stake_amount, - 0, - ); + ::SwapInterface::max_price(), + ) + .unwrap(); // 6. Transfer entire stake from origin_netuid -> destination_netuid. let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1057,6 +1178,10 @@ fn test_do_transfer_different_subnets() { &origin_coldkey, origin_netuid, ); + + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, alpha); + let (expected_alpha, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); + assert_ok!(SubtensorModule::do_transfer_stake( RuntimeOrigin::signed(origin_coldkey), destination_coldkey, @@ -1077,17 +1202,14 @@ fn test_do_transfer_different_subnets() { ); // 8. Verify stake ended up in destination subnet for destination coldkey. - let dest_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, - &destination_coldkey, - destination_netuid, - ); - let expected_value = U96F32::from_num(stake_amount - fee) - / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( - dest_stake, - expected_value.to_num::(), - epsilon = (expected_value / 1000).to_num::() + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &destination_coldkey, + destination_netuid, + ), + expected_alpha, + epsilon = 1000 ); }); } @@ -1103,16 +1225,24 @@ fn test_do_swap_success() { let coldkey = U256::from(1); let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, origin_netuid, ); + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, alpha_before); + let (expected_alpha, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); assert_ok!(SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -1135,16 +1265,8 @@ fn test_do_swap_success() { &coldkey, destination_netuid, ); - let alpha_fee = - U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = U96F32::from_num(alpha_before) - * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid); - assert_abs_diff_eq!( - alpha_after, - (expected_value - alpha_fee).to_num::(), - epsilon = (expected_value / 1000).to_num::() - ); + + assert_abs_diff_eq!(alpha_after, expected_alpha, epsilon = 1000); }); } @@ -1153,8 +1275,8 @@ fn test_do_swap_nonexistent_subnet() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let nonexistent_netuid1: u16 = 9998; - let nonexistent_netuid2: u16 = 9999; + let nonexistent_netuid1 = NetUid::from(9998); + let nonexistent_netuid2 = NetUid::from(9999); let stake_amount = 1_000_000; SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); @@ -1211,7 +1333,14 @@ fn test_do_swap_insufficient_stake() { let attempted_swap = stake_amount * 2; SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid1, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid1, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); assert_noop!( SubtensorModule::do_swap_stake( @@ -1240,7 +1369,14 @@ fn test_do_swap_wrong_origin() { let stake_amount = 100_000; SubtensorModule::create_account_if_non_existent(&real_coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &real_coldkey, netuid1, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &real_coldkey, + netuid1, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); assert_noop!( SubtensorModule::do_swap_stake( @@ -1269,7 +1405,14 @@ fn test_do_swap_minimum_stake_check() { let swap_amount = 1; SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid1, total_stake, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid1, + total_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); assert_err!( SubtensorModule::do_swap_stake( @@ -1296,12 +1439,19 @@ fn test_do_swap_same_subnet() { let stake_amount = DefaultMinStake::::get() * 10; SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - assert_eq!( + assert_err!( SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -1309,13 +1459,12 @@ fn test_do_swap_same_subnet() { netuid, alpha_before ), - Err(Error::::SameNetuid.into()) + DispatchError::from(Error::::SameNetuid) ); let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - - assert_eq!(alpha_after, alpha_before,); + assert_eq!(alpha_after, alpha_before); }); } @@ -1330,12 +1479,20 @@ fn test_do_swap_partial_stake() { let coldkey = U256::from(1); let hotkey = U256::from(2); let total_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, total_stake, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + total_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); let swap_amount = total_stake / 2; + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, swap_amount); + let (expected_alpha, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); assert_ok!(SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -1350,23 +1507,8 @@ fn test_do_swap_partial_stake() { &coldkey, origin_netuid ), - total_stake - swap_amount, - epsilon = total_stake / 1000 - ); - - let alpha_fee = - U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = U96F32::from_num(swap_amount) - * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid); - assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, - &coldkey, - destination_netuid - ), - (expected_value - alpha_fee).to_num::(), - epsilon = (expected_value / 1000).to_num::() + expected_alpha, + epsilon = 1000 ); }); } @@ -1382,16 +1524,24 @@ fn test_do_swap_storage_updates() { let coldkey = U256::from(1); let hotkey = U256::from(2); let stake_amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, origin_netuid, ); + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, alpha); + let (expected_alpha, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); assert_ok!(SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -1409,19 +1559,14 @@ fn test_do_swap_storage_updates() { 0 ); - let alpha_fee = - U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = U96F32::from_num(alpha) - * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, destination_netuid ), - (expected_value - alpha_fee).to_num::(), - epsilon = (expected_value / 1000).to_num::() + expected_alpha, + epsilon = 1000 ); }); } @@ -1437,12 +1582,18 @@ fn test_do_swap_multiple_times() { let coldkey = U256::from(1); let hotkey = U256::from(2); let initial_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid1, initial_stake, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid1, + initial_stake, + ::SwapInterface::max_price(), + ) + .unwrap(); - let mut total_alpha1_fee = 0; + let mut expected_alpha: u64 = 0; for _ in 0..3 { let alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid1, @@ -1455,14 +1606,14 @@ fn test_do_swap_multiple_times() { netuid2, alpha1 )); - - let fee_as_alpha = SubtensorModule::swap_tao_for_alpha(netuid1, fee); - total_alpha1_fee += fee_as_alpha; } let alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid2, ); if alpha2 > 0 { + let (tao_equivalent, _) = mock::swap_alpha_to_tao(netuid2, alpha2); + // we do this in the loop, because we need the value before the swap + expected_alpha = mock::swap_tao_to_alpha(netuid1, tao_equivalent).0; assert_ok!(SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -1470,23 +1621,18 @@ fn test_do_swap_multiple_times() { netuid1, alpha2 )); - - let fee_as_alpha = SubtensorModule::swap_tao_for_alpha(netuid1, fee); - total_alpha1_fee += fee_as_alpha; } } - let final_stake_netuid1: u64 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid1); - let final_stake_netuid2 = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid2); - let expected_stake = initial_stake - total_alpha1_fee; assert_abs_diff_eq!( - final_stake_netuid1, - expected_stake, - epsilon = initial_stake / 10000 + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid1), + expected_alpha, + epsilon = 1000 + ); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid2), + 0 ); - assert_eq!(final_stake_netuid2, 0); }); } @@ -1505,7 +1651,14 @@ fn test_do_swap_allows_non_owned_hotkey() { let stake_amount = DefaultMinStake::::get() * 10; SubtensorModule::create_account_if_non_existent(&foreign_coldkey, &hotkey); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, stake_amount, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, @@ -1538,16 +1691,29 @@ fn test_swap_stake_limit_validate() { let hotkey = U256::from(2); let stake_amount = 100_000_000_000; + let reserve = 1_000_000_000_000; + mock::setup_reserves(origin_netuid, reserve, reserve); + mock::setup_reserves(destination_netuid, reserve, reserve); + SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - let unstake_amount = - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, stake_amount, 0); + let unstake_amount = SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); // Setup limit price so that it doesn't allow much slippage at all - let limit_price = ((SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid)) - * U96F32::from_num(1_000_000_000)) - .to_num::() - - 1_u64; + let limit_price = + ((::SwapInterface::current_alpha_price(origin_netuid.into()) + / ::SwapInterface::current_alpha_price( + destination_netuid.into(), + )) + * U96F32::from_num(1_000_000_000)) + .to_num::() + - 1_u64; // Swap stake limit call let call = RuntimeCall::SubtensorModule(SubtensorCall::swap_stake_limit { @@ -1562,16 +1728,22 @@ fn test_swap_stake_limit_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to slippage - assert_err!( - result_no_stake, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::SlippageTooHigh.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::SlippageTooHigh.into() ); }); } @@ -1593,8 +1765,14 @@ fn test_stake_transfers_disabled_validate() { let stake_amount = 100_000_000_000; SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - let unstake_amount = - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, origin_netuid, stake_amount, 0); + let unstake_amount = SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + origin_netuid, + stake_amount, + ::SwapInterface::max_price(), + ) + .unwrap(); // Swap stake limit call let call = RuntimeCall::SubtensorModule(SubtensorCall::transfer_stake { @@ -1608,19 +1786,25 @@ fn test_stake_transfers_disabled_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Disable transfers in origin subnet TransferToggle::::insert(origin_netuid, false); TransferToggle::::insert(destination_netuid, true); // Submit to the signed extension validate function - let result1 = extension.validate(&coldkey, &call.clone(), &info, 10); - assert_err!( - result1, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::TransferDisallowed.into() - )) + let result1 = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); + assert_eq!( + result1.unwrap_err(), + CustomTransactionError::TransferDisallowed.into() ); // Disable transfers in destination subnet @@ -1628,12 +1812,18 @@ fn test_stake_transfers_disabled_validate() { TransferToggle::::insert(destination_netuid, false); // Submit to the signed extension validate function - let result2 = extension.validate(&coldkey, &call.clone(), &info, 10); - assert_err!( - result2, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::TransferDisallowed.into() - )) + let result2 = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); + assert_eq!( + result2.unwrap_err(), + CustomTransactionError::TransferDisallowed.into() ); // Enable transfers @@ -1641,13 +1831,21 @@ fn test_stake_transfers_disabled_validate() { TransferToggle::::insert(destination_netuid, true); // Submit to the signed extension validate function - let result3 = extension.validate(&coldkey, &call.clone(), &info, 10); + let result3 = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); assert_ok!(result3); }); } #[test] -// RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_move_stake_specific_stake_into_subnet_fail --exact --show-output +// RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::move_stake::test_move_stake_specific_stake_into_subnet_fail --exact --show-output fn test_move_stake_specific_stake_into_subnet_fail() { new_test_ext(1).execute_with(|| { let sn_owner_coldkey = U256::from(55453); @@ -1666,9 +1864,9 @@ fn test_move_stake_specific_stake_into_subnet_fail() { let tao_staked = 200_000_000; //add network - let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); + let netuid = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); - let origin_netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); + let origin_netuid = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); // Register hotkey on netuid register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0); @@ -1720,6 +1918,8 @@ fn test_move_stake_specific_stake_into_subnet_fail() { ); // Move stake to destination subnet + let (tao_equivalent, _) = mock::swap_alpha_to_tao(origin_netuid, alpha_to_move); + let (expected_value, _) = mock::swap_tao_to_alpha(netuid, tao_equivalent); assert_ok!(SubtensorModule::move_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -1738,19 +1938,15 @@ fn test_move_stake_specific_stake_into_subnet_fail() { ), 0 ); - let fee = DefaultStakingFee::::get(); - let alpha_fee: U96F32 = U96F32::from_num(fee) / SubtensorModule::get_alpha_price(netuid); - let expected_value = U96F32::from_num(alpha_to_move) - * SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(netuid); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &coldkey_account_id, netuid ), - (expected_value - alpha_fee).to_num::(), - epsilon = (expected_value / 1000).to_num::() + expected_value, + epsilon = 1000 ); }); } diff --git a/pallets/subtensor/src/tests/networks.rs b/pallets/subtensor/src/tests/networks.rs index 7dda0502c1..ff14a641db 100644 --- a/pallets/subtensor/src/tests/networks.rs +++ b/pallets/subtensor/src/tests/networks.rs @@ -8,7 +8,7 @@ use sp_core::U256; fn test_registration_ok() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 2; + let netuid = NetUid::from(2); let tempo: u16 = 13; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har @@ -45,7 +45,7 @@ fn test_registration_ok() { // fn test_schedule_dissolve_network_execution() { // new_test_ext(1).execute_with(|| { // let block_number: u64 = 0; -// let netuid: u16 = 2; +// let netuid = NetUid::from(2); // let tempo: u16 = 13; // let hotkey_account_id: U256 = U256::from(1); // let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har @@ -97,7 +97,7 @@ fn test_registration_ok() { // fn test_non_owner_schedule_dissolve_network_execution() { // new_test_ext(1).execute_with(|| { // let block_number: u64 = 0; -// let netuid: u16 = 2; +// let netuid = NetUid::from(2); // let tempo: u16 = 13; // let hotkey_account_id: U256 = U256::from(1); // let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har @@ -151,7 +151,7 @@ fn test_registration_ok() { // fn test_new_owner_schedule_dissolve_network_execution() { // new_test_ext(1).execute_with(|| { // let block_number: u64 = 0; -// let netuid: u16 = 2; +// let netuid = NetUid::from(2); // let tempo: u16 = 13; // let hotkey_account_id: U256 = U256::from(1); // let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har @@ -209,7 +209,7 @@ fn test_registration_ok() { // fn test_schedule_dissolve_network_execution_with_coldkey_swap() { // new_test_ext(1).execute_with(|| { // let block_number: u64 = 0; -// let netuid: u16 = 2; +// let netuid = NetUid::from(2); // let tempo: u16 = 13; // let hotkey_account_id: U256 = U256::from(1); // let coldkey_account_id = U256::from(0); // Neighbour of the beast, har har @@ -294,7 +294,7 @@ fn test_register_subnet_low_lock_cost() { let subnet_owner_coldkey = U256::from(1); let subnet_owner_hotkey = U256::from(2); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); assert!(SubtensorModule::if_subnet_exist(netuid)); // Ensure that both Subnet TAO and Subnet Alpha In equal to (actual) lock_cost @@ -317,7 +317,7 @@ fn test_register_subnet_high_lock_cost() { let subnet_owner_coldkey = U256::from(1); let subnet_owner_hotkey = U256::from(2); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); assert!(SubtensorModule::if_subnet_exist(netuid)); // Ensure that both Subnet TAO and Subnet Alpha In equal to 100 TAO diff --git a/pallets/subtensor/src/tests/neuron_info.rs b/pallets/subtensor/src/tests/neuron_info.rs index c51c1e7dad..a954ef6e26 100644 --- a/pallets/subtensor/src/tests/neuron_info.rs +++ b/pallets/subtensor/src/tests/neuron_info.rs @@ -1,11 +1,12 @@ use super::mock::*; use sp_core::U256; +use subtensor_runtime_common::NetUid; #[test] fn test_get_neuron_none() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uid: u16 = 42; let neuron = SubtensorModule::get_neuron(netuid, uid); @@ -16,7 +17,7 @@ fn test_get_neuron_none() { #[test] fn test_get_neuron_some() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -37,7 +38,7 @@ fn test_get_neuron_some() { #[test] fn test_get_neurons_list() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 2; let modality: u16 = 2; @@ -62,7 +63,7 @@ fn test_get_neurons_list() { #[test] fn test_get_neurons_empty() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let neuron_count = 0; let neurons = SubtensorModule::get_neurons(netuid); diff --git a/pallets/subtensor/src/tests/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index b142e5d3c9..ef23d1807d 100644 --- a/pallets/subtensor/src/tests/recycle_alpha.rs +++ b/pallets/subtensor/src/tests/recycle_alpha.rs @@ -2,6 +2,7 @@ use approx::assert_abs_diff_eq; use frame_support::{assert_noop, assert_ok, traits::Currency}; use sp_core::U256; +use super::mock; use super::mock::*; use crate::*; @@ -82,6 +83,7 @@ fn test_recycle_two_stakers() { // add stake to coldkey-hotkey pair so we can recycle it let stake = 200_000; + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, stake); increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake, netuid); // add some stake to other coldkey on same hotkey. @@ -115,7 +117,7 @@ fn test_recycle_two_stakers() { &other_coldkey, netuid ), - stake, + expected_alpha, epsilon = 2 ); @@ -151,6 +153,7 @@ fn test_recycle_staker_is_nominator() { // add stake to coldkey-hotkey pair so we can recycle it let stake = 200_000; + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, stake); increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake, netuid); // add some stake to other coldkey on same hotkey. @@ -189,7 +192,7 @@ fn test_recycle_staker_is_nominator() { // Make sure the other coldkey has no change assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), - stake, + expected_alpha, epsilon = 2 ); @@ -279,6 +282,7 @@ fn test_burn_staker_is_nominator() { // add stake to coldkey-hotkey pair so we can recycle it let stake = 200_000; + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, stake); increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake, netuid); // add some stake to other coldkey on same hotkey. @@ -312,7 +316,7 @@ fn test_burn_staker_is_nominator() { // Make sure the other coldkey has no change assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), - stake, + expected_alpha, epsilon = 2 ); @@ -348,6 +352,7 @@ fn test_burn_two_stakers() { // add stake to coldkey-hotkey pair so we can recycle it let stake = 200_000; + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, stake); increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake, netuid); // add some stake to other coldkey on same hotkey. @@ -381,7 +386,7 @@ fn test_burn_two_stakers() { &other_coldkey, netuid ), - stake, + expected_alpha, epsilon = 2 ); @@ -422,7 +427,7 @@ fn test_recycle_errors() { RuntimeOrigin::signed(coldkey), hotkey, 100_000, - 99 // non-existent subnet + 99.into() // non-existent subnet ), Error::::SubNetworkDoesNotExist ); @@ -432,7 +437,7 @@ fn test_recycle_errors() { RuntimeOrigin::signed(coldkey), hotkey, 100_000, - SubtensorModule::get_root_netuid(), + NetUid::ROOT, ), Error::::CannotBurnOrRecycleOnRootSubnet ); @@ -504,7 +509,7 @@ fn test_burn_errors() { RuntimeOrigin::signed(coldkey), hotkey, 100_000, - 99 // non-existent subnet + 99.into() // non-existent subnet ), Error::::SubNetworkDoesNotExist ); @@ -514,7 +519,7 @@ fn test_burn_errors() { RuntimeOrigin::signed(coldkey), hotkey, 100_000, - SubtensorModule::get_root_netuid(), + NetUid::ROOT, ), Error::::CannotBurnOrRecycleOnRootSubnet ); diff --git a/pallets/subtensor/src/tests/registration.rs b/pallets/subtensor/src/tests/registration.rs index 3a8ce39ba3..084eda0b66 100644 --- a/pallets/subtensor/src/tests/registration.rs +++ b/pallets/subtensor/src/tests/registration.rs @@ -1,16 +1,18 @@ #![allow(clippy::unwrap_used)] use approx::assert_abs_diff_eq; -use frame_support::traits::Currency; - -use super::mock::*; -use crate::{AxonInfoOf, CustomTransactionError, Error, SubtensorSignedExtension}; use frame_support::dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}; -use frame_support::sp_runtime::{DispatchError, transaction_validity::InvalidTransaction}; +use frame_support::sp_runtime::{DispatchError, transaction_validity::TransactionSource}; +use frame_support::traits::Currency; use frame_support::{assert_err, assert_noop, assert_ok}; -use frame_system::Config; +use frame_system::{Config, RawOrigin}; use sp_core::U256; -use sp_runtime::traits::{DispatchInfoOf, SignedExtension}; +use sp_runtime::traits::{DispatchInfoOf, TransactionExtension, TxBaseImplication}; +use subtensor_runtime_common::NetUid; + +use super::mock; +use super::mock::*; +use crate::{AxonInfoOf, CustomTransactionError, Error, SubtensorTransactionExtension}; /******************************************** subscribing::subscribe() tests @@ -22,7 +24,7 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; let nonce: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let work: Vec = vec![0; 32]; let hotkey: U256 = U256::from(0); let coldkey: U256 = U256::from(0); @@ -37,7 +39,8 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(3_166_200_000, 0), + call_weight: frame_support::weights::Weight::from_parts(3_166_200_000, 0), + extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -48,7 +51,7 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { #[test] fn test_registration_difficulty() { new_test_ext(1).execute_with(|| { - assert_eq!(SubtensorModule::get_difficulty(1).as_u64(), 10000); + assert_eq!(SubtensorModule::get_difficulty(1.into()).as_u64(), 10000); }); } @@ -56,7 +59,7 @@ fn test_registration_difficulty() { fn test_registration_invalid_seal_hotkey() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id_1: U256 = U256::from(1); let hotkey_account_id_2: U256 = U256::from(2); @@ -103,7 +106,7 @@ fn test_registration_invalid_seal_hotkey() { fn test_registration_ok() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har @@ -159,7 +162,7 @@ fn test_registration_ok() { fn test_registration_without_neuron_slot() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har @@ -192,7 +195,7 @@ fn test_registration_without_neuron_slot() { #[test] fn test_registration_under_limit() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let block_number: u64 = 0; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); @@ -218,9 +221,17 @@ fn test_registration_under_limit() { }; let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); //does not actually call register - let result = extension.validate(&who, &call.into(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.into(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); assert_ok!(result); //actually call register @@ -244,7 +255,7 @@ fn test_registration_under_limit() { #[test] fn test_registration_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let block_number: u64 = 0; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); @@ -271,13 +282,21 @@ fn test_registration_rate_limit_exceeded() { }; let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); - let result = extension.validate(&who, &call.into(), &info, 10); + let extension = SubtensorTransactionExtension::::new(); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.into(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Expectation: The transaction should be rejected - assert_err!( - result, - InvalidTransaction::Custom(CustomTransactionError::RateLimitExceeded.into()) + assert_eq!( + result.unwrap_err(), + CustomTransactionError::RateLimitExceeded.into() ); let current_registrants = SubtensorModule::get_registrations_this_interval(netuid); @@ -292,7 +311,7 @@ fn test_registration_rate_limit_exceeded() { #[test] fn test_burned_registration_under_limit() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); let who: ::AccountId = coldkey_account_id; @@ -300,6 +319,9 @@ fn test_burned_registration_under_limit() { // Set the burn cost SubtensorModule::set_burn(netuid, burn_cost); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + add_network(netuid, 13, 0); // Add the network // Give it some TAO to the coldkey balance; more than the burn cost SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, burn_cost + 10_000); @@ -315,10 +337,17 @@ fn test_burned_registration_under_limit() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); //does not actually call register - let burned_register_result = - extension.validate(&who, &call_burned_register.into(), &info, 10); + let burned_register_result = extension.validate( + RawOrigin::Signed(who).into(), + &call_burned_register.into(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); assert_ok!(burned_register_result); //actually call register @@ -336,7 +365,7 @@ fn test_burned_registration_under_limit() { #[test] fn test_burned_registration_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); let who: ::AccountId = coldkey_account_id; @@ -355,14 +384,21 @@ fn test_burned_registration_rate_limit_exceeded() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); - let burned_register_result = - extension.validate(&who, &call_burned_register.into(), &info, 10); + let extension = SubtensorTransactionExtension::::new(); + let burned_register_result = extension.validate( + RawOrigin::Signed(who).into(), + &call_burned_register.into(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Expectation: The transaction should be rejected - assert_err!( - burned_register_result, - InvalidTransaction::Custom(CustomTransactionError::RateLimitExceeded.into()) + assert_eq!( + burned_register_result.unwrap_err(), + CustomTransactionError::RateLimitExceeded.into() ); let current_registrants = SubtensorModule::get_registrations_this_interval(netuid); @@ -374,7 +410,7 @@ fn test_burned_registration_rate_limit_exceeded() { fn test_burned_registration_rate_allows_burn_adjustment() { // We need to be able to register more than the *target* registrations per interval new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(667); let who: ::AccountId = coldkey_account_id; @@ -383,6 +419,9 @@ fn test_burned_registration_rate_allows_burn_adjustment() { // Set the burn cost SubtensorModule::set_burn(netuid, burn_cost); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + add_network(netuid, 13, 0); // Add the network // Give it some TAO to the coldkey balance; more than the burn cost SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, burn_cost + 10_000); @@ -400,10 +439,17 @@ fn test_burned_registration_rate_allows_burn_adjustment() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); //does not actually call register - let burned_register_result = - extension.validate(&who, &call_burned_register.into(), &info, 10); + let burned_register_result = extension.validate( + RawOrigin::Signed(who).into(), + &call_burned_register.into(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); assert_ok!(burned_register_result); //actually call register @@ -421,7 +467,7 @@ fn test_burned_registration_rate_allows_burn_adjustment() { #[test] fn test_burned_registration_ok() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let burn_cost = 1000; @@ -429,6 +475,10 @@ fn test_burned_registration_ok() { //add network SubtensorModule::set_burn(netuid, burn_cost); add_network(netuid, tempo, 0); + + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); // Subscribe and check extrinsic output @@ -468,7 +518,7 @@ fn test_burned_registration_ok() { #[test] fn test_burn_registration_without_neuron_slot() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let burn_cost = 1000; @@ -494,7 +544,7 @@ fn test_burn_registration_without_neuron_slot() { #[test] fn test_burn_registration_doesnt_write_on_failure() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let burn_cost = 1000; @@ -534,7 +584,7 @@ fn test_burn_registration_doesnt_write_on_failure() { #[test] fn test_burn_adjustment() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let init_burn_cost: u64 = InitialMinBurn::get() + 10_000; let adjustment_interval = 1; @@ -548,6 +598,9 @@ fn test_burn_adjustment() { target_registrations_per_interval, ); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Register key 1. let hotkey_account_id_1 = U256::from(1); let coldkey_account_id_1 = U256::from(1); @@ -585,7 +638,7 @@ fn test_burn_adjustment() { #[test] fn test_burn_registration_pruning_scenarios() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let burn_cost = 1000; let coldkey_account_id = U256::from(667); @@ -601,6 +654,9 @@ fn test_burn_registration_pruning_scenarios() { SubtensorModule::set_target_registrations_per_interval(netuid, max_allowed_uids); SubtensorModule::set_immunity_period(netuid, immunity_period); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + add_network(netuid, tempo, 0); let mint_balance = burn_cost * u64::from(max_allowed_uids) + 1_000_000_000; @@ -701,7 +757,7 @@ fn test_burn_registration_pruning_scenarios() { #[test] fn test_registration_too_many_registrations_per_block() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; add_network(netuid, tempo, 0); SubtensorModule::set_max_registrations_per_block(netuid, 10); @@ -897,7 +953,7 @@ fn test_registration_too_many_registrations_per_block() { #[test] fn test_registration_too_many_registrations_per_interval() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; add_network(netuid, tempo, 0); SubtensorModule::set_max_registrations_per_block(netuid, 11); @@ -1089,7 +1145,7 @@ fn test_registration_immunity_period() { //impl this test when epoch impl and ca fn test_registration_already_active_hotkey() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); @@ -1142,7 +1198,7 @@ fn test_registration_already_active_hotkey() { fn test_registration_invalid_seal() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); @@ -1170,7 +1226,7 @@ fn test_registration_invalid_block_number() { new_test_ext(1).execute_with(|| { System::set_block_number(0); let block_number: u64 = 1; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); @@ -1201,7 +1257,7 @@ fn test_registration_invalid_block_number() { fn test_registration_invalid_difficulty() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); @@ -1234,7 +1290,7 @@ fn test_registration_invalid_difficulty() { fn test_registration_failed_no_signature() { new_test_ext(1).execute_with(|| { let block_number: u64 = 1; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( @@ -1262,7 +1318,7 @@ fn test_registration_failed_no_signature() { fn test_registration_get_uid_to_prune_all_in_immunity_period() { new_test_ext(1).execute_with(|| { System::set_block_number(0); - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); log::info!("add network"); register_ok_neuron(netuid, U256::from(0), U256::from(0), 39420842); @@ -1278,7 +1334,7 @@ fn test_registration_get_uid_to_prune_all_in_immunity_period() { SubtensorModule::get_neuron_block_at_registration(netuid, 0), 0 ); - assert_eq!(SubtensorModule::get_neuron_to_prune(0), 0); + assert_eq!(SubtensorModule::get_neuron_to_prune(NetUid::ROOT), 0); }); } @@ -1286,7 +1342,7 @@ fn test_registration_get_uid_to_prune_all_in_immunity_period() { fn test_registration_get_uid_to_prune_none_in_immunity_period() { new_test_ext(1).execute_with(|| { System::set_block_number(0); - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); log::info!("add network"); register_ok_neuron(netuid, U256::from(0), U256::from(0), 39420842); @@ -1304,14 +1360,14 @@ fn test_registration_get_uid_to_prune_none_in_immunity_period() { ); step_block(3); assert_eq!(SubtensorModule::get_current_block_as_u64(), 3); - assert_eq!(SubtensorModule::get_neuron_to_prune(0), 0); + assert_eq!(SubtensorModule::get_neuron_to_prune(NetUid::ROOT), 0); }); } #[test] fn test_registration_pruning() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let block_number: u64 = 0; let tempo: u16 = 13; let hotkey_account_id = U256::from(1); @@ -1387,7 +1443,7 @@ fn test_registration_pruning() { #[test] fn test_registration_get_neuron_metadata() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let block_number: u64 = 0; let tempo: u16 = 13; let hotkey_account_id = U256::from(1); @@ -1423,8 +1479,8 @@ fn test_registration_get_neuron_metadata() { #[test] fn test_registration_add_network_size() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let netuid2: u16 = 2; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let block_number: u64 = 0; let hotkey_account_id = U256::from(1); let hotkey_account_id1 = U256::from(2); @@ -1493,8 +1549,8 @@ fn test_registration_add_network_size() { #[test] fn test_burn_registration_increase_recycled_rao() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let netuid2: u16 = 2; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(667); @@ -1503,6 +1559,10 @@ fn test_burn_registration_increase_recycled_rao() { let _ = Balances::deposit_creating(&coldkey_account_id, Balance::from(1_000_000_000_000_u64)); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid2, reserve, reserve); + add_network(netuid, 13, 0); assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 0); @@ -1542,9 +1602,9 @@ fn test_burn_registration_increase_recycled_rao() { fn test_full_pass_through() { new_test_ext(1).execute_with(|| { // Create 3 networks. - let netuid0: u16 = 1; - let netuid1: u16 = 2; - let netuid2: u16 = 3; + let netuid0 = NetUid::from(1); + let netuid1 = NetUid::from(2); + let netuid2 = NetUid::from(3); // With 3 tempos let tempo0: u16 = 2; @@ -1961,7 +2021,7 @@ fn test_full_pass_through() { fn test_registration_origin_hotkey_mismatch() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id_1: U256 = U256::from(1); let hotkey_account_id_2: U256 = U256::from(2); @@ -1996,7 +2056,7 @@ fn test_registration_origin_hotkey_mismatch() { fn test_registration_disabled() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id: U256 = U256::from(668); @@ -2032,7 +2092,7 @@ fn test_registration_disabled() { // #[test] // fn test_hotkey_swap_ok() { // new_test_ext(1).execute_with(|| { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let tempo: u16 = 13; // let hotkey_account_id = U256::from(1); // let burn_cost = 1000; @@ -2072,7 +2132,7 @@ fn test_registration_disabled() { // #[test] // fn test_hotkey_swap_not_owner() { // new_test_ext(1).execute_with(|| { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let tempo: u16 = 13; // let hotkey_account_id = U256::from(1); // let burn_cost = 1000; @@ -2108,7 +2168,7 @@ fn test_registration_disabled() { // #[test] // fn test_hotkey_swap_same_key() { // new_test_ext(1).execute_with(|| { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let tempo: u16 = 13; // let hotkey_account_id = U256::from(1); // let burn_cost = 1000; @@ -2142,7 +2202,7 @@ fn test_registration_disabled() { // #[test] // fn test_hotkey_swap_registered_key() { // new_test_ext(1).execute_with(|| { -// let netuid: u16 = 1; +// let netuid = NetUid::from(1); // let tempo: u16 = 13; // let hotkey_account_id = U256::from(1); // let burn_cost = 1000; diff --git a/pallets/subtensor/src/tests/senate.rs b/pallets/subtensor/src/tests/senate.rs index 52b0c240c2..3aeec0eb9a 100644 --- a/pallets/subtensor/src/tests/senate.rs +++ b/pallets/subtensor/src/tests/senate.rs @@ -1,24 +1,25 @@ #![allow(clippy::unwrap_used)] -use super::mock::*; -use crate::*; use approx::assert_abs_diff_eq; use codec::Encode; use frame_support::{assert_noop, assert_ok}; +use frame_system::Config; +use frame_system::pallet_prelude::*; use frame_system::{EventRecord, Phase}; +use pallet_collective::Event as CollectiveEvent; use sp_core::{Get, H256, U256, bounded_vec}; use sp_runtime::{ BuildStorage, traits::{BlakeTwo256, Hash}, }; +use subtensor_swap_interface::SwapHandler; +use super::mock; +use super::mock::*; +use crate::Delegates; use crate::Error; use crate::migrations; -use frame_system::Config; -use frame_system::pallet_prelude::*; -use pallet_collective::Event as CollectiveEvent; - -use crate::Delegates; +use crate::*; pub fn new_test_ext() -> sp_io::TestExternalities { sp_tracing::try_init_simple(); @@ -61,13 +62,12 @@ fn test_senate_join_works() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har let stake = DefaultMinStake::::get() * 100; - let fee = DefaultStakingFee::::get(); //add network SubtensorModule::set_burn(netuid, burn_cost); @@ -75,6 +75,9 @@ fn test_senate_join_works() { // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = 1_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -113,13 +116,13 @@ fn test_senate_join_works() { &staker_coldkey, netuid ), - stake - fee, - epsilon = 10 + stake, + epsilon = 1 ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake - fee, - epsilon = 10 + stake, + epsilon = 1 ); assert_ok!(SubtensorModule::root_register( @@ -135,13 +138,12 @@ fn test_senate_vote_works() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let senate_hotkey = U256::from(1); let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - let fee = DefaultStakingFee::::get(); //add network SubtensorModule::set_burn(netuid, burn_cost); @@ -149,6 +151,9 @@ fn test_senate_vote_works() { // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -181,19 +186,20 @@ fn test_senate_vote_works() { netuid, stake )); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &staker_coldkey, netuid ), - stake - fee, - epsilon = stake / 1000 + stake, + epsilon = 1 ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake - fee, - epsilon = stake / 1000 + stake, + epsilon = 1 ); assert_ok!(SubtensorModule::root_register( @@ -248,7 +254,7 @@ fn test_senate_vote_not_member() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let senate_hotkey = U256::from(1); let hotkey_account_id = U256::from(6); @@ -261,6 +267,9 @@ fn test_senate_vote_not_member() { // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -309,13 +318,12 @@ fn test_senate_leave_works() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har let stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); //add network SubtensorModule::set_burn(netuid, burn_cost); @@ -323,6 +331,9 @@ fn test_senate_leave_works() { // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = stake * 1000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -354,19 +365,20 @@ fn test_senate_leave_works() { netuid, stake )); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &staker_coldkey, netuid ), - stake - fee, - epsilon = stake / 1000 + stake, + epsilon = 1 ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake - fee, - epsilon = stake / 1000 + stake, + epsilon = 1 ); assert_ok!(SubtensorModule::root_register( @@ -382,7 +394,7 @@ fn test_senate_leave_vote_removal() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let senate_hotkey = U256::from(1); let hotkey_account_id = U256::from(6); @@ -390,7 +402,6 @@ fn test_senate_leave_vote_removal() { let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har let coldkey_origin = <::RuntimeOrigin>::signed(coldkey_account_id); let stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); //add network SubtensorModule::set_burn(netuid, burn_cost); @@ -399,6 +410,9 @@ fn test_senate_leave_vote_removal() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, stake); SubtokenEnabled::::insert(netuid, true); + let reserve = stake * 1000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( coldkey_origin.clone(), @@ -430,19 +444,20 @@ fn test_senate_leave_vote_removal() { netuid, stake )); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &staker_coldkey, netuid ), - stake - fee, - epsilon = 10 + stake, + epsilon = 1 ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake - fee, - epsilon = 10 + stake, + epsilon = 1 ); assert_ok!(SubtensorModule::root_register( @@ -472,20 +487,23 @@ fn test_senate_leave_vote_removal() { // Fill the root network with many large stake keys. // This removes all other keys. // Add two networks. - let root_netuid: u16 = 0; - let other_netuid: u16 = 5; + let other_netuid = NetUid::from(5); add_network(other_netuid, 1, 0); SubtensorModule::set_burn(other_netuid, 0); SubtensorModule::set_max_registrations_per_block(other_netuid, 1000); SubtensorModule::set_target_registrations_per_interval(other_netuid, 1000); - SubtensorModule::set_max_registrations_per_block(root_netuid, 1000); - SubtensorModule::set_target_registrations_per_interval(root_netuid, 1000); - SubtokenEnabled::::insert(root_netuid, true); + SubtensorModule::set_max_registrations_per_block(NetUid::ROOT, 1000); + SubtensorModule::set_target_registrations_per_interval(NetUid::ROOT, 1000); + + let reserve = 1_000_000_000_000; + mock::setup_reserves(other_netuid, reserve, reserve); + mock::setup_reserves(NetUid::ROOT, reserve, reserve); + SubtokenEnabled::::insert(NetUid::ROOT, true); SubtokenEnabled::::insert(other_netuid, true); for i in 0..200 { - let hot: U256 = U256::from(i + 100); - let cold: U256 = U256::from(i + 100); + let hot = U256::from(i + 100); + let cold = U256::from(i + 100); // Add balance SubtensorModule::add_balance_to_coldkey_account(&cold, 100_000_000 + (i as u64)); // lots ot stake // Register @@ -498,7 +516,7 @@ fn test_senate_leave_vote_removal() { assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(cold), hot, - root_netuid, + NetUid::ROOT, 100_000_000 + (i as u64) )); // Register them on the root network. @@ -508,13 +526,13 @@ fn test_senate_leave_vote_removal() { )); // Check succesfull registration. assert!(SubtensorModule::get_uid_for_net_and_hotkey(other_netuid, &hot).is_ok()); - assert!(SubtensorModule::get_uid_for_net_and_hotkey(root_netuid, &hot).is_ok()); + assert!(SubtensorModule::get_uid_for_net_and_hotkey(NetUid::ROOT, &hot).is_ok()); // Check that they are all delegates assert!(SubtensorModule::hotkey_is_delegate(&hot)); } // No longer a root member assert!( - SubtensorModule::get_uid_for_net_and_hotkey(root_netuid, &hotkey_account_id).is_err() + SubtensorModule::get_uid_for_net_and_hotkey(NetUid::ROOT, &hotkey_account_id).is_err() ); // No longer a member of the senate assert!(!Senate::is_member(&hotkey_account_id)); @@ -531,12 +549,11 @@ fn test_senate_not_leave_when_stake_removed() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); // Neighbour of the beast, har har - let fee = DefaultStakingFee::::get(); //add network SubtensorModule::set_burn(netuid, burn_cost); @@ -544,6 +561,9 @@ fn test_senate_not_leave_when_stake_removed() { // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -576,19 +596,20 @@ fn test_senate_not_leave_when_stake_removed() { netuid, stake_amount )); + assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &staker_coldkey, netuid ), - stake_amount - fee, - epsilon = stake_amount / 1000 + stake_amount, + epsilon = 1 ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake_amount - fee, - epsilon = stake_amount / 1000 + stake_amount, + epsilon = 1 ); assert_ok!(SubtensorModule::root_register( @@ -615,7 +636,7 @@ fn test_senate_join_current_delegate() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(6); let burn_cost = 1000; @@ -627,6 +648,9 @@ fn test_senate_join_current_delegate() { // Give some coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + let reserve = 1_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); + // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(coldkey_account_id), @@ -689,17 +713,21 @@ fn test_adjust_senate_events() { new_test_ext().execute_with(|| { migrations::migrate_create_root_network::migrate_create_root_network::(); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); - let root_netuid = SubtensorModule::get_root_netuid(); - let fee = DefaultStakingFee::::get(); let max_senate_size: u16 = SenateMaxMembers::get() as u16; - let stake_threshold: u64 = - DefaultMinStake::::get() + DefaultStakingFee::::get(); // Give this much to every senator + let stake_threshold = { + let default_stake = DefaultMinStake::::get(); + let fee = ::SwapInterface::approx_fee_amount( + netuid.into(), + default_stake, + ); + default_stake + fee + }; // We will be registering MaxMembers hotkeys and two more to try a replace let balance_to_add = DefaultMinStake::::get() * 10 @@ -717,10 +745,13 @@ fn test_adjust_senate_events() { // Allow all registrations in netuid in same block. Same for root network. SubtensorModule::set_max_registrations_per_block(netuid, max_senate_size + 1); SubtensorModule::set_target_registrations_per_interval(netuid, max_senate_size + 1); - SubtensorModule::set_max_registrations_per_block(root_netuid, max_senate_size + 1); - SubtensorModule::set_target_registrations_per_interval(root_netuid, max_senate_size + 1); + SubtensorModule::set_max_registrations_per_block(NetUid::ROOT, max_senate_size + 1); + SubtensorModule::set_target_registrations_per_interval(NetUid::ROOT, max_senate_size + 1); SubtokenEnabled::::insert(netuid, true); - SubtokenEnabled::::insert(root_netuid, true); + SubtokenEnabled::::insert(NetUid::ROOT, true); + + let reserve = 100_000_000_000_000; + mock::setup_reserves(netuid, reserve, reserve); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -808,17 +839,23 @@ fn test_adjust_senate_events() { assert!(!Senate::is_member(&replacement_hotkey_account_id)); // Add/delegate enough stake to join the senate let stake = DefaultMinStake::::get() * 10; + + let reserve = 100_000_000_000_000; + mock::setup_reserves(NetUid::ROOT, reserve, reserve); + + let (_, fee) = mock::swap_tao_to_alpha(NetUid::ROOT, stake); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(coldkey_account_id), replacement_hotkey_account_id, - root_netuid, + NetUid::ROOT, stake // Will be more than the last one in the senate by stake (has 0 stake) )); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &replacement_hotkey_account_id, &coldkey_account_id, - root_netuid + NetUid::ROOT ), stake - fee, epsilon = stake / 1000 @@ -826,7 +863,7 @@ fn test_adjust_senate_events() { assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet( &replacement_hotkey_account_id, - root_netuid + NetUid::ROOT ), stake - fee, epsilon = stake / 1000 diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index 251dde2078..e0471fd89b 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -1,15 +1,17 @@ +#![allow(clippy::unwrap_used)] use super::mock::*; use crate::Error; use crate::*; +use frame_support::assert_noop; use frame_support::pallet_prelude::Weight; -use frame_support::{assert_err, assert_noop}; use frame_support::{ assert_ok, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, }; -use frame_system::Config; +use frame_system::{Config, RawOrigin}; use sp_core::U256; +use sp_runtime::traits::TxBaseImplication; mod test { use std::net::{Ipv4Addr, Ipv6Addr}; @@ -32,7 +34,7 @@ mod test { #[test] fn test_serving_subscribe_ok_dispatch_info_ok() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version: u32 = 2; let ip: u128 = 1676056785; let port: u16 = 128; @@ -53,7 +55,8 @@ fn test_serving_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(235_670_000, 0), + call_weight: frame_support::weights::Weight::from_parts(235_670_000, 0), + extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -65,7 +68,7 @@ fn test_serving_subscribe_ok_dispatch_info_ok() { fn test_serving_ok() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -103,7 +106,7 @@ fn test_serving_ok() { fn test_serving_tls_ok() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -161,7 +164,7 @@ fn test_serving_tls_ok() { fn test_serving_set_metadata_update() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -225,7 +228,7 @@ fn test_serving_set_metadata_update() { fn test_axon_serving_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -307,7 +310,7 @@ fn test_axon_serving_rate_limit_exceeded() { fn test_axon_invalid_port() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -340,7 +343,7 @@ fn test_axon_invalid_port() { #[test] fn test_prometheus_serving_subscribe_ok_dispatch_info_ok() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version: u32 = 2; let ip: u128 = 1676056785; let port: u16 = 128; @@ -355,7 +358,8 @@ fn test_prometheus_serving_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(231_170_000, 0), + call_weight: frame_support::weights::Weight::from_parts(231_170_000, 0), + extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -367,7 +371,7 @@ fn test_prometheus_serving_subscribe_ok_dispatch_info_ok() { fn test_prometheus_serving_ok() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -396,7 +400,7 @@ fn test_prometheus_serving_ok() { fn test_prometheus_serving_set_metadata_update() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -442,7 +446,7 @@ fn test_prometheus_serving_set_metadata_update() { fn test_prometheus_serving_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -505,7 +509,7 @@ fn test_prometheus_serving_rate_limit_exceeded() { fn test_prometheus_invalid_port() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let version: u32 = 2; let ip: u128 = 1676056785; @@ -555,7 +559,14 @@ fn test_serving_is_valid_ip_address_ipv4() { new_test_ext(1).execute_with(|| { assert!(SubtensorModule::is_valid_ip_address( 4, - test::ipv4(8, 8, 8, 8) + test::ipv4(8, 8, 8, 8), + false + )); + + assert!(SubtensorModule::is_valid_ip_address( + 4, + test::ipv4(0, 0, 0, 0), + true )); }); } @@ -565,11 +576,18 @@ fn test_serving_is_valid_ip_address_ipv6() { new_test_ext(1).execute_with(|| { assert!(SubtensorModule::is_valid_ip_address( 6, - test::ipv6(1, 2, 3, 4, 5, 6, 7, 8) + test::ipv6(1, 2, 3, 4, 5, 6, 7, 8), + false )); assert!(SubtensorModule::is_valid_ip_address( 6, - test::ipv6(1, 2, 3, 4, 5, 6, 7, 8) + test::ipv6(1, 2, 3, 4, 5, 6, 7, 8), + false + )); + assert!(SubtensorModule::is_valid_ip_address( + 6, + test::ipv6(0, 0, 0, 0, 0, 0, 0, 0), + true )); }); } @@ -579,19 +597,38 @@ fn test_serving_is_invalid_ipv4_address() { new_test_ext(1).execute_with(|| { assert!(!SubtensorModule::is_valid_ip_address( 4, - test::ipv4(0, 0, 0, 0) + test::ipv4(0, 0, 0, 0), + false + )); + assert!(!SubtensorModule::is_valid_ip_address( + 4, + test::ipv4(255, 255, 255, 255), + false )); assert!(!SubtensorModule::is_valid_ip_address( 4, - test::ipv4(255, 255, 255, 255) + test::ipv4(127, 0, 0, 1), + false )); assert!(!SubtensorModule::is_valid_ip_address( 4, - test::ipv4(127, 0, 0, 1) + test::ipv6(0xffff, 2, 3, 4, 5, 6, 7, 8), + false )); assert!(!SubtensorModule::is_valid_ip_address( 4, - test::ipv6(0xffff, 2, 3, 4, 5, 6, 7, 8) + test::ipv4(255, 255, 255, 255), + true + )); + assert!(!SubtensorModule::is_valid_ip_address( + 4, + test::ipv4(127, 0, 0, 1), + true + )); + assert!(!SubtensorModule::is_valid_ip_address( + 4, + test::ipv6(0xffff, 2, 3, 4, 5, 6, 7, 8), + true )); }); } @@ -601,13 +638,22 @@ fn test_serving_is_invalid_ipv6_address() { new_test_ext(1).execute_with(|| { assert!(!SubtensorModule::is_valid_ip_address( 6, - test::ipv6(0, 0, 0, 0, 0, 0, 0, 0) + test::ipv6(0, 0, 0, 0, 0, 0, 0, 0), + false + )); + assert!(!SubtensorModule::is_valid_ip_address( + 4, + test::ipv6( + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + ), + false )); assert!(!SubtensorModule::is_valid_ip_address( 4, test::ipv6( 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff - ) + ), + true )); }); } @@ -618,7 +664,7 @@ fn test_do_set_identity() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid = 1; + let netuid = NetUid::from(1); // Register a hotkey for the coldkey add_network(netuid, 13, 0); @@ -805,7 +851,7 @@ fn test_set_and_get_identity() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid = 1; + let netuid = NetUid::from(1); // Register a hotkey for the coldkey add_network(netuid, 13, 0); @@ -947,7 +993,7 @@ fn test_migrate_identities_to_v2() { let old_subnet_contact = b"subnet@example".to_vec(); SubnetIdentities::::insert( - 42u16, + NetUid::from(42), SubnetIdentity { subnet_name: old_subnet_name.clone(), github_repo: old_github_repo.clone(), @@ -957,7 +1003,7 @@ fn test_migrate_identities_to_v2() { assert!(Identities::::get(account_id_1).is_some()); assert!(Identities::::get(account_id_2).is_some()); - assert!(SubnetIdentities::::get(42u16).is_some()); + assert!(SubnetIdentities::::get(NetUid::from(42)).is_some()); assert!(!HasMigrationRun::::get( b"migrate_identities_to_v2".to_vec() )); @@ -970,7 +1016,7 @@ fn test_migrate_identities_to_v2() { ); assert!(Identities::::get(account_id_1).is_none()); assert!(Identities::::get(account_id_2).is_none()); - assert!(SubnetIdentities::::get(42u16).is_none()); + assert!(SubnetIdentities::::get(NetUid::from(42)).is_none()); let new_identity_1 = IdentitiesV2::::get(account_id_1) .expect("ChainOne should be migrated to IdentitiesV2"); @@ -990,7 +1036,7 @@ fn test_migrate_identities_to_v2() { assert_eq!(new_identity_2.url, chaintwo_url); assert_eq!(new_identity_2.github_repo, b"".to_vec()); - let new_subnet_identity = SubnetIdentitiesV2::::get(42u16) + let new_subnet_identity = SubnetIdentitiesV2::::get(NetUid::from(42)) .expect("SubnetExample should be migrated to SubnetIdentitiesV2"); let expected_subnet_url = b"".to_vec(); @@ -1013,13 +1059,73 @@ fn test_migrate_identities_to_v2() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test serving -- test_do_set_subnet_identity --exact --nocapture +// SKIP_WASM_BUILD=1 RUST_LOG=DEBUG cargo test --release -p pallet-subtensor test_migrate_subnet_identities_to_v3 -- --nocapture +#[test] +fn test_migrate_subnet_identities_to_v3() { + new_test_ext(1).execute_with(|| { + let old_subnet_name = b"SubnetExample".to_vec(); + let old_github_repo = b"https://github.com/org/repo".to_vec(); + let old_subnet_contact = b"subnet@example".to_vec(); + + SubnetIdentitiesV2::::insert( + NetUid::from(16), + SubnetIdentityV2 { + subnet_name: old_subnet_name.clone(), + github_repo: old_github_repo.clone(), + subnet_contact: old_subnet_contact.clone(), + subnet_url: b"".to_vec(), + discord: b"".to_vec(), + description: b"".to_vec(), + additional: b"".to_vec(), + }, + ); + + assert!(SubnetIdentitiesV2::::get(NetUid::from(16)).is_some()); + assert!(!HasMigrationRun::::get( + b"migrate_subnet_identities_to_v3".to_vec() + )); + + let weight = + crate::migrations::migrate_subnet_identities_to_v3::migrate_subnet_identities_to_v3::< + Test, + >(); + + assert!( + HasMigrationRun::::get(b"migrate_subnet_identities_to_v3".to_vec()), + "Expected HasMigrationRun to be true after migration" + ); + assert!(SubnetIdentitiesV2::::get(NetUid::from(16)).is_none()); + + let new_subnet_identity = SubnetIdentitiesV3::::get(NetUid::from(16)) + .expect("SubnetExample should be migrated to SubnetIdentitiesV3"); + + let expected_subnet_url = b"".to_vec(); + let expected_discord = b"".to_vec(); + let expected_description = b"".to_vec(); + let expected_additional = b"".to_vec(); + + assert_eq!(new_subnet_identity.subnet_name, old_subnet_name); + assert_eq!(new_subnet_identity.github_repo, old_github_repo); + assert_eq!(new_subnet_identity.subnet_contact, old_subnet_contact); + assert_eq!(new_subnet_identity.subnet_url, expected_subnet_url); + assert_eq!(new_subnet_identity.discord, expected_discord); + assert_eq!(new_subnet_identity.description, expected_description); + assert_eq!(new_subnet_identity.additional, expected_additional); + + assert!( + weight != Weight::zero(), + "Migration weight should be non-zero" + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=DEBUG cargo test --release -p pallet-subtensor test_do_set_subnet_identity -- --nocapture #[test] fn test_do_set_subnet_identity() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid = 1; + let netuid = NetUid::from(1); // Register a hotkey for the coldkey add_network(netuid, 13, 0); @@ -1035,6 +1141,7 @@ fn test_do_set_subnet_identity() { let subnet_url = b"subnet.com".to_vec(); let discord = b"discord.com".to_vec(); let description = b"I am the describer".to_vec(); + let logo_url = b"https://testsubnet.com/logo.png".to_vec(); let additional = b"tao foreva".to_vec(); // Set subnet identity @@ -1047,15 +1154,17 @@ fn test_do_set_subnet_identity() { subnet_url.clone(), discord.clone(), description.clone(), + logo_url.clone(), additional.clone(), )); // Check if subnet identity is set correctly let stored_identity = - SubnetIdentitiesV2::::get(netuid).expect("Subnet identity should be set"); + SubnetIdentitiesV3::::get(netuid).expect("Subnet identity should be set"); assert_eq!(stored_identity.subnet_name, subnet_name); assert_eq!(stored_identity.github_repo, github_repo); assert_eq!(stored_identity.subnet_contact, subnet_contact); + assert_eq!(stored_identity.logo_url, logo_url); // Test setting subnet identity by non-owner let non_owner_coldkey = U256::from(2); @@ -1069,6 +1178,7 @@ fn test_do_set_subnet_identity() { subnet_url.clone(), discord.clone(), description.clone(), + logo_url.clone(), additional.clone(), ), Error::::NotSubnetOwner @@ -1086,13 +1196,15 @@ fn test_do_set_subnet_identity() { subnet_url.clone(), discord.clone(), description.clone(), + logo_url.clone(), additional.clone(), )); let updated_identity = - SubnetIdentitiesV2::::get(netuid).expect("Updated subnet identity should be set"); + SubnetIdentitiesV3::::get(netuid).expect("Updated subnet identity should be set"); assert_eq!(updated_identity.subnet_name, new_subnet_name); assert_eq!(updated_identity.github_repo, new_github_repo); + assert_eq!(updated_identity.logo_url, logo_url); // Test setting subnet identity with invalid data (exceeding 1024 bytes total) let long_data = vec![0; 1025]; @@ -1107,6 +1219,7 @@ fn test_do_set_subnet_identity() { long_data.clone(), long_data.clone(), long_data.clone(), + long_data.clone(), ), Error::::InvalidIdentity ); @@ -1118,25 +1231,27 @@ fn test_do_set_subnet_identity() { fn test_is_valid_subnet_identity() { new_test_ext(1).execute_with(|| { // Test valid subnet identity - let valid_identity = SubnetIdentityV2 { + let valid_identity = SubnetIdentityV3 { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], subnet_url: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], + logo_url: vec![0; 1024], additional: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity(&valid_identity)); // Test subnet identity with total length exactly at the maximum - let max_length_identity = SubnetIdentityV2 { + let max_length_identity = SubnetIdentityV3 { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], subnet_url: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], + logo_url: vec![0; 1024], additional: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity( @@ -1144,13 +1259,14 @@ fn test_is_valid_subnet_identity() { )); // Test subnet identity with total length exceeding the maximum - let invalid_length_identity = SubnetIdentityV2 { + let invalid_length_identity = SubnetIdentityV3 { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], subnet_url: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], + logo_url: vec![0; 1024], additional: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( @@ -1158,13 +1274,14 @@ fn test_is_valid_subnet_identity() { )); // Test subnet identity with one field exceeding its maximum - let invalid_field_identity = SubnetIdentityV2 { + let invalid_field_identity = SubnetIdentityV3 { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], subnet_url: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], + logo_url: vec![0; 1024], additional: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( @@ -1172,25 +1289,27 @@ fn test_is_valid_subnet_identity() { )); // Test subnet identity with empty fields - let empty_identity = SubnetIdentityV2 { + let empty_identity = SubnetIdentityV3 { subnet_name: vec![], github_repo: vec![], subnet_contact: vec![], subnet_url: vec![], discord: vec![], description: vec![], + logo_url: vec![], additional: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&empty_identity)); // Test subnet identity with some empty and some filled fields - let mixed_identity = SubnetIdentityV2 { + let mixed_identity = SubnetIdentityV3 { subnet_name: b"Test Subnet".to_vec(), github_repo: vec![], subnet_contact: b"contact@testsubnet.com".to_vec(), subnet_url: b"https://testsubnet.com".to_vec(), discord: vec![], description: b"A description".to_vec(), + logo_url: vec![], additional: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&mixed_identity)); @@ -1201,7 +1320,7 @@ fn test_is_valid_subnet_identity() { fn test_set_identity_for_non_existent_subnet() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); - let netuid = 999; // Non-existent subnet ID + let netuid = NetUid::from(999); // Non-existent subnet ID // Subnet identity data let subnet_name = b"Non-existent Subnet".to_vec(); @@ -1210,6 +1329,7 @@ fn test_set_identity_for_non_existent_subnet() { let subnet_url = b"subnet.com".to_vec(); let discord = b"discord.com".to_vec(); let description = b"I am the describer".to_vec(); + let logo_url = b"https://testsubnet.com/logo.png".to_vec(); let additional = b"tao foreva".to_vec(); // Attempt to set identity for a non-existent subnet @@ -1223,6 +1343,7 @@ fn test_set_identity_for_non_existent_subnet() { subnet_url.clone(), discord.clone(), description.clone(), + logo_url.clone(), additional.clone(), ), Error::::NotSubnetOwner // Since there's no owner, it should fail @@ -1233,13 +1354,14 @@ fn test_set_identity_for_non_existent_subnet() { #[test] fn test_set_subnet_identity_dispatch_info_ok() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let subnet_name: Vec = b"JesusSubnet".to_vec(); let github_repo: Vec = b"bible.com".to_vec(); let subnet_contact: Vec = b"https://www.vatican.va".to_vec(); let subnet_url = b"subnet.com".to_vec(); let discord = b"discord.com".to_vec(); let description = b"I am the describer".to_vec(); + let logo_url = b"https://testsubnet.com/logo.png".to_vec(); let additional = b"tao foreva".to_vec(); let call: RuntimeCall = RuntimeCall::SubtensorModule(SubtensorCall::set_subnet_identity { @@ -1250,6 +1372,7 @@ fn test_set_subnet_identity_dispatch_info_ok() { subnet_url, discord, description, + logo_url, additional, }); @@ -1268,7 +1391,7 @@ fn test_serve_axon_validate() { new_test_ext(0).execute_with(|| { let hotkey = U256::from(1); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version: u32 = 2; let ip: u128 = 1676056785; let port: u16 = 128; @@ -1292,16 +1415,22 @@ fn test_serve_axon_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_bad = extension.validate(&hotkey, &call.clone(), &info, 10); + let result_bad = extension.validate( + RawOrigin::Signed(hotkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_bad, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::HotKeyNotRegisteredInNetwork.into() - )) + assert_eq!( + result_bad.unwrap_err(), + CustomTransactionError::HotKeyNotRegisteredInNetwork.into() ); // Register the hotkey in the subnet and try again @@ -1310,7 +1439,15 @@ fn test_serve_axon_validate() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Submit to the signed extension validate function - let result_ok = extension.validate(&hotkey, &call.clone(), &info, 10); + let result_ok = extension.validate( + RawOrigin::Signed(hotkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call passes assert_ok!(result_ok); diff --git a/pallets/subtensor/src/tests/staking.rs b/pallets/subtensor/src/tests/staking.rs index 9220fa7296..bca880b01c 100644 --- a/pallets/subtensor/src/tests/staking.rs +++ b/pallets/subtensor/src/tests/staking.rs @@ -1,18 +1,26 @@ #![allow(clippy::unwrap_used)] #![allow(clippy::arithmetic_side_effects)] +use approx::assert_abs_diff_eq; +use frame_support::dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}; +use frame_support::sp_runtime::{ + DispatchError, traits::TxBaseImplication, transaction_validity::TransactionSource, +}; use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency}; use frame_system::RawOrigin; -use safe_math::SafeDiv; +use pallet_subtensor_swap::Call as SwapCall; +use pallet_subtensor_swap::tick::TickIndex; +use safe_math::FixedExt; +use sp_core::{Get, H256, U256}; use substrate_fixed::traits::FromFixed; +use substrate_fixed::types::{I96F32, I110F18, U64F64, U96F32}; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler}; +use super::mock; use super::mock::*; use crate::*; -use approx::assert_abs_diff_eq; -use frame_support::dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}; -use frame_support::sp_runtime::DispatchError; -use sp_core::{Get, H256, U256}; -use substrate_fixed::types::{I96F32, I110F18, U64F64, U96F32}; + /*********************************************************** staking::add_stake() tests ************************************************************/ @@ -22,7 +30,7 @@ fn test_add_stake_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(0); let amount_staked = 5000; - let netuid = 1; + let netuid = NetUid::from(1); let call = RuntimeCall::SubtensorModule(SubtensorCall::add_stake { hotkey, netuid, @@ -31,7 +39,8 @@ fn test_add_stake_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(1_501_000_000, 0), + call_weight: frame_support::weights::Weight::from_parts(2_395_500_000, 0), + extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -44,10 +53,11 @@ fn test_add_stake_ok_no_emission() { let hotkey_account_id = U256::from(533453); let coldkey_account_id = U256::from(55453); let amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); //add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + + mock::setup_reserves(netuid, amount * 1_000_000, amount * 10_000_000); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); @@ -65,6 +75,7 @@ fn test_add_stake_ok_no_emission() { ); // Transfer to hotkey account, and check if the result is ok + let (alpha_staked, fee) = mock::swap_tao_to_alpha(netuid, amount); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -72,11 +83,21 @@ fn test_add_stake_ok_no_emission() { amount )); + let (tao_expected, _) = mock::swap_alpha_to_tao(netuid, alpha_staked); + let approx_fee = + ::SwapInterface::approx_fee_amount(netuid.into(), amount); + + assert_abs_diff_eq!( + SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), + tao_expected + approx_fee, // swap returns value after fee, so we need to compensate it + epsilon = 10000, + ); + // Check if stake has increased assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), amount - fee, - epsilon = amount / 1000, + epsilon = 10000 ); // Check if balance has decreased @@ -89,873 +110,6 @@ fn test_add_stake_ok_no_emission() { ); }); } -// #[test] -// fn test_add_stake_aggregate_ok_no_emission() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let amount = DefaultMinStake::::get() * 10; -// let fee = DefaultStakingFee::::get(); -// -// //add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// // Give it some $$$ in his coldkey balance -// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); -// -// // Check we have zero staked before transfer -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// 0 -// ); -// -// // Also total stake should be equal to the network initial lock -// assert_eq!( -// SubtensorModule::get_total_stake(), -// SubtensorModule::get_network_min_lock() -// ); -// -// // Transfer to hotkey account, and check if the result is ok -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount -// )); -// -// // Ensure that extrinsic call doesn't change the stake. -// assert_eq!( -// SubtensorModule::get_total_stake(), -// SubtensorModule::get_network_min_lock() -// ); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check if stake has increased -// assert_abs_diff_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// amount - fee, -// epsilon = amount / 1000, -// ); -// -// // Check if balance has decreased -// assert_eq!(SubtensorModule::get_coldkey_balance(&coldkey_account_id), 1); -// -// // Check if total stake has increased accordingly. -// assert_eq!( -// SubtensorModule::get_total_stake(), -// amount + SubtensorModule::get_network_min_lock() -// ); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::StakeAdded(..)) -// ) -// })); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_add_stake_aggregate_failed() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let amount = DefaultMinStake::::get() * 100; -// //add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// // Transfer to hotkey account, and check if the result is ok -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToAddAggregatedStake(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToAddAggregatedStake(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_verify_aggregated_stake_order() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let amount = 1_000_000_000_000u64; -// let limit_price = 6_000_000_000u64; -// let unstake_amount = 150_000_000_000u64; -// let limit_price2 = 1_350_000_000; -// -// // add network -// let netuid1: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// let netuid2: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// let netuid3: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// let netuid4: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// let netuid5: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// let netuid6: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// let tao_reserve: U96F32 = U96F32::from_num(1_500_000_000_000_u64); -// let alpha_in: U96F32 = U96F32::from_num(1_000_000_000_000_u64); -// -// for netuid in [netuid1, netuid3, netuid3, netuid4, netuid5, netuid6] { -// SubnetTAO::::insert(netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); -// } -// -// // Give it some $$$ in his coldkey balance -// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 6 * amount); -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid3, -// amount, -// ); -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid4, -// amount, -// ); -// -// // Add stake with slippage safety and check if the result is ok -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid3, -// amount -// )); -// -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid4, -// unstake_amount, -// limit_price2, -// true -// )); -// -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid1, -// amount, -// )); -// -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid2, -// amount, -// limit_price, -// true -// )); -// -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// )); -// -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// )); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// let add_stake_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(.., netuid, _)) = -// e.event -// { -// netuid == netuid1 -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let add_stake_limit_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded( -// _, -// _, -// netuid, -// _, -// _, -// _, -// )) = e.event -// { -// netuid == netuid2 -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let remove_stake_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(.., netuid, _)) = -// e.event -// { -// netuid == netuid3 -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let remove_stake_limit_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved( -// .., -// netuid, -// _, -// _, -// _, -// )) = e.event -// { -// netuid == netuid4 -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let unstake_all_position = System::events() -// .iter() -// .position(|e| { -// matches!( -// e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(..)) -// ) -// }) -// .expect("Stake event must be present in the event log."); -// -// let unstake_all_alpha_position = System::events() -// .iter() -// .position(|e| { -// matches!( -// e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded(..)) -// ) -// }) -// .expect("Stake event must be present in the event log."); -// -// // Check events order -// assert!(remove_stake_limit_position < remove_stake_position); -// assert!(remove_stake_position < unstake_all_position); -// assert!(unstake_all_position < unstake_all_alpha_position); -// assert!(add_stake_position > unstake_all_alpha_position); -// assert!(add_stake_limit_position < add_stake_position); -// }); -// } -// -// #[test] -// #[allow(clippy::indexing_slicing)] -// fn test_verify_aggregated_stake_order_reversed() { -// new_test_ext(1).execute_with(|| { -// let amount = 1_000_000_000_000u64; -// let limit_price = 6_000_000_000u64; -// let unstake_amount = 150_000_000_000u64; -// let limit_price2 = 1_350_000_000; -// -// // Coldkeys and hotkeys -// let coldkeys = vec![ -// U256::from(100), // add_stake -// U256::from(200), // add_stake_limit -// U256::from(300), // remove_stake -// U256::from(400), // remove_stake_limit -// U256::from(500), // unstake_all -// U256::from(600), // unstake_all_alpha -// ]; -// -// let hotkeys = (1..=6).map(U256::from).collect::>(); -// -// let netuids: Vec<_> = hotkeys -// .iter() -// .zip(coldkeys.iter()) -// .map(|(h, c)| add_dynamic_network(h, c)) -// .collect(); -// -// let tao_reserve = U96F32::from_num(1_500_000_000_000u64); -// let alpha_in = U96F32::from_num(1_000_000_000_000u64); -// -// for netuid in &netuids { -// SubnetTAO::::insert(*netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(*netuid, alpha_in.to_num::()); -// } -// -// for coldkey in &coldkeys { -// SubtensorModule::add_balance_to_coldkey_account(coldkey, amount); -// } -// -// for ((hotkey, coldkey), netuid) in hotkeys.iter().zip(coldkeys.iter()).zip(netuids.iter()) { -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// hotkey, coldkey, *netuid, amount, -// ); -// } -// -// // Add stake with slippage safety and check if the result is ok -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[2]), -// hotkeys[2], -// netuids[2], -// amount -// )); -// -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[3]), -// hotkeys[3], -// netuids[3], -// unstake_amount, -// limit_price2, -// true -// )); -// -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[0]), -// hotkeys[0], -// netuids[0], -// amount, -// )); -// -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[1]), -// hotkeys[1], -// netuids[1], -// amount, -// limit_price, -// true -// )); -// -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkeys[4]), -// hotkeys[4], -// )); -// -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkeys[5]), -// hotkeys[5], -// )); -// -// // Enable on_finalize code to run -// run_to_block_ext(2, false); -// // Reorder jobs based on the previous block hash -// let mut parent_hash = >::parent_hash(); -// parent_hash.as_mut()[0] = 0b10000000; -// >::set_parent_hash(parent_hash); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// let add_stake_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(.., netuid, _)) = -// e.event -// { -// netuid == netuids[0] -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let add_stake_limit_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded( -// _, -// _, -// netuid, -// _, -// _, -// _, -// )) = e.event -// { -// netuid == netuids[1] -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let remove_stake_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(.., netuid, _)) = -// e.event -// { -// netuid == netuids[2] -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let remove_stake_limit_position = System::events() -// .iter() -// .position(|e| { -// if let RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved( -// .., -// netuid, -// _, -// _, -// _, -// )) = e.event -// { -// netuid == netuids[3] -// } else { -// false -// } -// }) -// .expect("Stake event must be present in the event log."); -// -// let unstake_all_position = System::events() -// .iter() -// .position(|e| { -// matches!( -// e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(..)) -// ) -// }) -// .expect("Stake event must be present in the event log."); -// -// let unstake_all_alpha_position = System::events() -// .iter() -// .position(|e| { -// matches!( -// e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded(..)) -// ) -// }) -// .expect("Stake event must be present in the event log."); -// -// // Check events order -// assert!(add_stake_limit_position > add_stake_position); -// assert!(add_stake_position < unstake_all_alpha_position); -// assert!(unstake_all_position > unstake_all_alpha_position); -// assert!(remove_stake_position > unstake_all_position); -// assert!(remove_stake_limit_position > remove_stake_position); -// }); -// } -// -// #[test] -// #[allow(clippy::indexing_slicing)] -// fn test_verify_all_job_type_sort_by_coldkey() { -// new_test_ext(1).execute_with(|| { -// let amount = 1_000_000_000_000u64; -// let limit_price = 6_000_000_000u64; -// let unstake_amount = 150_000_000_000u64; -// let limit_price2 = 1_350_000_000; -// -// // Coldkeys and hotkeys -// let coldkeys = vec![ -// U256::from(100), // add_stake -// U256::from(200), // add_stake -// U256::from(300), // add_stake_limit -// U256::from(400), // add_stake_limit -// U256::from(500), // remove_stake -// U256::from(600), // remove_stake -// U256::from(700), // remove_stake_limit -// U256::from(800), // remove_stake_limit -// U256::from(900), // unstake_all -// U256::from(1000), // unstake_all -// U256::from(1100), // unstake_all_alpha -// U256::from(1200), // unstake_all_alpha -// ]; -// -// let hotkeys = (1..=12).map(U256::from).collect::>(); -// -// let netuids: Vec<_> = hotkeys -// .iter() -// .zip(coldkeys.iter()) -// .map(|(h, c)| add_dynamic_network(h, c)) -// .collect(); -// -// let tao_reserve = U96F32::from_num(1_500_000_000_000u64); -// let alpha_in = U96F32::from_num(1_000_000_000_000u64); -// -// for netuid in &netuids { -// SubnetTAO::::insert(*netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(*netuid, alpha_in.to_num::()); -// } -// -// for coldkey in &coldkeys { -// SubtensorModule::add_balance_to_coldkey_account(coldkey, amount); -// } -// -// for ((hotkey, coldkey), netuid) in hotkeys.iter().zip(coldkeys.iter()).zip(netuids.iter()) { -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// hotkey, coldkey, *netuid, amount, -// ); -// } -// -// // === Submit all job types === -// -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[0]), -// hotkeys[0], -// netuids[0], -// amount -// )); -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[1]), -// hotkeys[1], -// netuids[1], -// amount -// )); -// -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[2]), -// hotkeys[2], -// netuids[2], -// amount, -// limit_price, -// true -// )); -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[3]), -// hotkeys[3], -// netuids[3], -// amount, -// limit_price, -// true -// )); -// -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[4]), -// hotkeys[4], -// netuids[4], -// amount -// )); -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[5]), -// hotkeys[5], -// netuids[5], -// amount -// )); -// -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[6]), -// hotkeys[6], -// netuids[6], -// unstake_amount, -// limit_price2, -// true -// )); -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[7]), -// hotkeys[7], -// netuids[7], -// unstake_amount, -// limit_price2, -// true -// )); -// -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkeys[8]), -// hotkeys[8], -// )); -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkeys[9]), -// hotkeys[9], -// )); -// -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkeys[10]), -// hotkeys[10], -// )); -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkeys[11]), -// hotkeys[11], -// )); -// -// // Finalize block -// run_to_block_ext(3, true); -// -// // === Collect coldkeys by event type === -// let mut add_coldkeys = vec![]; -// let mut add_limit_coldkeys = vec![]; -// let mut remove_coldkeys = vec![]; -// let mut remove_limit_coldkeys = vec![]; -// let mut unstake_all_coldkeys = vec![]; -// let mut unstake_all_alpha_coldkeys = vec![]; -// -// for event in System::events().iter().map(|e| &e.event) { -// match event { -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(coldkey, ..)) => { -// add_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded(coldkey, ..)) => { -// add_limit_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(coldkey, ..)) => { -// remove_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved( -// coldkey, -// .., -// )) => { -// remove_limit_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(coldkey, _)) => { -// unstake_all_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded( -// coldkey, -// _, -// )) => { -// unstake_all_alpha_coldkeys.push(*coldkey); -// } -// _ => {} -// } -// } -// -// // === Assertions === -// assert_eq!(add_coldkeys, vec![coldkeys[1], coldkeys[0]]); // descending -// assert_eq!(add_limit_coldkeys, vec![coldkeys[3], coldkeys[2]]); // descending -// assert_eq!(remove_coldkeys, vec![coldkeys[4], coldkeys[5]]); // ascending -// assert_eq!(remove_limit_coldkeys, vec![coldkeys[6], coldkeys[7]]); // ascending -// assert_eq!(unstake_all_coldkeys, vec![coldkeys[8], coldkeys[9]]); // ascending -// assert_eq!(unstake_all_alpha_coldkeys, vec![coldkeys[10], coldkeys[11]]); // ascending -// }); -// } -// -// #[test] -// #[allow(clippy::indexing_slicing)] -// fn test_verify_all_job_type_sort_by_coldkey_reverse_order() { -// new_test_ext(1).execute_with(|| { -// let amount = 1_000_000_000_000u64; -// let limit_price = 6_000_000_000u64; -// let unstake_amount = 150_000_000_000u64; -// let limit_price2 = 1_350_000_000; -// -// // Coldkeys and hotkeys -// let coldkeys = vec![ -// U256::from(100), // add_stake -// U256::from(200), // add_stake -// U256::from(300), // add_stake_limit -// U256::from(400), // add_stake_limit -// U256::from(500), // remove_stake -// U256::from(600), // remove_stake -// U256::from(700), // remove_stake_limit -// U256::from(800), // remove_stake_limit -// U256::from(900), // unstake_all -// U256::from(1000), // unstake_all -// U256::from(1100), // unstake_all_alpha -// U256::from(1200), // unstake_all_alpha -// ]; -// -// let hotkeys = (1..=12).map(U256::from).collect::>(); -// -// let netuids: Vec<_> = hotkeys -// .iter() -// .zip(coldkeys.iter()) -// .map(|(h, c)| add_dynamic_network(h, c)) -// .collect(); -// -// let tao_reserve = U96F32::from_num(1_500_000_000_000u64); -// let alpha_in = U96F32::from_num(1_000_000_000_000u64); -// -// for netuid in &netuids { -// SubnetTAO::::insert(*netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(*netuid, alpha_in.to_num::()); -// } -// -// for coldkey in &coldkeys { -// SubtensorModule::add_balance_to_coldkey_account(coldkey, amount); -// } -// -// for ((hotkey, coldkey), netuid) in hotkeys.iter().zip(coldkeys.iter()).zip(netuids.iter()) { -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// hotkey, coldkey, *netuid, amount, -// ); -// } -// -// // === Submit all job types === -// -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[0]), -// hotkeys[0], -// netuids[0], -// amount -// )); -// assert_ok!(SubtensorModule::add_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[1]), -// hotkeys[1], -// netuids[1], -// amount -// )); -// -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[2]), -// hotkeys[2], -// netuids[2], -// amount, -// limit_price, -// true -// )); -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[3]), -// hotkeys[3], -// netuids[3], -// amount, -// limit_price, -// true -// )); -// -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[4]), -// hotkeys[4], -// netuids[4], -// amount -// )); -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkeys[5]), -// hotkeys[5], -// netuids[5], -// amount -// )); -// -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[6]), -// hotkeys[6], -// netuids[6], -// unstake_amount, -// limit_price2, -// true -// )); -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkeys[7]), -// hotkeys[7], -// netuids[7], -// unstake_amount, -// limit_price2, -// true -// )); -// -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkeys[8]), -// hotkeys[8], -// )); -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkeys[9]), -// hotkeys[9], -// )); -// -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkeys[10]), -// hotkeys[10], -// )); -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkeys[11]), -// hotkeys[11], -// )); -// -// // Reorder jobs based on the previous block hash -// let mut parent_hash = >::parent_hash(); -// parent_hash.as_mut()[0] = 0b10000000; -// >::set_parent_hash(parent_hash); -// -// // Finalize block -// run_to_block_ext(3, true); -// -// // === Collect coldkeys by event type === -// let mut add_coldkeys = vec![]; -// let mut add_limit_coldkeys = vec![]; -// let mut remove_coldkeys = vec![]; -// let mut remove_limit_coldkeys = vec![]; -// let mut unstake_all_coldkeys = vec![]; -// let mut unstake_all_alpha_coldkeys = vec![]; -// -// for event in System::events().iter().map(|e| &e.event) { -// match event { -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeAdded(coldkey, ..)) => { -// add_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded(coldkey, ..)) => { -// add_limit_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(coldkey, ..)) => { -// remove_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved( -// coldkey, -// .., -// )) => { -// remove_limit_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(coldkey, _)) => { -// unstake_all_coldkeys.push(*coldkey); -// } -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded( -// coldkey, -// _, -// )) => { -// unstake_all_alpha_coldkeys.push(*coldkey); -// } -// _ => {} -// } -// } -// -// // === Assertions === -// assert_eq!(add_coldkeys, vec![coldkeys[0], coldkeys[1]]); // ascending (reversed) -// assert_eq!(add_limit_coldkeys, vec![coldkeys[2], coldkeys[3]]); // ascending (reversed) -// assert_eq!(remove_coldkeys, vec![coldkeys[5], coldkeys[4]]); // descending (reversed) -// assert_eq!(remove_limit_coldkeys, vec![coldkeys[7], coldkeys[6]]); // descending (reversed) -// assert_eq!(unstake_all_coldkeys, vec![coldkeys[9], coldkeys[8]]); // descending (reversed) -// assert_eq!(unstake_all_alpha_coldkeys, vec![coldkeys[11], coldkeys[10]]); // descending (reversed) -// }); -// } #[test] fn test_dividends_with_run_to_block() { @@ -967,12 +121,12 @@ fn test_dividends_with_run_to_block() { let initial_stake: u64 = 5000; //add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); Tempo::::insert(netuid, 13); // Register neuron, this will set a self weight SubtensorModule::set_max_registrations_per_block(netuid, 3); - SubtensorModule::set_max_allowed_uids(1, 5); + SubtensorModule::set_max_allowed_uids(1.into(), 5); register_ok_neuron(netuid, neuron_src_hotkey_id, coldkey_account_id, 192213123); register_ok_neuron(netuid, neuron_dest_hotkey_id, coldkey_account_id, 12323); @@ -986,9 +140,10 @@ fn test_dividends_with_run_to_block() { ); // Check if the initial stake has arrived - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&neuron_src_hotkey_id), - initial_stake + initial_stake, + epsilon = 2 ); // Check if all three neurons are registered @@ -998,9 +153,10 @@ fn test_dividends_with_run_to_block() { run_to_block(2); // Check if the stake is equal to the inital stake + transfer - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&neuron_src_hotkey_id), - initial_stake + initial_stake, + epsilon = 2 ); // Check if the stake is equal to the inital stake + transfer @@ -1016,7 +172,7 @@ fn test_add_stake_err_signature() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(654); // bogus let amount = 20000; // Not used - let netuid = 1; + let netuid = NetUid::from(1); assert_err!( SubtensorModule::add_stake(RawOrigin::None.into(), hotkey_account_id, netuid, amount), @@ -1034,7 +190,7 @@ fn test_add_stake_not_registered_key_pair() { let hotkey_account_id = U256::from(54544); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount + fee); assert_err!( SubtensorModule::add_stake( @@ -1054,7 +210,7 @@ fn test_add_stake_ok_neuron_does_not_belong_to_coldkey() { let coldkey_id = U256::from(544); let hotkey_id = U256::from(54544); let other_cold_key = U256::from(99498); - let netuid: u16 = add_dynamic_network(&hotkey_id, &coldkey_id); + let netuid = add_dynamic_network(&hotkey_id, &coldkey_id); let stake = DefaultMinStake::::get() * 10; // Give it some $$$ in his coldkey balance @@ -1076,7 +232,7 @@ fn test_add_stake_err_not_enough_belance() { let coldkey_id = U256::from(544); let hotkey_id = U256::from(54544); let stake = DefaultMinStake::::get() * 10; - let netuid: u16 = add_dynamic_network(&hotkey_id, &coldkey_id); + let netuid = add_dynamic_network(&hotkey_id, &coldkey_id); // Lets try to stake with 0 balance in cold key account assert!(SubtensorModule::get_coldkey_balance(&coldkey_id) < stake); @@ -1100,7 +256,7 @@ fn test_add_stake_total_balance_no_change() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(551337); let coldkey_account_id = U256::from(51337); - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give it some $$$ in his coldkey balance let initial_balance = 10000; @@ -1150,7 +306,7 @@ fn test_add_stake_total_issuance_no_change() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(561337); let coldkey_account_id = U256::from(61337); - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give it some $$$ in his coldkey balance let initial_balance = 10000; @@ -1201,7 +357,7 @@ fn test_remove_stake_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(0); let amount_unstaked = 5000; - let netuid = 1; + let netuid = NetUid::from(1); let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake { hotkey, netuid, @@ -1210,8 +366,9 @@ fn test_remove_stake_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(1_671_800_000, 0) + call_weight: frame_support::weights::Weight::from_parts(1_671_800_000, 0) .add_proof_size(0), + extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -1227,7 +384,7 @@ fn test_remove_stake_ok_no_emission() { let coldkey_account_id = U256::from(4343); let hotkey_account_id = U256::from(4968585); let amount = DefaultMinStake::::get() * 10; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Some basic assertions @@ -1248,16 +405,16 @@ fn test_remove_stake_ok_no_emission() { netuid, amount, ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), - amount + amount, + epsilon = amount / 1000 ); // Add subnet TAO for the equivalent amount added at price - let amount_tao = - U96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); - SubnetTAO::::mutate(netuid, |v| *v += amount_tao.saturating_to_num::()); - TotalStake::::mutate(|v| *v += amount_tao.saturating_to_num::()); + let (amount_tao, fee) = mock::swap_alpha_to_tao(netuid, amount); + SubnetTAO::::mutate(netuid, |v| *v += amount_tao + fee); + TotalStake::::mutate(|v| *v += amount_tao + fee); // Do the magic assert_ok!(SubtensorModule::remove_stake( @@ -1267,165 +424,20 @@ fn test_remove_stake_ok_no_emission() { amount )); - let fee = SubtensorModule::calculate_staking_fee( - Some((&hotkey_account_id, netuid)), - &coldkey_account_id, - None, - &coldkey_account_id, - U96F32::saturating_from_num(amount), - ); - // we do not expect the exact amount due to slippage assert!(SubtensorModule::get_coldkey_balance(&coldkey_account_id) > amount / 10 * 9 - fee); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), - 0 + 0, + epsilon = 20000 ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake(), - SubtensorModule::get_network_min_lock() + fee + SubtensorModule::get_network_min_lock() + fee, + epsilon = 1000 ); }); } -// -// #[test] -// fn test_remove_stake_aggregate_ok_no_emission() { -// new_test_ext(1).execute_with(|| { -// let subnet_owner_coldkey = U256::from(1); -// let subnet_owner_hotkey = U256::from(2); -// let coldkey_account_id = U256::from(4343); -// let hotkey_account_id = U256::from(4968585); -// let amount = DefaultMinStake::::get() * 10; -// let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); -// register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); -// -// // Some basic assertions -// assert_eq!( -// SubtensorModule::get_total_stake(), -// SubtensorModule::get_network_min_lock() -// ); -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// 0 -// ); -// assert_eq!(SubtensorModule::get_coldkey_balance(&coldkey_account_id), 0); -// -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// amount, -// ); -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// amount -// ); -// -// // Add subnet TAO for the equivalent amount added at price -// let amount_tao = -// U96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); -// SubnetTAO::::mutate(netuid, |v| *v += amount_tao.saturating_to_num::()); -// TotalStake::::mutate(|v| *v += amount_tao.saturating_to_num::()); -// -// // Do the magic -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// let fee = SubtensorModule::calculate_staking_fee( -// Some((&hotkey_account_id, netuid)), -// &coldkey_account_id, -// None, -// &coldkey_account_id, -// U96F32::saturating_from_num(amount), -// ); -// -// // we do not expect the exact amount due to slippage -// assert!(SubtensorModule::get_coldkey_balance(&coldkey_account_id) > amount / 10 * 9 - fee); -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// 0 -// ); -// assert_eq!( -// SubtensorModule::get_total_stake(), -// SubtensorModule::get_network_min_lock() + fee -// ); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::StakeRemoved(..)) -// ) -// })); -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedStakeRemoved(..)) -// ) -// })); -// }); -// } -// #[test] -// fn test_remove_stake_aggregate_fail() { -// new_test_ext(1).execute_with(|| { -// let subnet_owner_coldkey = U256::from(1); -// let subnet_owner_hotkey = U256::from(2); -// let coldkey_account_id = U256::from(4343); -// let hotkey_account_id = U256::from(4968585); -// let amount = DefaultMinStake::::get() * 10; -// let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); -// register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); -// -// assert_ok!(SubtensorModule::remove_stake_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToRemoveAggregatedStake(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToRemoveAggregatedStake(..)) -// ) -// })); -// }); -// } #[test] fn test_remove_stake_amount_too_low() { @@ -1435,7 +447,7 @@ fn test_remove_stake_amount_too_low() { let coldkey_account_id = U256::from(4343); let hotkey_account_id = U256::from(4968585); let amount = 10_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Some basic assertions @@ -1475,7 +487,7 @@ fn test_remove_stake_err_signature() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(4968585); let amount = 10000; // Amount to be removed - let netuid = 1; + let netuid = NetUid::from(1); assert_err!( SubtensorModule::remove_stake( @@ -1496,7 +508,7 @@ fn test_remove_stake_ok_hotkey_does_not_belong_to_coldkey() { let hotkey_id = U256::from(54544); let other_cold_key = U256::from(99498); let amount = DefaultMinStake::::get() * 10; - let netuid: u16 = add_dynamic_network(&hotkey_id, &coldkey_id); + let netuid = add_dynamic_network(&hotkey_id, &coldkey_id); // Give the neuron some stake to remove SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -1549,7 +561,7 @@ fn test_remove_stake_total_balance_no_change() { let hotkey_account_id = U256::from(571337); let coldkey_account_id = U256::from(71337); let amount = DefaultMinStake::::get() * 10; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Some basic assertions @@ -1574,8 +586,8 @@ fn test_remove_stake_total_balance_no_change() { ); // Add subnet TAO for the equivalent amount added at price - let amount_tao = - U96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); + let amount_tao = U96F32::saturating_from_num(amount) + * ::SwapInterface::current_alpha_price(netuid.into()); SubnetTAO::::mutate(netuid, |v| *v += amount_tao.saturating_to_num::()); TotalStake::::mutate(|v| *v += amount_tao.saturating_to_num::()); @@ -1587,13 +599,7 @@ fn test_remove_stake_total_balance_no_change() { amount )); - let fee = SubtensorModule::calculate_staking_fee( - Some((&hotkey_account_id, netuid)), - &coldkey_account_id, - None, - &coldkey_account_id, - U96F32::saturating_from_num(amount), - ); + let fee = ::SwapInterface::approx_fee_amount(netuid.into(), amount); assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), amount - fee, @@ -1603,9 +609,10 @@ fn test_remove_stake_total_balance_no_change() { SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), 0 ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake(), - SubtensorModule::get_network_min_lock() + fee + SubtensorModule::get_network_min_lock() + fee, + epsilon = 3 ); // Check total balance is equal to the added stake. Even after remove stake (no fee, includes reserved/locked balance) @@ -1621,21 +628,15 @@ fn test_add_stake_insufficient_liquidity() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() * 10 + DefaultStakingFee::::get(); + let amount_staked = DefaultMinStake::::get() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked); // Set the liquidity at lowest possible value so that all staking requests fail - SubnetTAO::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); - SubnetAlphaIn::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); + let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; + mock::setup_reserves(netuid, reserve, reserve); // Check the error assert_noop!( @@ -1657,32 +658,44 @@ fn test_remove_stake_insufficient_liquidity() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() * 10 + DefaultStakingFee::::get(); + let amount_staked = DefaultMinStake::::get() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked); // Simulate stake for hotkey - SubnetTAO::::insert(netuid, u64::MAX / 1000); - SubnetAlphaIn::::insert(netuid, u64::MAX / 1000); - let alpha = SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid, amount_staked, 0); + let reserve = u64::MAX / 1000; + mock::setup_reserves(netuid, reserve, reserve); - // Set the liquidity at lowest possible value so that all staking requests fail - SubnetTAO::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); - SubnetAlphaIn::::insert( + let alpha = SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); + amount_staked, + ::SwapInterface::max_price(), + ) + .unwrap(); + + // Set the liquidity at lowest possible value so that all staking requests fail + let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; + mock::setup_reserves(netuid, reserve, reserve); // Check the error assert_noop!( SubtensorModule::remove_stake(RuntimeOrigin::signed(coldkey), hotkey, netuid, alpha), Error::::InsufficientLiquidity ); + + // Mock provided liquidity - remove becomes successful + SubnetTaoProvided::::insert(netuid, amount_staked + 1); + SubnetAlphaInProvided::::insert(netuid, 1); + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + alpha + ),); }); } @@ -1697,13 +710,14 @@ fn test_remove_stake_total_issuance_no_change() { let hotkey_account_id = U256::from(581337); let coldkey_account_id = U256::from(81337); let amount = DefaultMinStake::::get() * 10; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = DefaultStakingFee::::get(); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); + mock::setup_reserves(netuid, amount * 100, amount * 100); + // Some basic assertions assert_eq!( SubtensorModule::get_total_stake(), @@ -1722,6 +736,7 @@ fn test_remove_stake_total_issuance_no_change() { let inital_total_issuance = Balances::total_issuance(); // Stake to hotkey account, and check if the result is ok + let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -1737,6 +752,9 @@ fn test_remove_stake_total_issuance_no_change() { &coldkey_account_id, netuid, ); + + let total_fee = mock::swap_alpha_to_tao(netuid, stake).1 + fee; + assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -1748,8 +766,8 @@ fn test_remove_stake_total_issuance_no_change() { assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), - amount - fee * 2, - epsilon = amount / 1000, + amount - total_fee, + epsilon = 1 ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), @@ -1757,11 +775,12 @@ fn test_remove_stake_total_issuance_no_change() { ); assert_abs_diff_eq!( SubtensorModule::get_total_stake(), - fee * 2 + SubtensorModule::get_network_min_lock(), + total_fee + SubtensorModule::get_network_min_lock(), epsilon = fee / 1000 ); - // Check if total issuance is equal to the added stake, even after remove stake (no fee, includes reserved/locked balance) + // Check if total issuance is equal to the added stake, even after remove stake (no fee, + // includes reserved/locked balance) assert_abs_diff_eq!( inital_total_issuance, total_issuance_after_stake + amount, @@ -1772,7 +791,7 @@ fn test_remove_stake_total_issuance_no_change() { // so the total issuance should be lower by that amount assert_abs_diff_eq!( inital_total_issuance, - total_issuance_after_unstake + 2 * fee, + total_issuance_after_unstake + total_fee, epsilon = inital_total_issuance / 10000, ); }); @@ -1782,99 +801,68 @@ fn test_remove_stake_total_issuance_no_change() { #[test] fn test_remove_prev_epoch_stake() { new_test_ext(1).execute_with(|| { - let def_fee = DefaultStakingFee::::get(); - // Test case: (amount_to_stake, AlphaDividendsPerSubnet, TotalHotkeyAlphaLastEpoch, expected_fee) [ // No previous epoch stake and low hotkey stake - ( - DefaultMinStake::::get() * 10, - 0_u64, - 1000_u64, - def_fee * 2, - ), + (DefaultMinStake::::get() * 10, 0_u64, 1000_u64), // Same, but larger amount to stake - we get 0.005% for unstake - ( - 1_000_000_000, - 0_u64, - 1000_u64, - (1_000_000_000_f64 * 0.00005) as u64 + def_fee, - ), - ( - 100_000_000_000, - 0_u64, - 1000_u64, - (100_000_000_000_f64 * 0.00005) as u64 + def_fee, - ), + (1_000_000_000, 0_u64, 1000_u64), + (100_000_000_000, 0_u64, 1000_u64), // Lower previous epoch stake than current stake // Staking/unstaking 100 TAO, divs / total = 0.1 => fee is 1 TAO - ( - 100_000_000_000, - 1_000_000_000_u64, - 10_000_000_000_u64, - (100_000_000_000_f64 * 0.1) as u64 + def_fee, - ), + (100_000_000_000, 1_000_000_000_u64, 10_000_000_000_u64), // Staking/unstaking 100 TAO, divs / total = 0.001 => fee is 0.01 TAO - ( - 100_000_000_000, - 10_000_000_u64, - 10_000_000_000_u64, - (100_000_000_000_f64 * 0.001) as u64 + def_fee, - ), + (100_000_000_000, 10_000_000_u64, 10_000_000_000_u64), // Higher previous epoch stake than current stake - ( - 1_000_000_000, - 100_000_000_000_u64, - 100_000_000_000_000_u64, - (1_000_000_000_f64 * 0.001) as u64 + def_fee, - ), + (1_000_000_000, 100_000_000_000_u64, 100_000_000_000_000_u64), ] - .iter() - .for_each( - |(amount_to_stake, alpha_divs, hotkey_alpha, expected_fee)| { - let subnet_owner_coldkey = U256::from(1); - let subnet_owner_hotkey = U256::from(2); - let hotkey_account_id = U256::from(581337); - let coldkey_account_id = U256::from(81337); - let amount = *amount_to_stake; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); - - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); - AlphaDividendsPerSubnet::::insert(netuid, hotkey_account_id, *alpha_divs); - TotalHotkeyAlphaLastEpoch::::insert(hotkey_account_id, netuid, *hotkey_alpha); - let balance_before = SubtensorModule::get_coldkey_balance(&coldkey_account_id); - - // Stake to hotkey account, and check if the result is ok - assert_ok!(SubtensorModule::add_stake( - RuntimeOrigin::signed(coldkey_account_id), - hotkey_account_id, - netuid, - amount - )); + .into_iter() + .for_each(|(amount_to_stake, alpha_divs, hotkey_alpha)| { + let subnet_owner_coldkey = U256::from(1); + let subnet_owner_hotkey = U256::from(2); + let hotkey_account_id = U256::from(581337); + let coldkey_account_id = U256::from(81337); + let amount = amount_to_stake; + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); + + // Give it some $$$ in his coldkey balance + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); + AlphaDividendsPerSubnet::::insert(netuid, hotkey_account_id, alpha_divs); + TotalHotkeyAlphaLastEpoch::::insert(hotkey_account_id, netuid, hotkey_alpha); + let balance_before = SubtensorModule::get_coldkey_balance(&coldkey_account_id); + mock::setup_reserves(netuid, amount_to_stake * 10, amount_to_stake * 10); + + // Stake to hotkey account, and check if the result is ok + let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount + )); - // Remove all stake - let stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &coldkey_account_id, - netuid, - ); + // Remove all stake + let stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid, + ); - assert_ok!(SubtensorModule::remove_stake( - RuntimeOrigin::signed(coldkey_account_id), - hotkey_account_id, - netuid, - stake - )); + let fee = mock::swap_alpha_to_tao(netuid, stake).1 + fee; + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + stake + )); - // Measure actual fee - let balance_after = SubtensorModule::get_coldkey_balance(&coldkey_account_id); - let actual_fee = balance_before - balance_after; + // Measure actual fee + let balance_after = SubtensorModule::get_coldkey_balance(&coldkey_account_id); + let actual_fee = balance_before - balance_after; - assert_abs_diff_eq!(actual_fee, *expected_fee, epsilon = *expected_fee / 100,); - }, - ); + assert_abs_diff_eq!(actual_fee, fee, epsilon = fee / 100); + }); }); } @@ -1887,7 +875,7 @@ fn test_staking_sets_div_variables() { let hotkey_account_id = U256::from(581337); let coldkey_account_id = U256::from(81337); let amount = 100_000_000_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let tempo = 10; Tempo::::insert(netuid, tempo); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); @@ -1983,7 +971,7 @@ fn test_add_stake_to_hotkey_account_ok() { let hotkey_id = U256::from(5445); let coldkey_id = U256::from(5443433); let amount = 10_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_id, coldkey_id, 192213123); // There is no stake in the system at first, other than the network initial lock so result; @@ -2000,9 +988,10 @@ fn test_add_stake_to_hotkey_account_ok() { ); // The stake that is now in the account, should equal the amount - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_id), - amount + amount, + epsilon = 2 ); }); } @@ -2018,7 +1007,7 @@ fn test_remove_stake_from_hotkey_account() { let hotkey_id = U256::from(5445); let coldkey_id = U256::from(5443433); let amount = 10_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_id, coldkey_id, 192213123); // Add some stake that can be removed @@ -2030,9 +1019,10 @@ fn test_remove_stake_from_hotkey_account() { ); // Prelimiary checks - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_id), - amount + amount, + epsilon = 10 ); // Remove stake @@ -2194,7 +1184,7 @@ fn test_hotkey_belongs_to_coldkey_ok() { new_test_ext(1).execute_with(|| { let hotkey_id = U256::from(4434334); let coldkey_id = U256::from(34333); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let start_nonce: u64 = 0; add_network(netuid, tempo, 0); @@ -2244,7 +1234,7 @@ fn test_has_enough_stake_yes() { let hotkey_id = U256::from(4334); let coldkey_id = U256::from(87989); let intial_amount = 10_000; - let netuid = add_dynamic_network(&hotkey_id, &coldkey_id); + let netuid = NetUid::from(add_dynamic_network(&hotkey_id, &coldkey_id)); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_id, &coldkey_id, @@ -2252,9 +1242,10 @@ fn test_has_enough_stake_yes() { intial_amount, ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_id), - intial_amount + intial_amount, + epsilon = 2 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -2287,9 +1278,10 @@ fn test_has_enough_stake_no() { intial_amount, ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_id), - intial_amount + intial_amount, + epsilon = 2 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -2340,7 +1332,7 @@ fn test_has_enough_stake_no_for_zero() { #[test] fn test_non_existent_account() { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(0), &(U256::from(0)), @@ -2418,7 +1410,7 @@ fn test_clear_small_nominations() { let hot2 = U256::from(2); let cold1 = U256::from(3); let cold2 = U256::from(4); - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let amount = DefaultMinStake::::get() * 10; let fee: u64 = DefaultMinStake::::get(); let init_balance = amount + fee + ExistentialDeposit::get(); @@ -2595,7 +1587,7 @@ fn test_delegate_take_can_be_decreased() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2630,7 +1622,7 @@ fn test_can_set_min_take_ok() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2662,7 +1654,7 @@ fn test_delegate_take_can_not_be_increased_with_decrease_take() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2697,7 +1689,7 @@ fn test_delegate_take_can_be_increased() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2732,7 +1724,7 @@ fn test_delegate_take_can_not_be_decreased_with_increase_take() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2771,7 +1763,7 @@ fn test_delegate_take_can_be_increased_to_limit() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2809,7 +1801,7 @@ fn test_delegate_take_can_not_be_increased_beyond_limit() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2851,7 +1843,7 @@ fn test_rate_limits_enforced_on_increase_take() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2911,7 +1903,7 @@ fn test_rate_limits_enforced_on_decrease_before_increase_take() { SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 100000); // Register the neuron to a new network - let netuid = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey0, coldkey0, 124124); @@ -2974,7 +1966,6 @@ fn test_get_total_delegated_stake_after_unstaking() { let unstake_amount = DefaultMinStake::::get() * 5; let existential_deposit = ExistentialDeposit::get(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = DefaultStakingFee::::get(); register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); @@ -2982,6 +1973,7 @@ fn test_get_total_delegated_stake_after_unstaking() { SubtensorModule::add_balance_to_coldkey_account(&delegator, initial_stake); // Delegate stake + let (_, fee) = mock::swap_tao_to_alpha(netuid, initial_stake); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(delegator), delegate_hotkey, @@ -3041,7 +2033,7 @@ fn test_get_total_delegated_stake_no_delegations() { new_test_ext(1).execute_with(|| { let delegate = U256::from(1); let coldkey = U256::from(2); - let netuid = 1u16; + let netuid = NetUid::from(1u16); add_network(netuid, 1, 0); register_ok_neuron(netuid, delegate, coldkey, 0); @@ -3062,12 +2054,14 @@ fn test_get_total_delegated_stake_single_delegator() { let stake_amount = DefaultMinStake::::get() * 10 - 1; let existential_deposit = ExistentialDeposit::get(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = DefaultStakingFee::::get(); register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); // Add stake from delegator SubtensorModule::add_balance_to_coldkey_account(&delegator, stake_amount); + + let (_, fee) = mock::swap_tao_to_alpha(netuid, stake_amount); + assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(delegator), delegate_hotkey, @@ -3120,7 +2114,6 @@ fn test_get_alpha_share_stake_multiple_delegators() { let existential_deposit = 2; let stake1 = DefaultMinStake::::get() * 10; let stake2 = DefaultMinStake::::get() * 10 - 1; - let fee = DefaultStakingFee::::get(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey1, coldkey1, 0); @@ -3157,7 +2150,9 @@ fn test_get_alpha_share_stake_multiple_delegators() { ); // Calculate expected total delegated stake - let expected_total_stake = stake1 + stake2 - existential_deposit * 2 - fee * 2; + let fee = + ::SwapInterface::approx_fee_amount(netuid.into(), stake1 + stake2); + let expected_total_stake = stake1 + stake2 - existential_deposit * 2 - fee; let actual_total_stake = SubtensorModule::get_alpha_share_pool(hotkey1, netuid) .get_value(&coldkey1) + SubtensorModule::get_alpha_share_pool(hotkey2, netuid).get_value(&coldkey2); @@ -3179,7 +2174,6 @@ fn test_get_total_delegated_stake_exclude_owner_stake() { let delegator = U256::from(3); let owner_stake = DefaultMinStake::::get() * 10; let delegator_stake = DefaultMinStake::::get() * 10 - 1; - let fee = DefaultStakingFee::::get(); let netuid = add_dynamic_network(&delegate_hotkey, &delegate_coldkey); @@ -3194,6 +2188,7 @@ fn test_get_total_delegated_stake_exclude_owner_stake() { // Add delegator stake SubtensorModule::add_balance_to_coldkey_account(&delegator, delegator_stake); + let (_, fee) = mock::swap_tao_to_alpha(netuid, delegator_stake); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(delegator), delegate_hotkey, @@ -3220,7 +2215,7 @@ fn test_get_total_delegated_stake_exclude_owner_stake() { assert_abs_diff_eq!( actual_delegated_stake, expected_delegated_stake, - epsilon = expected_delegated_stake / 1000 + epsilon = 1000 ); }); } @@ -3236,7 +2231,7 @@ fn test_mining_emission_distribution_validator_valiminer_miner() { let validator_miner_hotkey = U256::from(4); let miner_coldkey = U256::from(5); let miner_hotkey = U256::from(6); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let subnet_tempo = 10; let stake = 100_000_000_000; @@ -3329,7 +2324,7 @@ fn test_staking_too_little_fails() { let amount = 10_000; //add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); @@ -3348,6 +2343,7 @@ fn test_staking_too_little_fails() { } // cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_fee_goes_to_subnet_tao --exact --show-output --nocapture +#[ignore = "fee now goes to liquidity provider"] #[test] fn test_add_stake_fee_goes_to_subnet_tao() { new_test_ext(1).execute_with(|| { @@ -3357,7 +2353,7 @@ fn test_add_stake_fee_goes_to_subnet_tao() { let coldkey = U256::from(3); let existential_deposit = ExistentialDeposit::get(); let tao_to_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); @@ -3395,6 +2391,7 @@ fn test_add_stake_fee_goes_to_subnet_tao() { } // cargo test --package pallet-subtensor --lib -- tests::staking::test_remove_stake_fee_goes_to_subnet_tao --exact --show-output --nocapture +#[ignore = "fees no go to liquidity providers"] #[test] fn test_remove_stake_fee_goes_to_subnet_tao() { new_test_ext(1).execute_with(|| { @@ -3403,7 +2400,6 @@ fn test_remove_stake_fee_goes_to_subnet_tao() { let hotkey = U256::from(2); let coldkey = U256::from(3); let tao_to_stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); @@ -3431,22 +2427,19 @@ fn test_remove_stake_fee_goes_to_subnet_tao() { // Subnet TAO should have increased by 2x fee as a result of staking + unstaking assert_abs_diff_eq!( - subnet_tao_before + 2 * fee, + subnet_tao_before, subnet_tao_after, epsilon = alpha_to_unstake / 1000 ); // User balance should decrease by 2x fee as a result of staking + unstaking let balance_after = SubtensorModule::get_coldkey_balance(&coldkey); - assert_abs_diff_eq!( - balance_after + 2 * fee, - tao_to_stake, - epsilon = tao_to_stake / 1000 - ); + assert_abs_diff_eq!(balance_after, tao_to_stake, epsilon = tao_to_stake / 1000); }); } // cargo test --package pallet-subtensor --lib -- tests::staking::test_remove_stake_fee_realistic_values --exact --show-output --nocapture +#[ignore = "fees are now calculated on the SwapInterface side"] #[test] fn test_remove_stake_fee_realistic_values() { new_test_ext(1).execute_with(|| { @@ -3468,8 +2461,7 @@ fn test_remove_stake_fee_realistic_values() { // This makes fee be equal ~0.0028 Alpha ~= 84000 rao let tao_reserve: U96F32 = U96F32::from_num(3_896_056_559_708_u64); let alpha_in: U96F32 = U96F32::from_num(128_011_331_299_964_u64); - SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); AlphaDividendsPerSubnet::::insert(netuid, hotkey, alpha_divs); TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, alpha_to_unstake); @@ -3483,15 +2475,7 @@ fn test_remove_stake_fee_realistic_values() { // Remove stake to measure fee let balance_before = SubtensorModule::get_coldkey_balance(&coldkey); - let expected_tao_no_fee = - SubtensorModule::sim_swap_alpha_for_tao(netuid, alpha_to_unstake).unwrap(); - - // Estimate fees - let mut expected_fee = - expected_tao_no_fee as f64 * alpha_divs as f64 / alpha_to_unstake as f64; - if expected_fee < expected_tao_no_fee as f64 * 0.00005 { - expected_fee = expected_tao_no_fee as f64 * 0.00005; - } + let (expected_tao, expected_fee) = mock::swap_alpha_to_tao(netuid, alpha_to_unstake); assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey), @@ -3502,14 +2486,12 @@ fn test_remove_stake_fee_realistic_values() { // Calculate expected fee let balance_after = SubtensorModule::get_coldkey_balance(&coldkey); - let actual_fee = expected_tao_no_fee as f64 - (balance_after - balance_before) as f64; + // FIXME since fee is calculated by SwapInterface and the values here are after fees, the + // actual_fee is 0. but it's left here to discuss in review + let actual_fee = expected_tao - (balance_after - balance_before); log::info!("Actual fee: {:?}", actual_fee); - assert_abs_diff_eq!( - actual_fee as u64, - expected_fee as u64, - epsilon = expected_fee as u64 / 1000 - ); + assert_abs_diff_eq!(actual_fee, expected_fee, epsilon = expected_fee / 1000); }); } @@ -3520,9 +2502,16 @@ fn test_stake_below_min_validate() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() + DefaultStakingFee::::get() - 1; - let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let amount_staked = { + let defaulte_stake = DefaultMinStake::::get(); + let fee = + ::SwapInterface::approx_fee_amount(netuid.into(), defaulte_stake); + let min_valid_stake = defaulte_stake + fee; + + min_valid_stake - 1 + }; + SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked); @@ -3536,20 +2525,32 @@ fn test_stake_below_min_validate() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); // Increase the stake to be equal to the minimum, but leave the balance low - let amount_staked = DefaultMinStake::::get() + DefaultStakingFee::::get(); + let amount_staked = { + let defaulte_stake = DefaultMinStake::::get(); + let fee = + ::SwapInterface::approx_fee_amount(netuid.into(), defaulte_stake); + + defaulte_stake + fee + }; let call_2 = RuntimeCall::SubtensorModule(SubtensorCall::add_stake { hotkey, netuid, @@ -3557,21 +2558,35 @@ fn test_stake_below_min_validate() { }); // Submit to the signed extension validate function - let result_low_balance = extension.validate(&coldkey, &call_2.clone(), &info, 10); + let result_low_balance = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call_2.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Still doesn't pass, but with a different reason (balance too low) - assert_err!( - result_low_balance, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::BalanceTooLow.into() - )) + assert_eq!( + result_low_balance.unwrap_err(), + CustomTransactionError::BalanceTooLow.into() ); // Increase the coldkey balance to match the minimum SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1); // Submit to the signed extension validate function - let result_min_stake = extension.validate(&coldkey, &call_2.clone(), &info, 10); + let result_min_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call_2.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call passes assert_ok!(result_min_stake); @@ -3590,14 +2605,15 @@ fn test_add_stake_limit_validate() { let amount = 900_000_000_000; // add network - let netuid: u16 = add_dynamic_network(&hotkey, &coldkey); + let netuid = add_dynamic_network(&hotkey, &coldkey); // Force-set alpha in and tao reserve to make price equal 1.5 let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // Give it some $$$ in his coldkey balance @@ -3619,16 +2635,22 @@ fn test_add_stake_limit_validate() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to slippage - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::SlippageTooHigh.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::SlippageTooHigh.into() ); }); } @@ -3646,7 +2668,7 @@ fn test_remove_stake_limit_validate() { let unstake_amount = 150_000_000_000; // add network - let netuid: u16 = add_dynamic_network(&hotkey, &coldkey); + let netuid = add_dynamic_network(&hotkey, &coldkey); // Give the neuron some stake to remove SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -3661,7 +2683,8 @@ fn test_remove_stake_limit_validate() { let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // Setup limit price so that it doesn't drop by more than 10% from current price @@ -3679,16 +2702,22 @@ fn test_remove_stake_limit_validate() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to slippage - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::SlippageTooHigh.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::SlippageTooHigh.into() ); }); } @@ -3702,17 +2731,16 @@ fn test_stake_overflow() { let hotkey_account_id = U256::from(54544); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let amount = 21_000_000_000_000_000; // Max TAO supply - let fee = DefaultStakingFee::::get(); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); // Setup liquidity with 21M TAO values - SubnetTAO::::insert(netuid, amount); - SubnetAlphaIn::::insert(netuid, amount); + mock::setup_reserves(netuid, amount, amount); // Stake and check if the result is ok + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, amount); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -3720,18 +2748,17 @@ fn test_stake_overflow() { amount )); - // Check if stake has increased properly (staking 1:1 to SubnetTAO results in SubnetTAO/2 alpha) - assert_abs_diff_eq!( + // Check if stake has increased properly + assert_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - (amount - fee) / 2, - epsilon = amount / 1_000_000, + expected_alpha ); // Check if total stake has increased accordingly. assert_abs_diff_eq!( SubtensorModule::get_total_stake(), amount + SubtensorModule::get_network_min_lock(), - epsilon = 10 + epsilon = 1 ); }); } @@ -3746,21 +2773,16 @@ fn test_stake_low_liquidity_validate() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() * 10 + DefaultStakingFee::::get(); + let amount_staked = DefaultMinStake::::get() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked); // Set the liquidity at lowest possible value so that all staking requests fail - SubnetTAO::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); - SubnetAlphaIn::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); + + let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; + mock::setup_reserves(netuid, reserve, reserve); // Add stake call let call = RuntimeCall::SubtensorModule(SubtensorCall::add_stake { @@ -3769,19 +2791,24 @@ fn test_stake_low_liquidity_validate() { amount_staked, }); - let info: DispatchInfo = - DispatchInfoOf::<::RuntimeCall>::default(); + let info = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::InsufficientLiquidity.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::InsufficientLiquidity.into() ); }); } @@ -3796,26 +2823,28 @@ fn test_unstake_low_liquidity_validate() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() * 10 + DefaultStakingFee::::get(); + let amount_staked = DefaultMinStake::::get() * 10; // FIXME: DefaultStakingFee is deprecated let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount_staked); // Simulate stake for hotkey - SubnetTAO::::insert(netuid, u64::MAX / 1000); - SubnetAlphaIn::::insert(netuid, u64::MAX / 1000); - let alpha = SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid, amount_staked, 0); + let reserve = u64::MAX / 1000; + mock::setup_reserves(netuid, reserve, reserve); - // Set the liquidity at lowest possible value so that all staking requests fail - SubnetTAO::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); - SubnetAlphaIn::::insert( + let alpha = SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); + amount_staked, + ::SwapInterface::max_price(), + ) + .unwrap(); + + // Set the liquidity at lowest possible value so that all staking requests fail + let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; + mock::setup_reserves(netuid, reserve, reserve); // Remove stake call let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake { @@ -3824,19 +2853,24 @@ fn test_unstake_low_liquidity_validate() { amount_unstaked: alpha, }); - let info: DispatchInfo = - DispatchInfoOf::<::RuntimeCall>::default(); + let info = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::InsufficientLiquidity.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::InsufficientLiquidity.into() ); }); } @@ -3851,7 +2885,7 @@ fn test_unstake_all_validate() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let amount_staked = DefaultMinStake::::get() * 10 + DefaultStakingFee::::get(); + let amount_staked = DefaultMinStake::::get() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); @@ -3860,17 +2894,18 @@ fn test_unstake_all_validate() { // Simulate stake for hotkey SubnetTAO::::insert(netuid, u64::MAX / 1000); SubnetAlphaIn::::insert(netuid, u64::MAX / 1000); - SubtensorModule::stake_into_subnet(&hotkey, &coldkey, netuid, amount_staked, 0); + SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + amount_staked, + ::SwapInterface::max_price(), + ) + .unwrap(); // Set the liquidity at lowest possible value so that all staking requests fail - SubnetTAO::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); - SubnetAlphaIn::::insert( - netuid, - DefaultMinimumPoolLiquidity::::get().to_num::(), - ); + let reserve = u64::from(mock::SwapMinimumReserve::get()) - 1; + mock::setup_reserves(netuid, reserve, reserve); // unstake_all call let call = RuntimeCall::SubtensorModule(SubtensorCall::unstake_all { hotkey }); @@ -3878,16 +2913,22 @@ fn test_unstake_all_validate() { let info: DispatchInfo = DispatchInfoOf::<::RuntimeCall>::default(); - let extension = SubtensorSignedExtension::::new(); + let extension = SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&coldkey, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(coldkey).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); }); } @@ -3897,31 +2938,31 @@ fn test_max_amount_add_root() { new_test_ext(0).execute_with(|| { // 0 price on root => max is 0 assert_eq!( - SubtensorModule::get_max_amount_add(0, 0), + SubtensorModule::get_max_amount_add(NetUid::ROOT, 0), Err(Error::::ZeroMaxStakeAmount) ); // 0.999999... price on root => max is 0 assert_eq!( - SubtensorModule::get_max_amount_add(0, 999_999_999), + SubtensorModule::get_max_amount_add(NetUid::ROOT, 999_999_999), Err(Error::::ZeroMaxStakeAmount) ); // 1.0 price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_add(0, 1_000_000_000), + SubtensorModule::get_max_amount_add(NetUid::ROOT, 1_000_000_000), Ok(u64::MAX) ); // 1.000...001 price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_add(0, 1_000_000_001), + SubtensorModule::get_max_amount_add(NetUid::ROOT, 1_000_000_001), Ok(u64::MAX) ); // 2.0 price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_add(0, 2_000_000_000), + SubtensorModule::get_max_amount_add(NetUid::ROOT, 2_000_000_000), Ok(u64::MAX) ); }); @@ -3930,7 +2971,7 @@ fn test_max_amount_add_root() { #[test] fn test_max_amount_add_stable() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // 0 price => max is 0 @@ -3968,201 +3009,137 @@ fn test_max_amount_add_stable() { // cargo test --package pallet-subtensor --lib -- tests::staking::test_max_amount_add_dynamic --exact --show-output #[test] fn test_max_amount_add_dynamic() { + // tao_in, alpha_in, limit_price, expected_max_swappable + [ + // Zero handling (no panics) + ( + 1_000_000_000, + 1_000_000_000, + 0, + Err(Error::::ZeroMaxStakeAmount), + ), + // Low bounds + (100, 100, 1_100_000_000, Ok(4)), + (1_000, 1_000, 1_100_000_000, Ok(48)), + (10_000, 10_000, 1_100_000_000, Ok(489)), + // Basic math + (1_000_000, 1_000_000, 4_000_000_000, Ok(1_000_000)), + (1_000_000, 1_000_000, 9_000_000_000, Ok(2_000_000)), + (1_000_000, 1_000_000, 16_000_000_000, Ok(3_000_000)), + ( + 1_000_000_000_000, + 1_000_000_000_000, + 16_000_000_000, + Ok(3_000_000_000_000), + ), + // Normal range values with edge cases + ( + 150_000_000_000, + 100_000_000_000, + 0, + Err(Error::::ZeroMaxStakeAmount), + ), + ( + 150_000_000_000, + 100_000_000_000, + 100_000_000, + Err(Error::::ZeroMaxStakeAmount), + ), + ( + 150_000_000_000, + 100_000_000_000, + 500_000_000, + Err(Error::::ZeroMaxStakeAmount), + ), + ( + 150_000_000_000, + 100_000_000_000, + 1_499_999_999, + Err(Error::::ZeroMaxStakeAmount), + ), + (150_000_000_000, 100_000_000_000, 1_500_000_000, Ok(5)), + (150_000_000_000, 100_000_000_000, 1_500_000_001, Ok(51)), + ( + 150_000_000_000, + 100_000_000_000, + 6_000_000_000, + Ok(150_000_000_000), + ), + // Miscellaneous overflows and underflows + (u64::MAX / 2, u64::MAX, u64::MAX, Ok(u64::MAX)), + ] + .into_iter() + .for_each(|(tao_in, alpha_in, limit_price, expected_max_swappable)| { + new_test_ext(0).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + + // Forse-set alpha in and tao reserve to achieve relative price of subnets + SubnetTAO::::insert(netuid, tao_in); + SubnetAlphaIn::::insert(netuid, alpha_in); + + // Force the swap to initialize + SubtensorModule::swap_tao_for_alpha(netuid, 0, 1_000_000_000_000).unwrap(); + + if alpha_in != 0 { + let expected_price = U96F32::from_num(tao_in) / U96F32::from_num(alpha_in); + assert_abs_diff_eq!( + ::SwapInterface::current_alpha_price(netuid.into()) + .to_num::(), + expected_price.to_num::(), + epsilon = expected_price.to_num::() / 1_000_f64 + ); + } + + match expected_max_swappable { + Err(e) => assert_err!(SubtensorModule::get_max_amount_add(netuid, limit_price), e), + Ok(v) => assert_abs_diff_eq!( + SubtensorModule::get_max_amount_add(netuid, limit_price).unwrap(), + v, + epsilon = v / 100 + ), + } + }); + }); +} + +#[test] +fn test_max_amount_remove_root() { new_test_ext(0).execute_with(|| { - let subnet_owner_coldkey = U256::from(1001); - let subnet_owner_hotkey = U256::from(1002); - let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - - // Test cases are generated with help with this limit-staking calculator: - // https://docs.google.com/spreadsheets/d/1pfU-PVycd3I4DbJIc0GjtPohy4CbhdV6CWqgiy__jKE - // This is for reference only; verify before use. - // - // CSV backup for this spreadhsheet: - // - // SubnetTAO,AlphaIn,initial price,limit price,max swappable - // 100,100,=A2/B2,4,=B8*D8-A8 - // - // tao_in, alpha_in, limit_price, expected_max_swappable - [ - // Zero handling (no panics) - ( - 0, - 1_000_000_000, - 100, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 1_000_000_000, - 0, - 100, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 1_000_000_000, - 1_000_000_000, - 0, - Err(Error::::ZeroMaxStakeAmount), - ), - // Low bounds - (1, 1, 0, Err(Error::::ZeroMaxStakeAmount)), - (1, 1, 1, Err(Error::::ZeroMaxStakeAmount)), - (1, 1, 2, Err(Error::::ZeroMaxStakeAmount)), - (1, 1, 50_000_000_000, Ok(49)), - // Basic math - (1_000, 1_000, 2_000_000_000, Ok(1_000)), - (1_000, 1_000, 4_000_000_000, Ok(3_000)), - (1_000, 1_000, 16_000_000_000, Ok(15_000)), - ( - 1_000_000_000_000, - 1_000_000_000_000, - 16_000_000_000, - Ok(15_000_000_000_000), - ), - // Normal range values with edge cases - ( - 150_000_000_000, - 100_000_000_000, - 0, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 150_000_000_000, - 100_000_000_000, - 100_000_000, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 150_000_000_000, - 100_000_000_000, - 500_000_000, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 150_000_000_000, - 100_000_000_000, - 1_499_999_999, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 150_000_000_000, - 100_000_000_000, - 1_500_000_000, - Err(Error::::ZeroMaxStakeAmount), - ), - (150_000_000_000, 100_000_000_000, 1_500_000_001, Ok(100)), - ( - 150_000_000_000, - 100_000_000_000, - 3_000_000_000, - Ok(150_000_000_000), - ), - // Miscellaneous overflows and underflows - (150_000_000_000, 100_000_000_000, u64::MAX, Ok(u64::MAX)), - (150_000_000_000, 100_000_000_000, u64::MAX / 2, Ok(u64::MAX)), - (1_000_000, 1_000_000_000_000_000_000_u64, 1, Ok(999_000_000)), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 2, - Ok(1_999_000_000), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 10_000, - Ok(9_999_999_000_000), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 100_000, - Ok(99_999_999_000_000), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 1_000_000, - Ok(999_999_999_000_000), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 1_000_000_000, - Ok(999_999_999_999_000_000), - ), - ( - 21_000_000_000_000_000, - 10_000_000, - 4_200_000_000_000_000_000, - Ok(21_000_000_000_000_000), - ), - ( - 21_000_000_000_000_000, - 1_000_000_000_000_000_000_u64, - u64::MAX, - Ok(u64::MAX), - ), - ( - 21_000_000_000_000_000, - 1_000_000_000_000_000_000_u64, - 42_000_000, - Ok(21_000_000_000_000_000), - ), - ] - .iter() - .for_each( - |&(tao_in, alpha_in, limit_price, ref expected_max_swappable)| { - // Forse-set alpha in and tao reserve to achieve relative price of subnets - SubnetTAO::::insert(netuid, tao_in); - SubnetAlphaIn::::insert(netuid, alpha_in); - - if alpha_in != 0 { - let expected_price = I96F32::from_num(tao_in) / I96F32::from_num(alpha_in); - assert_eq!(SubtensorModule::get_alpha_price(netuid), expected_price); - } - - assert_eq!( - SubtensorModule::get_max_amount_add(netuid, limit_price), - *expected_max_swappable, - ); - }, - ); - }); -} - -#[test] -fn test_max_amount_remove_root() { - new_test_ext(0).execute_with(|| { - // 0 price on root => max is u64::MAX - assert_eq!(SubtensorModule::get_max_amount_remove(0, 0), Ok(u64::MAX)); + // 0 price on root => max is u64::MAX + assert_eq!( + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 0), + Ok(u64::MAX) + ); // 0.5 price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_remove(0, 500_000_000), + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 500_000_000), Ok(u64::MAX) ); // 0.999999... price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_remove(0, 999_999_999), + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 999_999_999), Ok(u64::MAX) ); // 1.0 price on root => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_remove(0, 1_000_000_000), + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 1_000_000_000), Ok(u64::MAX) ); // 1.000...001 price on root => max is 0 assert_eq!( - SubtensorModule::get_max_amount_remove(0, 1_000_000_001), + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 1_000_000_001), Err(Error::::ZeroMaxStakeAmount) ); // 2.0 price on root => max is 0 assert_eq!( - SubtensorModule::get_max_amount_remove(0, 2_000_000_000), + SubtensorModule::get_max_amount_remove(NetUid::ROOT, 2_000_000_000), Err(Error::::ZeroMaxStakeAmount) ); }); @@ -4171,7 +3148,7 @@ fn test_max_amount_remove_root() { #[test] fn test_max_amount_remove_stable() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // 0 price => max is u64::MAX @@ -4214,15 +3191,6 @@ fn test_max_amount_remove_dynamic() { let subnet_owner_hotkey = U256::from(1002); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - // Test cases are generated with help with this limit-staking calculator: - // https://docs.google.com/spreadsheets/d/1pfU-PVycd3I4DbJIc0GjtPohy4CbhdV6CWqgiy__jKE - // This is for reference only; verify before use. - // - // CSV backup for this spreadhsheet: - // - // SubnetTAO,AlphaIn,initial price,limit price,max swappable - // 100,100,=A2/B2,4,=A2/D2-B2 - // // tao_in, alpha_in, limit_price, expected_max_swappable [ // Zero handling (no panics) @@ -4238,33 +3206,37 @@ fn test_max_amount_remove_dynamic() { 100, Err(Error::::ZeroMaxStakeAmount), ), - (1_000_000_000, 1_000_000_000, 0, Ok(u64::MAX)), - // Low bounds - (1, 1, 0, Ok(u64::MAX)), - (1, 1, 1, Ok(999_999_999)), - (1, 1, 2, Ok(499_999_999)), - (1, 1, 250_000_000, Ok(3)), + (10_000_000_000, 10_000_000_000, 0, Ok(u64::MAX)), + // Low bounds (numbers are empirical, it is only important that result + // is sharply decreasing when limit price increases) + (1_000, 1_000, 0, Ok(4_308_000_000_000)), + (1_001, 1_001, 0, Ok(4_310_000_000_000)), + (1_001, 1_001, 1, Ok(31_750_000)), + (1_001, 1_001, 2, Ok(22_500_000)), + (1_001, 1_001, 1_001, Ok(1_000_000)), + (1_001, 1_001, 10_000, Ok(316_000)), + (1_001, 1_001, 100_000, Ok(100_000)), // Basic math - (1_000, 1_000, 250_000_000, Ok(3_000)), - (1_000, 1_000, 62_500_000, Ok(15_000)), + (1_000_000, 1_000_000, 250_000_000, Ok(1_000_000)), + (1_000_000, 1_000_000, 62_500_000, Ok(3_000_000)), ( 1_000_000_000_000, 1_000_000_000_000, 62_500_000, - Ok(15_000_000_000_000), + Ok(3_000_000_000_000), ), - // Normal range values with edge cases + // Normal range values with edge cases and sanity checks (200_000_000_000, 100_000_000_000, 0, Ok(u64::MAX)), ( 200_000_000_000, 100_000_000_000, - 1_000_000_000, + 500_000_000, Ok(100_000_000_000), ), ( 200_000_000_000, 100_000_000_000, - 500_000_000, + 125_000_000, Ok(300_000_000_000), ), ( @@ -4279,69 +3251,39 @@ fn test_max_amount_remove_dynamic() { 2_000_000_001, Err(Error::::ZeroMaxStakeAmount), ), - (200_000_000_000, 100_000_000_000, 1_999_999_999, Ok(50)), - (200_000_000_000, 100_000_000_000, 1_999_999_990, Ok(500)), + (200_000_000_000, 100_000_000_000, 1_999_999_999, Ok(24)), + (200_000_000_000, 100_000_000_000, 1_999_999_990, Ok(252)), // Miscellaneous overflows and underflows ( - 2_000_000_000_000, - 100_000_000_000, - u64::MAX, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 200_000_000_000, - 100_000_000_000, - u64::MAX / 2, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 1, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 10, - Err(Error::::ZeroMaxStakeAmount), - ), - ( - 1_000_000, - 1_000_000_000_000_000_000_u64, - 100, - Err(Error::::ZeroMaxStakeAmount), - ), - ( + 21_000_000_000_000_000, 1_000_000, - 1_000_000_000_000_000_000_u64, - 1_000, - Err(Error::::ZeroMaxStakeAmount), + 21_000_000_000_000_000, + Ok(30_700_000), ), + (21_000_000_000_000_000, 1_000_000, u64::MAX, Ok(67_164)), ( - 1_000_000, - 1_000_000_000_000_000_000_u64, + 21_000_000_000_000_000, + 1_000_000_000_000_000_000, u64::MAX, Err(Error::::ZeroMaxStakeAmount), ), ( 21_000_000_000_000_000, - 1_000_000, - 21_000_000_000_000_000, - Ok(999_000_000), + 1_000_000_000_000_000_000, + 20_000_000, + Ok(24_800_000_000_000_000), ), - (21_000_000_000_000_000, 1_000_000, u64::MAX, Ok(138_412)), ( 21_000_000_000_000_000, - 1_000_000_000_000_000_000_u64, - u64::MAX, - Err(Error::::ZeroMaxStakeAmount), + 21_000_000_000_000_000, + 999_999_999, + Ok(10_500_000), ), ( 21_000_000_000_000_000, - 1_000_000_000_000_000_000_u64, - 20_000_000, - Ok(50_000_000_000_000_000), + 21_000_000_000_000_000, + 0, + Ok(u64::MAX), ), ] .iter() @@ -4353,13 +3295,27 @@ fn test_max_amount_remove_dynamic() { if alpha_in != 0 { let expected_price = I96F32::from_num(tao_in) / I96F32::from_num(alpha_in); - assert_eq!(SubtensorModule::get_alpha_price(netuid), expected_price); + assert_eq!( + ::SwapInterface::current_alpha_price(netuid.into()), + expected_price + ); } - assert_eq!( - SubtensorModule::get_max_amount_remove(netuid, limit_price), - *expected_max_swappable, - ); + match expected_max_swappable { + Err(_) => assert_err!( + SubtensorModule::get_max_amount_remove(netuid, limit_price), + Error::::ZeroMaxStakeAmount + ), + Ok(v) => { + let expected = v.saturating_add((*v as f64 * 0.003) as u64); + + assert_abs_diff_eq!( + SubtensorModule::get_max_amount_remove(netuid, limit_price).unwrap(), + expected, + epsilon = expected / 100 + ); + } + } }, ); }); @@ -4370,35 +3326,38 @@ fn test_max_amount_remove_dynamic() { fn test_max_amount_move_root_root() { new_test_ext(0).execute_with(|| { // 0 price on (root, root) exchange => max is u64::MAX - assert_eq!(SubtensorModule::get_max_amount_move(0, 0, 0), Ok(u64::MAX)); + assert_eq!( + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 0), + Ok(u64::MAX) + ); // 0.5 price on (root, root) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, 0, 500_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 500_000_000), Ok(u64::MAX) ); // 0.999999... price on (root, root) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, 0, 999_999_999), + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 999_999_999), Ok(u64::MAX) ); // 1.0 price on (root, root) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, 0, 1_000_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 1_000_000_000), Ok(u64::MAX) ); // 1.000...001 price on (root, root) => max is 0 assert_eq!( - SubtensorModule::get_max_amount_move(0, 0, 1_000_000_001), + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 1_000_000_001), Err(Error::::ZeroMaxStakeAmount) ); // 2.0 price on (root, root) => max is 0 assert_eq!( - SubtensorModule::get_max_amount_move(0, 0, 2_000_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 2_000_000_000), Err(Error::::ZeroMaxStakeAmount) ); }); @@ -4408,42 +3367,42 @@ fn test_max_amount_move_root_root() { #[test] fn test_max_amount_move_root_stable() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); // 0 price on (root, stable) exchange => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 0), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 0), Ok(u64::MAX) ); // 0.5 price on (root, stable) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 500_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 500_000_000), Ok(u64::MAX) ); // 0.999999... price on (root, stable) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 999_999_999), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 999_999_999), Ok(u64::MAX) ); // 1.0 price on (root, stable) => max is u64::MAX assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 1_000_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 1_000_000_000), Ok(u64::MAX) ); // 1.000...001 price on (root, stable) => max is 0 assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 1_000_000_001), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 1_000_000_001), Err(Error::::ZeroMaxStakeAmount) ); // 2.0 price on (root, stable) => max is 0 assert_eq!( - SubtensorModule::get_max_amount_move(0, netuid, 2_000_000_000), + SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 2_000_000_000), Err(Error::::ZeroMaxStakeAmount) ); }); @@ -4454,7 +3413,7 @@ fn test_max_amount_move_root_stable() { fn test_max_amount_move_stable_dynamic() { new_test_ext(0).execute_with(|| { // Add stable subnet - let stable_netuid: u16 = 1; + let stable_netuid = NetUid::from(1); add_network(stable_netuid, 1, 0); // Add dynamic subnet @@ -4462,13 +3421,13 @@ fn test_max_amount_move_stable_dynamic() { let subnet_owner_hotkey = U256::from(1002); let dynamic_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - // Forse-set alpha in and tao reserve to make price equal 0.5 + // Force-set alpha in and tao reserve to make price equal 0.5 let tao_reserve: U96F32 = U96F32::from_num(50_000_000_000_u64); let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(dynamic_netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(dynamic_netuid, alpha_in.to_num::()); - let current_price: U96F32 = - U96F32::from_num(SubtensorModule::get_alpha_price(dynamic_netuid)); + let current_price = + ::SwapInterface::current_alpha_price(dynamic_netuid.into()); assert_eq!(current_price, U96F32::from_num(0.5)); // The tests below just mimic the add_stake_limit tests for reverted price @@ -4492,11 +3451,12 @@ fn test_max_amount_move_stable_dynamic() { ); // 2x price => max is 1x TAO + let tao_reserve_u64 = tao_reserve.to_num::(); assert_abs_diff_eq!( - SubtensorModule::get_max_amount_move(stable_netuid, dynamic_netuid, 1_000_000_000) + SubtensorModule::get_max_amount_move(stable_netuid, dynamic_netuid, 500_000_000) .unwrap(), - 50_000_000_000, - epsilon = 10_000, + tao_reserve_u64 + (tao_reserve_u64 as f64 * 0.003) as u64, + epsilon = tao_reserve_u64 / 100, ); // Precision test: @@ -4528,7 +3488,7 @@ fn test_max_amount_move_stable_dynamic() { fn test_max_amount_move_dynamic_stable() { new_test_ext(0).execute_with(|| { // Add stable subnet - let stable_netuid: u16 = 1; + let stable_netuid = NetUid::from(1); add_network(stable_netuid, 1, 0); // Add dynamic subnet @@ -4541,8 +3501,8 @@ fn test_max_amount_move_dynamic_stable() { let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(dynamic_netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(dynamic_netuid, alpha_in.to_num::()); - let current_price: U96F32 = - U96F32::from_num(SubtensorModule::get_alpha_price(dynamic_netuid)); + let current_price = + ::SwapInterface::current_alpha_price(dynamic_netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // The tests below just mimic the remove_stake_limit tests @@ -4578,12 +3538,13 @@ fn test_max_amount_move_dynamic_stable() { epsilon = 10_000 ); - // 1/2 price => max is 1x Alpha + // 1/4 price => max is 1x Alpha + let alpha_in_u64 = alpha_in.to_num::(); assert_abs_diff_eq!( - SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 750_000_000) + SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 375_000_000) .unwrap(), - 100_000_000_000, - epsilon = 10_000, + alpha_in_u64 + (alpha_in_u64 as f64 * 0.003) as u64, + epsilon = alpha_in_u64 / 1000, ); // Precision test: @@ -4819,8 +3780,11 @@ fn test_max_amount_move_dynamic_dynamic() { if dest_price != 0 { let expected_price = origin_price / dest_price; assert_eq!( - SubtensorModule::get_alpha_price(origin_netuid) - / SubtensorModule::get_alpha_price(destination_netuid), + ::SwapInterface::current_alpha_price( + origin_netuid.into() + ) / ::SwapInterface::current_alpha_price( + destination_netuid.into() + ), expected_price ); } @@ -4847,17 +3811,16 @@ fn test_add_stake_limit_ok() { let hotkey_account_id = U256::from(533453); let coldkey_account_id = U256::from(55453); let amount = 900_000_000_000; // over the maximum - let fee = DefaultStakingFee::::get(); // add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Forse-set alpha in and tao reserve to make price equal 1.5 - let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); - SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let tao_reserve = U96F32::from_num(150_000_000_000_u64); + let alpha_in = U96F32::from_num(100_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // Give it some $$$ in his coldkey balance @@ -4866,7 +3829,7 @@ fn test_add_stake_limit_ok() { // Setup limit price so that it doesn't peak above 4x of current price // The amount that can be executed at this price is 450 TAO only // Alpha produced will be equal to 75 = 450*100/(450+150) - let limit_price = 6_000_000_000; + let limit_price = 24_000_000_000; let expected_executed_stake = 75_000_000_000; // Add stake with slippage safety and check if the result is ok @@ -4886,166 +3849,32 @@ fn test_add_stake_limit_ok() { &coldkey_account_id, netuid ), - expected_executed_stake - fee, + expected_executed_stake, epsilon = expected_executed_stake / 1000, ); - // Check that 450 TAO balance still remains free on coldkey + // Check that 450 TAO less fees balance still remains free on coldkey + let fee = ::SwapInterface::approx_fee_amount( + netuid.into(), + amount / 2, + ) as f64; assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), - 450_000_000_000, - epsilon = 10_000 + amount / 2 - fee as u64, + epsilon = amount / 2 / 1000 ); // Check that price has updated to ~24 = (150+450) / (100 - 75) let exp_price = U96F32::from_num(24.0); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); assert_abs_diff_eq!( exp_price.to_num::(), current_price.to_num::(), - epsilon = 0.0001, + epsilon = 0.001, ); }); } -// -// #[test] -// fn test_add_stake_limit_aggregate_ok() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let amount = 900_000_000_000; // over the maximum -// let fee = DefaultStakingFee::::get(); -// -// // add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// // Forse-set alpha in and tao reserve to make price equal 1.5 -// let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); -// let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); -// SubnetTAO::::insert(netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); -// let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); -// assert_eq!(current_price, U96F32::from_num(1.5)); -// -// // Give it some $$$ in his coldkey balance -// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); -// -// // Setup limit price so that it doesn't peak above 4x of current price -// // The amount that can be executed at this price is 450 TAO only -// // Alpha produced will be equal to 75 = 450*100/(450+150) -// let limit_price = 6_000_000_000; -// let expected_executed_stake = 75_000_000_000; -// -// // Add stake with slippage safety and check if the result is ok -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount, -// limit_price, -// true -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check if stake has increased only by 75 Alpha -// assert_abs_diff_eq!( -// SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid -// ), -// expected_executed_stake - fee, -// epsilon = expected_executed_stake / 1000, -// ); -// -// // Check that 450 TAO balance still remains free on coldkey -// assert_abs_diff_eq!( -// SubtensorModule::get_coldkey_balance(&coldkey_account_id), -// 450_000_000_000, -// epsilon = 10_000 -// ); -// -// // Check that price has updated to ~24 = (150+450) / (100 - 75) -// let exp_price = U96F32::from_num(24.0); -// let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); -// assert_abs_diff_eq!( -// exp_price.to_num::(), -// current_price.to_num::(), -// epsilon = 0.0001, -// ); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::StakeAdded(..)) -// ) -// })); -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeAdded(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_add_stake_limit_aggregate_fail() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let amount = 900_000_000_000; -// let limit_price = 6_000_000_000; -// // add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// assert_ok!(SubtensorModule::add_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// amount, -// limit_price, -// true -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToAddAggregatedLimitedStake(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToAddAggregatedLimitedStake(..)) -// ) -// })); -// }); -// } #[test] fn test_add_stake_limit_fill_or_kill() { @@ -5055,14 +3884,17 @@ fn test_add_stake_limit_fill_or_kill() { let amount = 900_000_000_000; // over the maximum // add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Force-set alpha in and tao reserve to make price equal 1.5 let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); + // FIXME it's failing because in the swap pallet, the alpha price is set only after an + // initial swap assert_eq!(current_price, U96F32::from_num(1.5)); // Give it some $$$ in his coldkey balance @@ -5071,7 +3903,7 @@ fn test_add_stake_limit_fill_or_kill() { // Setup limit price so that it doesn't peak above 4x of current price // The amount that can be executed at this price is 450 TAO only // Alpha produced will be equal to 25 = 100 - 450*100/(150+450) - let limit_price = 6_000_000_000; + let limit_price = 24_000_000_000; // Add stake with slippage safety and check if it fails assert_noop!( @@ -5112,7 +3944,7 @@ fn test_add_stake_limit_partial_zero_max_stake_amount_error() { let tao_reserve: U96F32 = U96F32::from_num(5_032_494_439_940_u64); let alpha_in: U96F32 = U96F32::from_num(186_268_425_402_874_u64); - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); @@ -5138,204 +3970,65 @@ fn test_remove_stake_limit_ok() { let hotkey_account_id = U256::from(533453); let coldkey_account_id = U256::from(55453); let stake_amount = 300_000_000_000; - let unstake_amount = 150_000_000_000; - let fee = DefaultStakingFee::::get(); // add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); - - // Give the neuron some stake to remove - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id, - netuid, - stake_amount, + stake_amount + ExistentialDeposit::get(), ); + + // Forse-set sufficient reserves + let tao_reserve: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + SubnetTAO::::insert(netuid, tao_reserve.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + + // Stake to hotkey account, and check if the result is ok + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + stake_amount + )); let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, &coldkey_account_id, netuid, ); - // Forse-set alpha in and tao reserve to make price equal 1.5 - let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); - SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); - assert_eq!(current_price, U96F32::from_num(1.5)); - - // Setup limit price so resulting average price doesn't drop by more than 10% from current price - let limit_price = 1_350_000_000; + // Setup limit price to 99% of current price + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); + let limit_price = (current_price.to_num::() * 990_000_000_f64) as u64; - // Alpha unstaked = 150 / 1.35 - 100 ~ 11.1 - let expected_alpha_reduction = 11_111_111_111; + // Alpha unstaked - calculated using formula from delta_in() + let expected_alpha_reduction = (0.00138 * alpha_in.to_num::()) as u64; + let fee: u64 = (expected_alpha_reduction as f64 * 0.003) as u64; // Remove stake with slippage safety assert_ok!(SubtensorModule::remove_stake_limit( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - unstake_amount, + alpha_before / 2, limit_price, true )); + let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid, + ); - // Check if stake has decreased only by + // Check if stake has decreased properly assert_abs_diff_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_account_id, - &coldkey_account_id, - netuid - ), - alpha_before - expected_alpha_reduction - fee, - epsilon = expected_alpha_reduction / 1_000, + alpha_before - alpha_after, + expected_alpha_reduction + fee, + epsilon = expected_alpha_reduction / 10, ); }); } -// -// #[test] -// fn test_remove_stake_limit_aggregate_ok() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let stake_amount = 300_000_000_000; -// let unstake_amount = 150_000_000_000; -// let fee = DefaultStakingFee::::get(); -// -// // add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// stake_amount, -// ); -// let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// ); -// -// // Forse-set alpha in and tao reserve to make price equal 1.5 -// let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); -// let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); -// SubnetTAO::::insert(netuid, tao_reserve.to_num::()); -// SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); -// let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); -// assert_eq!(current_price, U96F32::from_num(1.5)); -// -// // Setup limit price so resulting average price doesn't drop by more than 10% from current price -// let limit_price = 1_350_000_000; -// -// // Alpha unstaked = 150 / 1.35 - 100 ~ 11.1 -// let expected_alpha_reduction = 11_111_111_111; -// -// // Remove stake with slippage safety -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// unstake_amount, -// limit_price, -// true -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check if stake has decreased only by -// assert_abs_diff_eq!( -// SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid -// ), -// alpha_before - expected_alpha_reduction - fee, -// epsilon = expected_alpha_reduction / 1_000, -// ); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::StakeRemoved(..)) -// ) -// })); -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedLimitedStakeRemoved(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_remove_stake_limit_aggregate_fail() { -// new_test_ext(1).execute_with(|| { -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55453); -// let stake_amount = 300_000_000; -// let unstake_amount = 150_000_000_000; -// let limit_price = 1_350_000_000; -// // add network -// let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); -// -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// stake_amount, -// ); -// -// assert_ok!(SubtensorModule::remove_stake_limit_aggregate( -// RuntimeOrigin::signed(coldkey_account_id), -// hotkey_account_id, -// netuid, -// unstake_amount, -// limit_price, -// true -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToRemoveAggregatedLimitedStake(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::FailedToRemoveAggregatedLimitedStake(..)) -// ) -// })); -// }); -// } #[test] fn test_remove_stake_limit_fill_or_kill() { @@ -5346,7 +4039,7 @@ fn test_remove_stake_limit_fill_or_kill() { let unstake_amount = 150_000_000_000; // add network - let netuid: u16 = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); + let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); // Give the neuron some stake to remove SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -5361,7 +4054,8 @@ fn test_remove_stake_limit_fill_or_kill() { let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); - let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // Setup limit price so that it doesn't drop by more than 10% from current price @@ -5392,127 +4086,6 @@ fn test_remove_stake_limit_fill_or_kill() { }); } -// #[test] -// fn test_add_stake_specific() { -// new_test_ext(1).execute_with(|| { -// let sn_owner_coldkey = U256::from(55453); - -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55454); -// let hotkey_owner_account_id = U256::from(533454); - -// let existing_shares: U64F64 = -// U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX)); -// let existing_stake = 36_711_495_953; -// let amount_added = 1_274_280_132; - -// //add network -// let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); - -// // Register hotkey on netuid -// register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0); -// // Check we have zero staked -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// 0 -// ); - -// // Set a hotkey pool for the hotkey -// let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid); -// hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden - -// // Adjust the total hotkey stake and shares to match the existing values -// TotalHotkeyShares::::insert(hotkey_account_id, netuid, existing_shares); -// TotalHotkeyAlpha::::insert(hotkey_account_id, netuid, existing_stake); - -// // Make the hotkey a delegate -// Delegates::::insert(hotkey_account_id, 0); - -// // Add stake as new hotkey -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// amount_added, -// ); - -// // Check the stake and shares are correct -// assert!(Alpha::::get((&hotkey_account_id, &coldkey_account_id, netuid)) > 0); -// assert_eq!( -// TotalHotkeyAlpha::::get(hotkey_account_id, netuid), -// amount_added + existing_stake -// ); -// }); -// } - -// #[test] -// // RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_specific_stake_into_subnet --exact --show-output -// fn test_add_stake_specific_stake_into_subnet() { -// new_test_ext(1).execute_with(|| { -// let sn_owner_coldkey = U256::from(55453); - -// let hotkey_account_id = U256::from(533453); -// let coldkey_account_id = U256::from(55454); -// let hotkey_owner_account_id = U256::from(533454); - -// let existing_shares: U64F64 = -// U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX)); -// let existing_stake = 36_711_495_953; - -// let tao_in = 2_409_892_148_947; -// let alpha_in = 15_358_708_513_716; - -// let tao_staked = 200_000_000; -// let fee = DefaultStakingFee::::get(); - -// //add network -// let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); - -// // Register hotkey on netuid -// register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0); -// // Check we have zero staked -// assert_eq!( -// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), -// 0 -// ); - -// // Set a hotkey pool for the hotkey -// let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid); -// hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden - -// // Adjust the total hotkey stake and shares to match the existing values -// TotalHotkeyShares::::insert(hotkey_account_id, netuid, existing_shares); -// TotalHotkeyAlpha::::insert(hotkey_account_id, netuid, existing_stake); - -// // Make the hotkey a delegate -// Delegates::::insert(hotkey_account_id, 0); - -// // Setup Subnet pool -// SubnetAlphaIn::::insert(netuid, alpha_in); -// SubnetTAO::::insert(netuid, tao_in); - -// // Add stake as new hotkey -// SubtensorModule::stake_into_subnet( -// &hotkey_account_id, -// &coldkey_account_id, -// netuid, -// tao_staked, -// fee, -// ); - -// // Check the stake and shares are correct -// assert!(Alpha::::get((&hotkey_account_id, &coldkey_account_id, netuid)) > 0); -// log::info!( -// "Alpha: {}", -// Alpha::::get((&hotkey_account_id, &coldkey_account_id, netuid)) -// ); -// log::info!( -// "TotalHotkeyAlpha: {}", -// TotalHotkeyAlpha::::get(hotkey_account_id, netuid) -// ); -// }); -// } - #[test] // RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_specific_stake_into_subnet_fail --exact --show-output fn test_add_stake_specific_stake_into_subnet_fail() { @@ -5533,7 +4106,7 @@ fn test_add_stake_specific_stake_into_subnet_fail() { let tao_staked = 200_000_000; //add network - let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); + let netuid = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey); // Register hotkey on netuid register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0); @@ -5565,8 +4138,15 @@ fn test_add_stake_specific_stake_into_subnet_fail() { ); // Add stake as new hotkey - let expected_alpha = - SubtensorModule::sim_swap_tao_for_alpha(netuid, tao_staked).unwrap_or(0); + let expected_alpha = ::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + tao_staked, + ::SwapInterface::max_price(), + true, + ) + .map(|v| v.amount_paid_out) + .unwrap_or_default(); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -5597,8 +4177,7 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { let hotkey_account_id = U256::from(581337); let coldkey_account_id = U256::from(81337); let amount = 10_000_000_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let mut fee = DefaultStakingFee::::get(); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance @@ -5619,6 +4198,8 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { netuid, ); let remove_amount = (U64F64::from_num(alpha) * U64F64::from_num(0.999991)).to_num::(); + // we expected the entire stake to be returned + let (expected_balance, _) = mock::swap_alpha_to_tao(netuid, alpha); assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -5627,11 +4208,10 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { )); // Check that all alpha was unstaked and all TAO balance was returned (less fees) - fee = fee + fee.max((remove_amount as f64 * 0.00005) as u64); assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), - amount - fee, - epsilon = 100000, + expected_balance, + epsilon = 10, ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), @@ -5655,14 +4235,14 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { let hotkey_account_id = U256::from(581337); let coldkey_account_id = U256::from(81337); let amount = 10_000_000_000; - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = DefaultStakingFee::::get(); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); // Stake to hotkey account, and check if the result is ok + let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -5676,6 +4256,7 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { &coldkey_account_id, netuid, ); + let fee = mock::swap_alpha_to_tao(netuid, (alpha as f64 * 0.99) as u64).1 + fee; assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -5684,9 +4265,10 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { )); // Check that all alpha was unstaked and 99% TAO balance was returned (less fees) + // let fee = ::SwapInterface::approx_fee_amount(netuid.into(), (amount as f64 * 0.99) as u64); assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), - (amount as f64 * 0.99) as u64 - fee * 2, + (amount as f64 * 0.99) as u64 - fee, epsilon = amount / 1000, ); assert_abs_diff_eq!( @@ -5714,9 +4296,8 @@ fn test_move_stake_limit_partial() { let move_amount = 150_000_000_000; // add network - let origin_netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let destination_netuid: u16 = - add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let origin_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let destination_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(origin_netuid, hotkey, coldkey, 192213123); register_ok_neuron(destination_netuid, hotkey, coldkey, 192213123); @@ -5736,8 +4317,8 @@ fn test_move_stake_limit_partial() { SubnetAlphaIn::::insert(origin_netuid, alpha_in.to_num::()); SubnetTAO::::insert(destination_netuid, (tao_reserve * 100_000).to_num::()); SubnetAlphaIn::::insert(destination_netuid, (alpha_in * 100_000).to_num::()); - let current_price: U96F32 = - U96F32::from_num(SubtensorModule::get_alpha_price(origin_netuid)); + let current_price = + ::SwapInterface::current_alpha_price(origin_netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); // The relative price between origin and destination subnets is 1. @@ -5775,7 +4356,7 @@ fn test_unstake_all_hits_liquidity_min() { let stake_amount = 190_000_000_000; // 190 Alpha - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); // Give the neuron some stake to remove SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -5786,17 +4367,16 @@ fn test_unstake_all_hits_liquidity_min() { ); // Setup the Alpha pool so that removing all the Alpha will bring liqudity below the minimum - let remaining_tao: I96F32 = - DefaultMinimumPoolLiquidity::::get().saturating_sub(I96F32::from(1)); - let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); + let remaining_tao = I96F32::from_num(u64::from(mock::SwapMinimumReserve::get()) - 1) + .saturating_sub(I96F32::from(1)); + let alpha_reserves = I110F18::from(stake_amount + 10_000_000); let alpha = stake_amount; - let k: I110F18 = I110F18::from_fixed(remaining_tao) + let k = I110F18::from_fixed(remaining_tao) .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); - let tao_reserves: I110F18 = k.safe_div(alpha_reserves); + let tao_reserves = k.safe_div(alpha_reserves); - SubnetTAO::::insert(netuid, tao_reserves.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); + mock::setup_reserves(netuid, tao_reserves.to_num(), alpha_reserves.to_num()); // Try to unstake, but we reduce liquidity too far @@ -5820,42 +4400,50 @@ fn test_unstake_all_alpha_hits_liquidity_min() { let coldkey = U256::from(1); let hotkey = U256::from(2); - let stake_amount = 190_000_000_000; // 190 Alpha + let stake_amount = 100_000_000_000; // 100 TAO - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - // Give the neuron some stake to remove - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, + SubtensorModule::add_balance_to_coldkey_account( &coldkey, - netuid, - stake_amount, + stake_amount + ExistentialDeposit::get(), ); + // Give the neuron some stake to remove + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + stake_amount + )); - // Setup the Alpha pool so that removing all the Alpha will bring liqudity below the minimum - let remaining_tao: I96F32 = - DefaultMinimumPoolLiquidity::::get().saturating_sub(I96F32::from(1)); - let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); - let alpha = stake_amount; + // Setup the pool so that removing all the TAO will bring liqudity below the minimum + let remaining_tao = I96F32::from_num(u64::from(mock::SwapMinimumReserve::get()) - 1) + .saturating_sub(I96F32::from(1)); + let alpha = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); + let alpha_reserves = I110F18::from(alpha + 10_000_000); - let k: I110F18 = I110F18::from_fixed(remaining_tao) + let k = I110F18::from_fixed(remaining_tao) .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); - let tao_reserves: I110F18 = k.safe_div(alpha_reserves); + let tao_reserves = k.safe_div(alpha_reserves); - SubnetTAO::::insert(netuid, tao_reserves.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); + mock::setup_reserves( + netuid, + tao_reserves.to_num::() / 100_u64, + alpha_reserves.to_num(), + ); // Try to unstake, but we reduce liquidity too far - assert_ok!(SubtensorModule::unstake_all_alpha( - RuntimeOrigin::signed(coldkey), - hotkey, - )); - + assert_err!( + SubtensorModule::unstake_all_alpha(RuntimeOrigin::signed(coldkey), hotkey), + Error::::AmountTooLow + ); + // Expect nothing to be unstaked let new_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - assert_abs_diff_eq!(new_alpha, stake_amount, epsilon = 0,); + assert_eq!(new_alpha, alpha); }); } @@ -5867,30 +4455,25 @@ fn test_unstake_all_alpha_works() { let coldkey = U256::from(1); let hotkey = U256::from(2); - let stake_amount = 190_000_000_000; // 190 Alpha + let stake_amount = 190_000_000_000; // 190 TAO - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - // Give the neuron some stake to remove - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, + SubtensorModule::add_balance_to_coldkey_account( &coldkey, - netuid, - stake_amount, + stake_amount + ExistentialDeposit::get(), ); - // Setup the Alpha pool so that removing all the Alpha will keep liq above min - let remaining_tao: I96F32 = - DefaultMinimumPoolLiquidity::::get().saturating_add(I96F32::from(10_000_000)); - let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); - let alpha = stake_amount; - - let k: I110F18 = I110F18::from_fixed(remaining_tao) - .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); - let tao_reserves: I110F18 = k.safe_div(alpha_reserves); + // Give the neuron some stake to remove + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + stake_amount + )); - SubnetTAO::::insert(netuid, tao_reserves.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); + // Setup the pool so that removing all the TAO will keep liq above min + mock::setup_reserves(netuid, stake_amount * 10, stake_amount * 100); // Unstake all alpha to root assert_ok!(SubtensorModule::unstake_all_alpha( @@ -5900,116 +4483,15 @@ fn test_unstake_all_alpha_works() { let new_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000,); - let new_root = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, 0); + assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000); + let new_root = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + ); assert!(new_root > 100_000); }); } -// #[test] -// fn test_unstake_all_alpha_aggregate_works() { -// new_test_ext(1).execute_with(|| { -// let subnet_owner_coldkey = U256::from(1001); -// let subnet_owner_hotkey = U256::from(1002); -// let coldkey = U256::from(1); -// let hotkey = U256::from(2); -// -// let stake_amount = 190_000_000_000; // 190 Alpha -// -// let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); -// register_ok_neuron(netuid, hotkey, coldkey, 192213123); -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey, -// &coldkey, -// netuid, -// stake_amount, -// ); -// -// // Setup the Alpha pool so that removing all the Alpha will keep liq above min -// let remaining_tao: I96F32 = -// DefaultMinimumPoolLiquidity::::get().saturating_add(I96F32::from(10_000_000)); -// let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); -// let alpha = stake_amount; -// -// let k: I110F18 = I110F18::from_fixed(remaining_tao) -// .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); -// let tao_reserves: I110F18 = k.safe_div(alpha_reserves); -// -// SubnetTAO::::insert(netuid, tao_reserves.to_num::()); -// SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); -// -// // Unstake all alpha to root -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkey), -// hotkey, -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// let new_alpha = -// SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); -// assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000,); -// let new_root = -// SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, 0); -// assert!(new_root > 100_000); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaSucceeded(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_unstake_all_alpha_aggregate_fails() { -// new_test_ext(1).execute_with(|| { -// let coldkey = U256::from(1); -// let hotkey = U256::from(2); -// -// assert_ok!(SubtensorModule::unstake_all_alpha_aggregate( -// RuntimeOrigin::signed(coldkey), -// hotkey, -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaFailed(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllAlphaFailed(..)) -// ) -// })); -// }); -// } #[test] fn test_unstake_all_works() { @@ -6019,32 +4501,27 @@ fn test_unstake_all_works() { let coldkey = U256::from(1); let hotkey = U256::from(2); - let stake_amount = 190_000_000_000; // 190 Alpha + let stake_amount = 190_000_000_000; // 190 TAO - let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); - // Give the neuron some stake to remove - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, + SubtensorModule::add_balance_to_coldkey_account( &coldkey, - netuid, - stake_amount, + stake_amount + ExistentialDeposit::get(), ); - // Setup the Alpha pool so that removing all the Alpha will keep liq above min - let remaining_tao: I96F32 = - DefaultMinimumPoolLiquidity::::get().saturating_add(I96F32::from(10_000_000)); - let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); - let alpha = stake_amount; - - let k: I110F18 = I110F18::from_fixed(remaining_tao) - .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); - let tao_reserves: I110F18 = k.safe_div(alpha_reserves); + // Give the neuron some stake to remove + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + stake_amount + )); - SubnetTAO::::insert(netuid, tao_reserves.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); + // Setup the pool so that removing all the TAO will keep liq above min + mock::setup_reserves(netuid, stake_amount * 10, stake_amount * 100); - // Unstake all alpha to root + // Unstake all alpha to free balance assert_ok!(SubtensorModule::unstake_all( RuntimeOrigin::signed(coldkey), hotkey, @@ -6052,116 +4529,484 @@ fn test_unstake_all_works() { let new_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000,); + assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000); let new_balance = SubtensorModule::get_coldkey_balance(&coldkey); assert!(new_balance > 100_000); }); } -// #[test] -// fn test_unstake_all_aggregate_works() { -// new_test_ext(1).execute_with(|| { -// let subnet_owner_coldkey = U256::from(1001); -// let subnet_owner_hotkey = U256::from(1002); -// let coldkey = U256::from(1); -// let hotkey = U256::from(2); -// -// let stake_amount = 190_000_000_000; // 190 Alpha -// -// let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); -// register_ok_neuron(netuid, hotkey, coldkey, 192213123); -// // Give the neuron some stake to remove -// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( -// &hotkey, -// &coldkey, -// netuid, -// stake_amount, -// ); -// -// // Setup the Alpha pool so that removing all the Alpha will keep liq above min -// let remaining_tao: I96F32 = -// DefaultMinimumPoolLiquidity::::get().saturating_add(I96F32::from(10_000_000)); -// let alpha_reserves: I110F18 = I110F18::from(stake_amount + 10_000_000); -// let alpha = stake_amount; -// -// let k: I110F18 = I110F18::from_fixed(remaining_tao) -// .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); -// let tao_reserves: I110F18 = k.safe_div(alpha_reserves); -// -// SubnetTAO::::insert(netuid, tao_reserves.to_num::()); -// SubnetAlphaIn::::insert(netuid, alpha_reserves.to_num::()); -// -// // Unstake all alpha to root -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkey), -// hotkey, -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// let new_alpha = -// SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); -// assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000,); -// let new_balance = SubtensorModule::get_coldkey_balance(&coldkey); -// assert!(new_balance > 100_000); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllSucceeded(..)) -// ) -// })); -// }); -// } -// -// #[test] -// fn test_unstake_all_aggregate_fails() { -// new_test_ext(1).execute_with(|| { -// let coldkey = U256::from(1); -// let hotkey = U256::from(2); -// -// // Unstake all alpha to root -// assert_ok!(SubtensorModule::unstake_all_aggregate( -// RuntimeOrigin::signed(coldkey), -// hotkey, -// )); -// -// // Check for the block delay -// run_to_block_ext(2, true); -// -// // Check that event was not emitted. -// assert!(System::events().iter().all(|e| { -// !matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllFailed(..)) -// ) -// })); -// -// // Enable on_finalize code to run -// run_to_block_ext(3, true); -// -// // Check that event was emitted. -// assert!(System::events().iter().any(|e| { -// matches!( -// &e.event, -// RuntimeEvent::SubtensorModule(Event::AggregatedUnstakeAllFailed(..)) -// ) -// })); -// }); -// } +#[test] +fn test_stake_into_subnet_ok() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let hotkey = U256::from(3); + let coldkey = U256::from(4); + let amount = 100_000_000; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()) + .to_num::(); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake with slippage safety and check if the result is ok + assert_ok!(SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + amount, + u64::MAX, + )); + let expected_stake = (amount as f64) * 0.997 / current_price; + + // Check if stake has increased + assert_abs_diff_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) + as f64, + expected_stake, + epsilon = expected_stake / 1000., + ); + }); +} + +#[test] +fn test_stake_into_subnet_low_amount() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let hotkey = U256::from(3); + let coldkey = U256::from(4); + let amount = 10; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()) + .to_num::(); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake with slippage safety and check if the result is ok + assert_ok!(SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + amount, + u64::MAX, + )); + let expected_stake = ((amount as f64) * 0.997 / current_price) as u64; + + // Check if stake has increased + assert_abs_diff_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) + as u64, + expected_stake, + epsilon = expected_stake / 100, + ); + }); +} + +#[test] +fn test_unstake_from_subnet_low_amount() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let hotkey = U256::from(3); + let coldkey = U256::from(4); + let amount = 10; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake and check if the result is ok + assert_ok!(SubtensorModule::stake_into_subnet( + &hotkey, + &coldkey, + netuid, + amount, + u64::MAX, + )); + + // Remove stake + let alpha = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); + assert_ok!(SubtensorModule::unstake_from_subnet( + &hotkey, + &coldkey, + netuid, + alpha, + u64::MIN, + )); + + // Check if stake is zero + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), + 0, + ); + }); +} + +#[test] +fn test_stake_into_subnet_prohibitive_limit() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let amount = 100_000_000; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake and check if the result is ok + // Use prohibitive limit price + assert_err!( + SubtensorModule::add_stake_limit( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + amount, + 0, + true, + ), + Error::::ZeroMaxStakeAmount + ); + + // Check if stake has NOT increased + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid + ), + 0_u64 + ); + + // Check if balance has NOT decreased + assert_eq!(SubtensorModule::get_coldkey_balance(&coldkey), amount); + }); +} + +#[test] +fn test_unstake_from_subnet_prohibitive_limit() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let amount = 100_000_000; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake and check if the result is ok + assert_ok!(SubtensorModule::stake_into_subnet( + &owner_hotkey, + &coldkey, + netuid, + amount, + u64::MAX, + )); + + // Remove stake + // Use prohibitive limit price + let balance_before = SubtensorModule::get_coldkey_balance(&coldkey); + let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid, + ); + assert_err!( + SubtensorModule::remove_stake_limit( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + alpha, + u64::MAX, + true, + ), + Error::::ZeroMaxStakeAmount + ); + + // Check if stake has NOT decreased + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid + ), + alpha + ); + + // Check if balance has NOT increased + assert_eq!( + SubtensorModule::get_coldkey_balance(&coldkey), + balance_before, + ); + }); +} + +#[test] +fn test_unstake_full_amount() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let amount = 100_000_000; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount); + + // Forse-set alpha in and tao reserve to make price equal 0.01 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(1_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Initialize swap v3 + assert_ok!(::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + 0, + 0, + true + )); + + // Add stake and check if the result is ok + assert_ok!(SubtensorModule::stake_into_subnet( + &owner_hotkey, + &coldkey, + netuid, + amount, + u64::MAX, + )); + + // Remove stake + // Use prohibitive limit price + let balance_before = SubtensorModule::get_coldkey_balance(&coldkey); + let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid, + ); + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + alpha, + )); + + // Check if stake is zero + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid + ), + 0 + ); + + // Check if balance has increased accordingly + let balance_after = SubtensorModule::get_coldkey_balance(&coldkey); + let actual_balance_increase = (balance_after - balance_before) as f64; + let fee_rate = pallet_subtensor_swap::FeeRate::::get(NetUid::from(netuid)) as f64 + / u16::MAX as f64; + let expected_balance_increase = amount as f64 * (1. - fee_rate) / (1. + fee_rate); + assert_abs_diff_eq!( + actual_balance_increase, + expected_balance_increase, + epsilon = expected_balance_increase / 10_000. + ); + }); +} + +fn price_to_tick(price: f64) -> TickIndex { + let price_sqrt: U64F64 = U64F64::from_num(price.sqrt()); + // Handle potential errors in the conversion + match TickIndex::try_from_sqrt_price(price_sqrt) { + Ok(mut tick) => { + // Ensure the tick is within bounds + if tick > TickIndex::MAX { + tick = TickIndex::MAX; + } else if tick < TickIndex::MIN { + tick = TickIndex::MIN; + } + tick + } + // Default to a reasonable value when conversion fails + Err(_) => { + if price > 1.0 { + TickIndex::MAX + } else { + TickIndex::MIN + } + } + } +} + +/// Test correctness of swap fees: +/// 1. TAO is not minted or burned +/// 2. Fees match FeeRate +/// +#[test] +fn test_swap_fees_tao_correctness() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let amount = 1_000_000_000; + let owner_balance_before = amount * 10; + let user_balance_before = amount * 100; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, user_balance_before); + let fee_rate = pallet_subtensor_swap::FeeRate::::get(NetUid::from(netuid)) as f64 + / u16::MAX as f64; + pallet_subtensor_swap::EnabledUserLiquidity::::insert(NetUid::from(netuid), true); + + // Forse-set alpha in and tao reserve to make price equal 0.25 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(400_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Check starting "total TAO" + let total_tao_before = + user_balance_before + owner_balance_before + SubnetTAO::::get(netuid); + + // Get alpha for owner + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(owner_coldkey), + owner_hotkey, + netuid, + amount, + )); + let mut fees = (fee_rate * amount as f64) as u64; + + // Add owner coldkey Alpha as concentrated liquidity + // between current price current price + 0.01 + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()) + .to_num::() + + 0.0001; + let limit_price = current_price + 0.01; + let tick_low = price_to_tick(current_price); + let tick_high = price_to_tick(limit_price); + let liquidity = amount; + + assert_ok!(::SwapInterface::do_add_liquidity( + netuid.into(), + &owner_coldkey, + &owner_hotkey, + tick_low, + tick_high, + liquidity, + )); + + // Limit-buy and then sell all alpha for user to hit owner liquidity + assert_ok!(SubtensorModule::add_stake_limit( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + amount, + (limit_price * u64::MAX as f64) as u64, + true + )); + fees += (fee_rate * amount as f64) as u64; + + let user_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid, + ); + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + user_alpha, + )); + // Do not add fees because selling fees are in alpha + + // Check ending "total TAO" + let owner_balance_after = SubtensorModule::get_coldkey_balance(&owner_coldkey); + let user_balance_after = SubtensorModule::get_coldkey_balance(&coldkey); + let total_tao_after = + user_balance_after + owner_balance_after + SubnetTAO::::get(netuid) + fees; + + // Total TAO does not change, leave some epsilon for rounding + assert_abs_diff_eq!(total_tao_before, total_tao_after, epsilon = 2,); + }); +} #[test] fn test_increase_stake_for_hotkey_and_coldkey_on_subnet_adds_to_staking_hotkeys_map() { @@ -6170,7 +5015,7 @@ fn test_increase_stake_for_hotkey_and_coldkey_on_subnet_adds_to_staking_hotkeys_ let coldkey1 = U256::from(2); let hotkey = U256::from(3); - let netuid = 1; + let netuid = NetUid::from(1); let stake_amount = 100_000_000_000; // Check no entry in the staking hotkeys map @@ -6209,3 +5054,264 @@ fn test_increase_stake_for_hotkey_and_coldkey_on_subnet_adds_to_staking_hotkeys_ assert!(StakingHotkeys::::get(coldkey1).contains(&hotkey)); }); } + +/// This test verifies that minimum stake amount is sufficient to move price and apply +/// non-zero staking fees +#[test] +fn test_default_min_stake_sufficiency() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let min_tao_stake = DefaultMinStake::::get() * 2; + let amount = min_tao_stake; + let owner_balance_before = amount * 10; + let user_balance_before = amount * 100; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, owner_balance_before); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, user_balance_before); + let fee_rate = pallet_subtensor_swap::FeeRate::::get(NetUid::from(netuid)) as f64 + / u16::MAX as f64; + + // Set some extreme, but realistic TAO and Alpha reserves to minimize slippage + // 1% of TAO max supply + // 0.01 Alpha price + let tao_reserve = U96F32::from_num(210_000_000_000_000_u64); + let alpha_in = U96F32::from_num(21_000_000_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + let current_price_before = + ::SwapInterface::current_alpha_price(netuid.into()); + + // Stake and unstake + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + amount, + )); + let fee_stake = (fee_rate * amount as f64) as u64; + let current_price_after_stake = + ::SwapInterface::current_alpha_price(netuid.into()); + + let user_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid, + ); + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + user_alpha, + )); + let fee_unstake = (fee_rate * user_alpha as f64) as u64; + let current_price_after_unstake = + ::SwapInterface::current_alpha_price(netuid.into()); + + assert!(fee_stake > 0); + assert!(fee_unstake > 0); + assert!(current_price_after_stake > current_price_before); + assert!(current_price_after_stake > current_price_after_unstake); + }); +} + +/// Test that modify_position always credits fees +/// +/// cargo test --package pallet-subtensor --lib -- tests::staking::test_update_position_fees --exact --show-output +#[test] +fn test_update_position_fees() { + // Test cases: add or remove liquidity during modification + [false, true].into_iter().for_each(|add| { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(4); + let amount = 1_000_000_000; + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&owner_coldkey, amount * 10); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount * 100); + pallet_subtensor_swap::EnabledUserLiquidity::::insert(NetUid::from(netuid), true); + + // Forse-set alpha in and tao reserve to make price equal 0.25 + let tao_reserve = U96F32::from_num(100_000_000_000_u64); + let alpha_in = U96F32::from_num(400_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + + // Get alpha for owner + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(owner_coldkey), + owner_hotkey, + netuid, + amount, + )); + + // Add owner coldkey Alpha as concentrated liquidity + // between current price current price + 0.01 + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()) + .to_num::() + + 0.0001; + let limit_price = current_price + 0.001; + let tick_low = price_to_tick(current_price); + let tick_high = price_to_tick(limit_price); + let liquidity = amount; + + let (position_id, _, _) = ::SwapInterface::do_add_liquidity( + NetUid::from(netuid), + &owner_coldkey, + &owner_hotkey, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + // Buy and then sell all alpha for user to hit owner liquidity + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + amount, + )); + + let user_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &coldkey, + netuid, + ); + assert_ok!(SubtensorModule::remove_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + user_alpha, + )); + + // Modify position - fees should be collected and paid to the owner + let owner_tao_before = SubtensorModule::get_coldkey_balance(&owner_coldkey); + let owner_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &owner_coldkey, + netuid, + ); + + // Make small modification + let delta = + ::MinimumLiquidity::get() + as i64 + * (if add { 1 } else { -1 }); + assert_ok!(Swap::modify_position( + RuntimeOrigin::signed(owner_coldkey), + owner_hotkey, + netuid.into(), + position_id.into(), + delta, + )); + + // Check ending owner TAO and alpha + let owner_tao_after_add = SubtensorModule::get_coldkey_balance(&owner_coldkey); + let owner_alpha_after_add = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &owner_coldkey, + netuid, + ); + + assert!(owner_tao_after_add > owner_tao_before); + assert!(owner_alpha_after_add > owner_alpha_before); // always greater because of claimed fees + + // Make small modification again - should not claim more fees + assert_ok!(Swap::modify_position( + RuntimeOrigin::signed(owner_coldkey), + owner_hotkey, + netuid.into(), + position_id.into(), + delta, + )); + + // Check ending owner TAO and alpha + let owner_tao_after_repeat = SubtensorModule::get_coldkey_balance(&owner_coldkey); + let owner_alpha_after_repeat = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &owner_coldkey, + netuid, + ); + + assert!(owner_tao_after_add == owner_tao_after_repeat); + if add { + assert!(owner_alpha_after_add > owner_alpha_after_repeat); + } else { + assert!(owner_alpha_after_add < owner_alpha_after_repeat); + } + }); + }); +} + +fn setup_positions(netuid: NetUid) { + for (coldkey, hotkey, low_price, high_price, liquidity) in [ + (2, 12, 0.1, 0.20, 1_000_000_000_000_u64), + (3, 13, 0.15, 0.25, 200_000_000_000_u64), + (4, 14, 0.25, 0.5, 3_000_000_000_000_u64), + (5, 15, 0.3, 0.6, 300_000_000_000_u64), + (6, 16, 0.4, 0.7, 8_000_000_000_000_u64), + (7, 17, 0.5, 0.8, 600_000_000_000_u64), + (8, 18, 0.6, 0.9, 700_000_000_000_u64), + (9, 19, 0.7, 1.0, 100_000_000_000_u64), + (10, 20, 0.8, 1.1, 300_000_000_000_u64), + ] { + SubtensorModule::create_account_if_non_existent(&U256::from(coldkey), &U256::from(hotkey)); + SubtensorModule::add_balance_to_coldkey_account( + &U256::from(coldkey), + 1_000_000_000_000_000, + ); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &U256::from(hotkey), + &U256::from(coldkey), + netuid.into(), + 1_000_000_000_000_000, + ); + + let tick_low = price_to_tick(low_price); + let tick_high = price_to_tick(high_price); + let add_lq_call = SwapCall::::add_liquidity { + hotkey: U256::from(hotkey), + netuid: netuid.into(), + tick_low, + tick_high, + liquidity, + }; + assert_ok!( + RuntimeCall::Swap(add_lq_call).dispatch(RuntimeOrigin::signed(U256::from(coldkey))) + ); + } +} + +#[test] +fn test_large_swap() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let coldkey = U256::from(100); + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); + pallet_subtensor_swap::EnabledUserLiquidity::::insert(NetUid::from(netuid), true); + + // Force the swap to initialize + SubtensorModule::swap_tao_for_alpha(netuid, 0, 1_000_000_000_000).unwrap(); + + setup_positions(netuid.into()); + + let swap_amount = 100_000_000_000_000; + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + owner_hotkey, + netuid, + swap_amount, + )); + }); +} diff --git a/pallets/subtensor/src/tests/staking2.rs b/pallets/subtensor/src/tests/staking2.rs index 6fbabf83b2..0c98a83bb1 100644 --- a/pallets/subtensor/src/tests/staking2.rs +++ b/pallets/subtensor/src/tests/staking2.rs @@ -1,18 +1,22 @@ -use super::mock::*; -use crate::*; +#![allow(clippy::unwrap_used)] + use frame_support::{ assert_ok, dispatch::{GetDispatchInfo, Pays}, weights::Weight, }; use sp_core::U256; -use substrate_fixed::types::{I96F32, U96F32}; +use subtensor_swap_interface::SwapHandler; + +use super::mock; +use super::mock::*; +use crate::*; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --workspace --test staking2 -- test_swap_tao_for_alpha_dynamic_mechanism --exact --nocapture #[test] fn test_stake_base_case() { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let tao_to_swap = 1_000_000_000; // 1 TAO // Set up the subnet with dynamic mechanism @@ -21,32 +25,32 @@ fn test_stake_base_case() { // Initialize subnet with some existing TAO and Alpha let initial_subnet_tao = 10_000_000_000; // 10 TAO let initial_subnet_alpha = 5_000_000_000; // 5 Alpha - SubnetTAO::::insert(netuid, initial_subnet_tao); - SubnetAlphaIn::::insert(netuid, initial_subnet_alpha); + mock::setup_reserves(netuid, initial_subnet_tao, initial_subnet_alpha); SubnetAlphaOut::::insert(netuid, initial_subnet_alpha); // Record initial total stake let initial_total_stake = TotalStake::::get(); // Perform swap - let alpha_received = SubtensorModule::swap_tao_for_alpha(netuid, tao_to_swap); + let (alpha_expected, fee) = mock::swap_tao_to_alpha(netuid, tao_to_swap); + let alpha_received = SubtensorModule::swap_tao_for_alpha( + netuid, + tao_to_swap, + ::SwapInterface::max_price(), + ) + .unwrap() + .amount_paid_out; // Verify correct alpha calculation using constant product formula - let k: I96F32 = - I96F32::from_num(initial_subnet_alpha) * I96F32::from_num(initial_subnet_tao); - let expected_alpha: I96F32 = I96F32::from_num(initial_subnet_alpha) - - (k / (I96F32::from_num(initial_subnet_tao + tao_to_swap))); - let expected_alpha_u64 = expected_alpha.to_num::(); - assert_eq!( - alpha_received, expected_alpha_u64, + alpha_received, alpha_expected, "Alpha received calculation is incorrect" ); // Check subnet updates assert_eq!( SubnetTAO::::get(netuid), - initial_subnet_tao + tao_to_swap, + initial_subnet_tao + tao_to_swap - fee, "Subnet TAO not updated correctly" ); assert_eq!( @@ -78,7 +82,7 @@ fn test_stake_base_case() { #[test] fn test_share_based_staking() { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let primary_hotkey = U256::from(1); let primary_coldkey = U256::from(2); let stake_amount = 1_000_000_000; // 1 TAO @@ -403,7 +407,7 @@ fn test_share_based_staking_denominator_precision() { .iter() .for_each(|test_case| { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); let stake_amount = test_case.0; @@ -457,7 +461,7 @@ fn test_share_based_staking_stake_unstake_inject() { .iter() .for_each(|test_case| { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); let coldkey2 = U256::from(3); @@ -527,7 +531,7 @@ fn test_share_based_staking_stake_inject_stake_new() { .iter() .for_each(|test_case| { new_test_ext(1).execute_with(|| { - let netuid = 1; + let netuid = NetUid::from(1); let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); let coldkey2 = U256::from(3); @@ -594,7 +598,7 @@ fn test_try_associate_hotkey() { RuntimeCall::SubtensorModule(crate::Call::try_associate_hotkey { hotkey: hotkey1 }); let dispatch_info = call.get_dispatch_info(); // Verify tx weight > 0 - assert!(dispatch_info.weight.all_gte(Weight::from_all(0))); + assert!(dispatch_info.call_weight.all_gte(Weight::from_all(0))); // Verify pays Yes is set assert_eq!(dispatch_info.pays_fee, Pays::Yes); @@ -633,9 +637,9 @@ fn test_stake_fee_api() { let hotkey2 = U256::from(3); let coldkey2 = U256::from(4); - let netuid0 = 1; - let netuid1 = 2; - let root_netuid = SubtensorModule::get_root_netuid(); + let netuid0 = NetUid::from(1); + let netuid1 = NetUid::from(2); + let root_netuid = NetUid::ROOT; let alpha_divs = 100_000_000_000; let total_hotkey_alpha = 100_000_000_000; @@ -668,13 +672,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_0 = SubtensorModule::calculate_staking_fee( - None, - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_0 = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); assert_eq!(stake_fee_0, dynamic_fee_0); // Test stake fee for remove on root @@ -685,13 +684,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_1 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - None, - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_1 = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); assert_eq!(stake_fee_1, dynamic_fee_1); // Test stake fee for move from root to non-root @@ -702,13 +696,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_2 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_2 = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); assert_eq!(stake_fee_2, dynamic_fee_2); // Test stake fee for move between hotkeys on root @@ -719,13 +708,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_3 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey2, root_netuid)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_3 = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); assert_eq!(stake_fee_3, dynamic_fee_3); // Test stake fee for move between coldkeys on root @@ -736,13 +720,8 @@ fn test_stake_fee_api() { coldkey2, stake_amount, ); - let dynamic_fee_4 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey1, root_netuid)), - &coldkey2, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_4 = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); assert_eq!(stake_fee_4, dynamic_fee_4); // Test stake fee for *swap* from non-root to root @@ -753,13 +732,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_5 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, root_netuid)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_5 = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); assert_eq!(stake_fee_5, dynamic_fee_5); // Test stake fee for move between hotkeys on non-root @@ -770,13 +744,8 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_6 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey2, netuid0)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_6 = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); assert_eq!(stake_fee_6, dynamic_fee_6); // Test stake fee for move between coldkeys on non-root @@ -787,13 +756,8 @@ fn test_stake_fee_api() { coldkey2, stake_amount, ); - let dynamic_fee_7 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey2, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_7 = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); assert_eq!(stake_fee_7, dynamic_fee_7); // Test stake fee for *swap* from non-root to non-root @@ -804,28 +768,21 @@ fn test_stake_fee_api() { coldkey1, stake_amount, ); - let dynamic_fee_8 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, netuid1)), - &coldkey1, - U96F32::saturating_from_num(stake_amount), - ); + let dynamic_fee_8 = + ::SwapInterface::approx_fee_amount(netuid1.into(), stake_amount); assert_eq!(stake_fee_8, dynamic_fee_8); }); } +#[ignore = "fees are now calculated by SwapInterface"] #[test] fn test_stake_fee_calculation() { new_test_ext(1).execute_with(|| { let hotkey1 = U256::from(1); - let coldkey1 = U256::from(2); - let hotkey2 = U256::from(3); - let coldkey2 = U256::from(4); - let netuid0 = 1; - let netuid1 = 2; - let root_netuid = SubtensorModule::get_root_netuid(); + let netuid0 = NetUid::from(1); + let netuid1 = NetUid::from(2); + let root_netuid = NetUid::ROOT; // Set SubnetMechanism to 1 (Dynamic) SubnetMechanism::::insert(netuid0, 1); SubnetMechanism::::insert(netuid1, 1); @@ -836,16 +793,14 @@ fn test_stake_fee_calculation() { let reciprocal_price = 2; // 1 / price let stake_amount = 100_000_000_000_u64; - let default_fee = DefaultStakingFee::::get(); + let default_fee = 0; // FIXME: DefaultStakingFee is deprecated // Setup alpha out SubnetAlphaOut::::insert(netuid0, 100_000_000_000); SubnetAlphaOut::::insert(netuid1, 100_000_000_000); // Set pools using price - SubnetAlphaIn::::insert(netuid0, tao_in * reciprocal_price); - SubnetTAO::::insert(netuid0, tao_in); - SubnetAlphaIn::::insert(netuid1, tao_in * reciprocal_price); - SubnetTAO::::insert(netuid1, tao_in); + mock::setup_reserves(netuid0, tao_in, tao_in * reciprocal_price); + mock::setup_reserves(netuid1, tao_in, tao_in * reciprocal_price); // Setup alpha divs for hotkey1 AlphaDividendsPerSubnet::::insert(netuid0, hotkey1, alpha_divs); @@ -856,93 +811,34 @@ fn test_stake_fee_calculation() { TotalHotkeyAlpha::::insert(hotkey1, netuid1, total_hotkey_alpha); // Test stake fee for add_stake - let stake_fee_0 = SubtensorModule::calculate_staking_fee( - None, - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Default for adding stake - assert_eq!(stake_fee_0, default_fee); + + // Default for adding stake + let stake_fee = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); + assert_eq!(stake_fee, default_fee); // Test stake fee for remove on root - let stake_fee_1 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - None, - &coldkey1, - U96F32::from_num(stake_amount), - ); // Default for removing stake from root - assert_eq!(stake_fee_1, default_fee); + let stake_fee = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); // Default for removing stake from root + assert_eq!(stake_fee, default_fee); // Test stake fee for move from root to non-root - let stake_fee_2 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Default for moving stake from root to non-root - assert_eq!(stake_fee_2, default_fee); - // Test stake fee for move between hotkeys on root - let stake_fee_3 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey2, root_netuid)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Default for moving stake between hotkeys on root - assert_eq!(stake_fee_3, default_fee); + // Default for moving stake from root to non-root + let stake_fee = + ::SwapInterface::approx_fee_amount(netuid0.into(), stake_amount); + assert_eq!(stake_fee, default_fee); - // Test stake fee for move between coldkeys on root - let stake_fee_4 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, root_netuid)), - &coldkey1, - Some((&hotkey1, root_netuid)), - &coldkey2, - U96F32::from_num(stake_amount), - ); // Default for moving stake between coldkeys on root - assert_eq!(stake_fee_4, default_fee); - - // Test stake fee for *swap* from non-root to root - let stake_fee_5 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, root_netuid)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Charged a dynamic fee - assert_ne!(stake_fee_5, default_fee); - - // Test stake fee for move between hotkeys on non-root - let stake_fee_6 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey2, netuid0)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Charge the default fee - assert_eq!(stake_fee_6, default_fee); - - // Test stake fee for move between coldkeys on non-root - let stake_fee_7 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, netuid0)), - &coldkey2, - U96F32::from_num(stake_amount), - ); // Charge the default fee; stake did not leave the subnet. - assert_eq!(stake_fee_7, default_fee); + // Test stake fee for move between hotkeys on root + let stake_fee = + ::SwapInterface::approx_fee_amount(root_netuid.into(), stake_amount); // Default for moving stake between hotkeys on root + assert_eq!(stake_fee, default_fee); // Test stake fee for *swap* from non-root to non-root - let stake_fee_8 = SubtensorModule::calculate_staking_fee( - Some((&hotkey1, netuid0)), - &coldkey1, - Some((&hotkey1, netuid1)), - &coldkey1, - U96F32::from_num(stake_amount), - ); // Charged a dynamic fee - assert_ne!(stake_fee_8, default_fee); + + // Charged a dynamic fee + let stake_fee = + ::SwapInterface::approx_fee_amount(netuid1.into(), stake_amount); + assert_ne!(stake_fee, default_fee); }); } diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index ec737f8601..ebac3e786d 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -1,9 +1,11 @@ -use super::mock::*; -use crate::*; use frame_support::{assert_noop, assert_ok}; use frame_system::Config; use sp_core::U256; +use super::mock; +use super::mock::*; +use crate::*; + /*************************** pub fn do_start_call() tests *****************************/ @@ -11,12 +13,13 @@ use sp_core::U256; #[test] fn test_do_start_call_ok() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let coldkey_account_id = U256::from(0); add_network_without_emission_block(netuid, tempo, 0); assert_eq!(FirstEmissionBlockNumber::::get(netuid), None); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000); // account 0 is the default owner for any subnet assert_eq!(SubnetOwner::::get(netuid), coldkey_account_id); @@ -39,7 +42,7 @@ fn test_do_start_call_ok() { #[test] fn test_do_start_call_fail_with_not_existed_subnet() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey_account_id = U256::from(0); assert_noop!( SubtensorModule::start_call( @@ -54,10 +57,17 @@ fn test_do_start_call_fail_with_not_existed_subnet() { #[test] fn test_do_start_call_fail_not_owner() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let coldkey_account_id = U256::from(0); - let wrong_owner_account_id = U256::from(1); + let wrong_owner_account_id = U256::from(2); + let burn_cost = 1000; + //add network + SubtensorModule::set_burn(netuid, burn_cost); + add_network_without_emission_block(netuid, tempo, 0); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000); + // Give it some $$$ in his coldkey balance + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); add_network_without_emission_block(netuid, tempo, 0); @@ -78,9 +88,16 @@ fn test_do_start_call_fail_not_owner() { #[test] fn test_do_start_call_fail_with_cannot_start_call_now() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let coldkey_account_id = U256::from(0); + let burn_cost = 1000; + //add network + SubtensorModule::set_burn(netuid, burn_cost); + add_network_without_emission_block(netuid, tempo, 0); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000); + // Give it some $$$ in his coldkey balance + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); add_network_without_emission_block(netuid, tempo, 0); @@ -99,13 +116,28 @@ fn test_do_start_call_fail_with_cannot_start_call_now() { #[test] fn test_do_start_call_fail_for_set_again() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let coldkey_account_id = U256::from(0); + let hotkey_account_id = U256::from(1); + let burn_cost = 1000; + SubtensorModule::set_burn(netuid, burn_cost); add_network_without_emission_block(netuid, tempo, 0); assert_eq!(FirstEmissionBlockNumber::::get(netuid), None); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000); + + // Give it some $$$ in his coldkey balance + SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + + // Subscribe and check extrinsic output + assert_ok!(SubtensorModule::burned_register( + <::RuntimeOrigin>::signed(coldkey_account_id), + netuid, + hotkey_account_id + )); + assert_eq!(SubnetOwner::::get(netuid), coldkey_account_id); let block_number = System::block_number() + DurationOfStartCall::get(); @@ -129,12 +161,13 @@ fn test_do_start_call_fail_for_set_again() { #[test] fn test_do_start_call_ok_with_same_block_number_after_coinbase() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let coldkey_account_id = U256::from(0); add_network_without_emission_block(netuid, tempo, 0); assert_eq!(FirstEmissionBlockNumber::::get(netuid), None); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000); assert_eq!(SubnetOwner::::get(netuid), coldkey_account_id); @@ -205,6 +238,7 @@ fn test_no_duplicates_in_get_symbol_for_subnet() { let mut seen = HashSet::new(); for netuid in 0u16..=438 { + let netuid = NetUid::from(netuid); let symbol = Pallet::::get_symbol_for_subnet(netuid); assert!( seen.insert(symbol.clone()), @@ -222,7 +256,7 @@ fn test_subtoken_enable() { // ensure_subtoken_enabled new_test_ext(1).execute_with(|| { let account = U256::from(0); - let netuid: u16 = 1; + let netuid = NetUid::from(1); // let to_be_set: u64 = 10 add_network_disable_subtoken(netuid, 10, 0); assert!(!SubtokenEnabled::::get(netuid)); @@ -239,21 +273,34 @@ fn test_subtoken_enable() { }); } -// cargo test --package pallet-subtensor --lib -- tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output +// cargo test --package pallet-subtensor --lib -- +// tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output +#[allow(clippy::unwrap_used)] #[test] fn test_subtoken_enable_reject_trading_before_enable() { // ensure_subtoken_enabled new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let netuid2: u16 = 2; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(2); let hotkey_account_2_id: U256 = U256::from(3); let amount = DefaultMinStake::::get() * 10; + let stake_bal = 10_000_000_000; // 10 Alpha + + let limit_price = 1_000_000_000; // not important + add_network_disable_subtoken(netuid, 10, 0); add_network_disable_subtoken(netuid2, 10, 0); + assert!(!SubtokenEnabled::::get(netuid)); + assert!(!SubtokenEnabled::::get(netuid2)); + + // Set liq high enough to not trigger other errors + SubnetTAO::::set(netuid, 20_000_000_000); + SubnetAlphaIn::::set(netuid, 20_000_000_000); + // Register so staking *could* work register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 0); register_ok_neuron(netuid2, hotkey_account_id, coldkey_account_id, 100); @@ -262,6 +309,14 @@ fn test_subtoken_enable_reject_trading_before_enable() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000); + // Give some stake + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid, + stake_bal, + ); + // all trading extrinsic should be rejected. assert_noop!( SubtensorModule::add_stake( @@ -273,6 +328,62 @@ fn test_subtoken_enable_reject_trading_before_enable() { Error::::SubtokenDisabled ); + assert_noop!( + SubtensorModule::add_stake_limit( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount, + limit_price, + false + ), + Error::::SubtokenDisabled + ); + + // For unstake_all the result is Ok, but the + // operation is not performed. + assert_ok!(SubtensorModule::unstake_all( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id + )); + // Check that the stake is still the same + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid + ), + stake_bal + ); + + // For unstake_all_alpha, the result is AmountTooLow because no re-staking happens. + assert_noop!( + SubtensorModule::unstake_all_alpha( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id + ), + Error::::AmountTooLow + ); + // Check that the stake is still the same + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid + ), + stake_bal + ); + + SubtensorModule::remove_stake_limit( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount, + limit_price, + false, + ) + .unwrap(); + assert_noop!( SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), @@ -344,8 +455,8 @@ fn test_subtoken_enable_reject_trading_before_enable() { #[test] fn test_subtoken_enable_trading_ok_with_enable() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let netuid2: u16 = 2; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(2); let hotkey_account_2_id: U256 = U256::from(3); @@ -356,6 +467,13 @@ fn test_subtoken_enable_trading_ok_with_enable() { add_network(netuid, 10, 0); add_network(netuid2, 10, 0); + + let reserve = stake_amount * 1000; + mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid2, reserve, reserve); + SubnetAlphaOut::::insert(netuid, reserve); + SubnetAlphaOut::::insert(netuid2, reserve); + // Register so staking works register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 0); register_ok_neuron(netuid2, hotkey_account_id, coldkey_account_id, 100); @@ -440,11 +558,6 @@ fn test_subtoken_enable_trading_ok_with_enable() { unstake_amount, )); - assert_ok!(SubtensorModule::unstake_all( - RuntimeOrigin::signed(coldkey_account_id), - hotkey_account_id, - )); - assert_ok!(SubtensorModule::unstake_all_alpha( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -457,8 +570,8 @@ fn test_subtoken_enable_trading_ok_with_enable() { fn test_subtoken_enable_ok_for_burn_register_before_enable() { // ensure_subtoken_enabled new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let netuid2: u16 = 2; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let hotkey_account_id: U256 = U256::from(1); let coldkey_account_id = U256::from(2); let hotkey_account_2_id: U256 = U256::from(3); @@ -486,3 +599,65 @@ fn test_subtoken_enable_ok_for_burn_register_before_enable() { )); }); } + +#[test] +fn test_user_liquidity_access_control() { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(1); + let owner_coldkey = U256::from(2); + let not_owner = U256::from(999); // arbitrary non-owner + + // add network + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Initially should be disabled + assert!(!pallet_subtensor_swap::EnabledUserLiquidity::::get( + NetUid::from(netuid) + )); + + // Not owner, not root: should fail + assert_noop!( + Swap::toggle_user_liquidity(RuntimeOrigin::signed(not_owner), netuid, true), + DispatchError::BadOrigin + ); + + // Subnet owner can enable + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::signed(owner_coldkey), + netuid, + true + )); + assert!(pallet_subtensor_swap::EnabledUserLiquidity::::get( + NetUid::from(netuid) + )); + + // Root can disable + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::root(), + netuid, + false + )); + assert!(!pallet_subtensor_swap::EnabledUserLiquidity::::get( + NetUid::from(netuid) + )); + + // Root can enable again + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::root(), + netuid, + true + )); + assert!(pallet_subtensor_swap::EnabledUserLiquidity::::get( + NetUid::from(netuid) + )); + + // Subnet owner cannot disable (only root can disable) + assert_noop!( + Swap::toggle_user_liquidity(RuntimeOrigin::signed(owner_coldkey), netuid, false), + DispatchError::BadOrigin + ); + assert!(pallet_subtensor_swap::EnabledUserLiquidity::::get( + NetUid::from(netuid) + )); + }); +} diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index 385830904c..c58091a7ec 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -1,20 +1,24 @@ #![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] -use codec::Encode; -use frame_support::weights::Weight; -use frame_support::{assert_err, assert_noop, assert_ok}; -use frame_system::{Config, RawOrigin}; -use super::mock::*; -use crate::*; -use crate::{Call, ColdkeySwapScheduleDuration, Error}; use approx::assert_abs_diff_eq; +use codec::Encode; use frame_support::error::BadOrigin; use frame_support::traits::OnInitialize; use frame_support::traits::schedule::DispatchTime; use frame_support::traits::schedule::v3::Named as ScheduleNamed; +use frame_support::weights::Weight; +use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::{Config, RawOrigin}; use sp_core::{Get, H256, U256}; -use sp_runtime::DispatchError; +use sp_runtime::{DispatchError, traits::TxBaseImplication}; use substrate_fixed::types::U96F32; +use subtensor_runtime_common::SubnetInfo; +use subtensor_swap_interface::{OrderType, SwapHandler}; + +use super::mock; +use super::mock::*; +use crate::*; +use crate::{Call, ColdkeySwapScheduleDuration, Error}; // // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_coldkey -- test_swap_total_hotkey_coldkey_stakes_this_interval --exact --nocapture // #[test] @@ -53,7 +57,7 @@ fn test_swap_subnet_owner() { new_test_ext(1).execute_with(|| { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid = 1u16; + let netuid = NetUid::from(1u16); add_network(netuid, 1, 0); SubnetOwner::::insert(netuid, old_coldkey); @@ -80,12 +84,15 @@ fn test_swap_total_coldkey_stake() { let other_hotkey = U256::from(5); let stake = DefaultMinStake::::get() * 10; - let netuid = 1u16; + let netuid = NetUid::from(1u16); add_network(netuid, 1, 0); SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake * 2 + 1_000); register_ok_neuron(netuid, hotkey, old_coldkey, 1001000); register_ok_neuron(netuid, other_hotkey, other_coldkey, 1001000); + let reserve = stake * 10; + mock::setup_reserves(netuid, reserve, reserve); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), hotkey, @@ -242,8 +249,8 @@ fn test_swap_with_multiple_subnets() { new_test_ext(1).execute_with(|| { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid1 = 1u16; - let netuid2 = 2u16; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); @@ -288,8 +295,11 @@ fn test_swap_idempotency() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); let hotkey = U256::from(3); - let netuid = 1u16; + let netuid = NetUid::from(1u16); let stake = DefaultMinStake::::get() * 10; + let reserve = stake * 10; + + mock::setup_reserves(netuid, reserve, reserve); // Add a network add_network(netuid, 1, 0); @@ -340,11 +350,10 @@ fn test_swap_with_max_values() { let hotkey = U256::from(5); let hotkey2 = U256::from(6); let other_coldkey = U256::from(7); - let netuid = 1u16; - let netuid2 = 2u16; + let netuid = NetUid::from(1); + let netuid2 = NetUid::from(2); let stake = 10_000; let max_stake = 21_000_000_000_000_000; // 21 Million TAO; max possible balance. - let fee = DefaultStakingFee::::get(); // Add a network add_network(netuid, 1, 0); @@ -359,6 +368,10 @@ fn test_swap_with_max_values() { SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, max_stake + 1_000); SubtensorModule::add_balance_to_coldkey_account(&old_coldkey2, max_stake + 1_000); + let reserve = max_stake * 10; + mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid2, reserve, reserve); + // Stake to hotkey on each subnet. assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -366,12 +379,23 @@ fn test_swap_with_max_values() { netuid, max_stake )); + let expected_stake1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &old_coldkey, + netuid, + ); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey2), hotkey2, netuid2, max_stake )); + let expected_stake2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &old_coldkey2, + netuid2, + ); let mut weight = Weight::zero(); assert_ok!(SubtensorModule::perform_swap_coldkey( @@ -389,17 +413,19 @@ fn test_swap_with_max_values() { SubtensorModule::get_total_stake_for_coldkey(&old_coldkey), 0 ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), - max_stake - fee + expected_stake1, + epsilon = expected_stake1 / 1000 ); assert_eq!( SubtensorModule::get_total_stake_for_coldkey(&old_coldkey2), 0 ); - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey2), - max_stake - fee + expected_stake2, + epsilon = expected_stake2 / 1000 ); }); } @@ -412,13 +438,16 @@ fn test_swap_with_non_existent_new_coldkey() { let new_coldkey = U256::from(2); let hotkey = U256::from(3); let stake = DefaultMinStake::::get() * 10; - let netuid = 1u16; - let fee = DefaultStakingFee::::get(); + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey, old_coldkey, 1001000); // Give old coldkey some balance. SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake + 1_000); + + let reserve = stake * 10; + mock::setup_reserves(netuid, reserve, reserve); + // Stake to hotkey. assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -426,6 +455,11 @@ fn test_swap_with_non_existent_new_coldkey() { netuid, stake )); + let expected_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &old_coldkey, + netuid, + ); let mut weight = Weight::zero(); assert_ok!(SubtensorModule::perform_swap_coldkey( @@ -438,9 +472,16 @@ fn test_swap_with_non_existent_new_coldkey() { SubtensorModule::get_total_stake_for_coldkey(&old_coldkey), 0 ); - assert_eq!( - SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), - stake - fee + + let actual_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &new_coldkey, + netuid, + ); + assert_abs_diff_eq!( + actual_stake, + expected_stake, + epsilon = expected_stake / 1000 ); }); } @@ -535,18 +576,12 @@ fn test_swap_concurrent_modifications() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); let hotkey = U256::from(3); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let initial_stake = 1_000_000_000_000; let additional_stake = 500_000_000_000; - let initial_stake_alpha = - U96F32::from(initial_stake).saturating_mul(SubtensorModule::get_alpha_price(netuid)); - let fee = SubtensorModule::calculate_staking_fee( - None, - &new_coldkey, - Some((&hotkey, netuid)), - &new_coldkey, - initial_stake_alpha, - ); + + let reserve = (initial_stake + additional_stake) * 1000; + mock::setup_reserves(netuid, reserve, reserve); // Setup initial state add_network(netuid, 1, 1); @@ -555,6 +590,7 @@ fn test_swap_concurrent_modifications() { initial_stake + additional_stake + 1_000_000, ); register_ok_neuron(netuid, hotkey, new_coldkey, 1001000); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(new_coldkey), hotkey, @@ -563,25 +599,15 @@ fn test_swap_concurrent_modifications() { )); // Verify initial stake - assert_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, - &new_coldkey, - netuid - ), - initial_stake - fee - ); - - // Wait some blocks - step_block(10); - - // Get stake before swap let stake_before_swap = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &new_coldkey, netuid, ); + // Wait some blocks + step_block(10); + // Simulate concurrent stake addition assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(new_coldkey), @@ -590,6 +616,12 @@ fn test_swap_concurrent_modifications() { additional_stake )); + let stake_with_additional = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &new_coldkey, + netuid, + ); + let mut weight = Weight::zero(); assert_ok!(SubtensorModule::perform_swap_coldkey( &old_coldkey, @@ -597,15 +629,15 @@ fn test_swap_concurrent_modifications() { &mut weight )); - assert_abs_diff_eq!( + assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &new_coldkey, netuid ), - stake_before_swap + additional_stake - fee, - epsilon = (stake_before_swap + additional_stake - fee) / 1000 + stake_with_additional ); + assert!(stake_with_additional > stake_before_swap); assert!(!Alpha::::contains_key((hotkey, old_coldkey, netuid))); }); } @@ -616,7 +648,7 @@ fn test_swap_with_invalid_subnet_ownership() { new_test_ext(1).execute_with(|| { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid = 1u16; + let netuid = NetUid::from(1u16); SubnetOwner::::insert(netuid, old_coldkey); @@ -643,12 +675,15 @@ fn test_do_swap_coldkey_success() { let new_coldkey = U256::from(2); let hotkey1 = U256::from(3); let hotkey2 = U256::from(4); - let netuid = 1u16; + let netuid = NetUid::from(1u16); let stake_amount1 = DefaultMinStake::::get() * 10; let stake_amount2 = DefaultMinStake::::get() * 20; let swap_cost = SubtensorModule::get_key_swap_cost(); let free_balance_old = 12345u64 + swap_cost; + let reserve = (stake_amount1 + stake_amount2) * 10; + mock::setup_reserves(netuid, reserve, reserve); + // Setup initial state add_network(netuid, 13, 0); register_ok_neuron(netuid, hotkey1, old_coldkey, 0); @@ -822,13 +857,11 @@ fn test_swap_stake_for_coldkey() { let stake_amount1 = DefaultMinStake::::get() * 10; let stake_amount2 = DefaultMinStake::::get() * 20; let stake_amount3 = DefaultMinStake::::get() * 30; - let total_stake = stake_amount1 + stake_amount2; let mut weight = Weight::zero(); - let fee = DefaultStakingFee::::get(); // Setup initial state // Add a network - let netuid = 1u16; + let netuid = NetUid::from(1u16); add_network(netuid, 1, 0); // Register hotkeys @@ -840,6 +873,9 @@ fn test_swap_stake_for_coldkey() { stake_amount1 + stake_amount2 + 1_000_000, ); + let reserve = (stake_amount1 + stake_amount2 + stake_amount3) * 10; + mock::setup_reserves(netuid, reserve, reserve); + // Stake to hotkeys assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -847,29 +883,22 @@ fn test_swap_stake_for_coldkey() { netuid, stake_amount1 )); + let expected_stake_alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &old_coldkey, + netuid, + ); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), hotkey2, netuid, stake_amount2 )); - - // Verify stakes - assert_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey1, - &old_coldkey, - netuid - ), - stake_amount1 - fee - ); - assert_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey2, - &old_coldkey, - netuid - ), - stake_amount2 - fee + let expected_stake_alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &old_coldkey, + netuid, ); // Insert existing for same hotkey1 @@ -882,6 +911,11 @@ fn test_swap_stake_for_coldkey() { netuid, stake_amount3 )); + let expected_stake_alpha3 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &new_coldkey, + netuid, + ); // Record initial values let initial_total_issuance = SubtensorModule::get_total_issuance(); @@ -897,9 +931,10 @@ fn test_swap_stake_for_coldkey() { SubtensorModule::perform_swap_coldkey(&old_coldkey, &new_coldkey, &mut weight); // Verify stake is additive, not replaced - assert_eq!( + assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), - initial_total_stake_for_old_coldkey + initial_total_stake_for_new_coldkey + initial_total_stake_for_old_coldkey + initial_total_stake_for_new_coldkey, + epsilon = 2 ); // Verify ownership transfer @@ -916,7 +951,7 @@ fn test_swap_stake_for_coldkey() { &new_coldkey, netuid ), - stake_amount1 + stake_amount3 - fee * 2 + expected_stake_alpha1 + expected_stake_alpha3 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -924,7 +959,7 @@ fn test_swap_stake_for_coldkey() { &new_coldkey, netuid ), - stake_amount2 - fee + expected_stake_alpha2 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -978,23 +1013,23 @@ fn test_swap_staking_hotkeys_for_coldkey() { let hotkey2 = U256::from(5); let stake_amount1 = DefaultMinStake::::get() * 10; let stake_amount2 = DefaultMinStake::::get() * 20; - let total_stake = stake_amount1 + stake_amount2; let mut weight = Weight::zero(); - let fee = DefaultStakingFee::::get(); // Setup initial state // Add a network - let netuid = 1u16; + let netuid = NetUid::from(1u16); add_network(netuid, 1, 0); // Give some balance to old coldkey SubtensorModule::add_balance_to_coldkey_account( &old_coldkey, stake_amount1 + stake_amount2 + 1_000_000, - ); - // Register hotkeys + ); // Register hotkeys register_ok_neuron(netuid, hotkey1, old_coldkey, 0); register_ok_neuron(netuid, hotkey2, other_coldkey, 0); + let reserve = (stake_amount1 + stake_amount2) * 10; + mock::setup_reserves(netuid, reserve, reserve); + // Stake to hotkeys assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -1002,29 +1037,22 @@ fn test_swap_staking_hotkeys_for_coldkey() { netuid, stake_amount1 )); + let expected_stake_alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &old_coldkey, + netuid, + ); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), hotkey2, netuid, stake_amount2 )); - - // Verify stakes - assert_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey1, - &old_coldkey, - netuid - ), - stake_amount1 - fee - ); - assert_eq!( - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey2, - &old_coldkey, - netuid - ), - stake_amount2 - fee + let expected_stake_alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &old_coldkey, + netuid, ); // Perform the swap @@ -1051,14 +1079,16 @@ fn test_swap_delegated_stake_for_coldkey() { let stake_amount1 = DefaultMinStake::::get() * 10; let stake_amount2 = DefaultMinStake::::get() * 20; let mut weight = Weight::zero(); - let netuid = 1u16; - let fee = DefaultStakingFee::::get(); + let netuid = NetUid::from(1); // Setup initial state add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey1, other_coldkey, 0); register_ok_neuron(netuid, hotkey2, other_coldkey, 0); + let reserve = (stake_amount1 + stake_amount2) * 10; + mock::setup_reserves(netuid, reserve, reserve); + // Notice hotkey1 and hotkey2 are Owned by other_coldkey // old_coldkey and new_coldkey therefore delegates stake to them // === Give old_coldkey some balance === @@ -1066,6 +1096,7 @@ fn test_swap_delegated_stake_for_coldkey() { &old_coldkey, stake_amount1 + stake_amount2 + 1_000_000, ); + // === Stake to hotkeys === assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -1073,12 +1104,25 @@ fn test_swap_delegated_stake_for_coldkey() { netuid, stake_amount1 )); + let expected_stake_alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey1, + &old_coldkey, + netuid, + ); + + let (expected_stake_alpha2, fee) = mock::swap_tao_to_alpha(netuid, stake_amount2); assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), hotkey2, netuid, stake_amount2 )); + let expected_stake_alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey2, + &old_coldkey, + netuid, + ); + let fee = (expected_stake_alpha2 as f64 * 0.003) as u64; // Record initial values let initial_total_issuance = SubtensorModule::get_total_issuance(); @@ -1107,7 +1151,7 @@ fn test_swap_delegated_stake_for_coldkey() { &new_coldkey, netuid ), - stake_amount1 - fee + expected_stake_alpha1 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1115,7 +1159,7 @@ fn test_swap_delegated_stake_for_coldkey() { &new_coldkey, netuid ), - stake_amount2 - fee + expected_stake_alpha2 ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1174,8 +1218,8 @@ fn test_swap_subnet_owner_for_coldkey() { new_test_ext(1).execute_with(|| { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid1 = 1u16; - let netuid2 = 2u16; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let mut weight = Weight::zero(); // Initialize SubnetOwner for old_coldkey @@ -1203,7 +1247,7 @@ fn test_do_swap_coldkey_with_subnet_ownership() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); let hotkey = U256::from(3); - let netuid = 1u16; + let netuid = NetUid::from(1u16); let stake_amount: u64 = 1000u64; let swap_cost = SubtensorModule::get_key_swap_cost(); @@ -1237,7 +1281,7 @@ fn test_coldkey_has_associated_hotkeys() { new_test_ext(1).execute_with(|| { let coldkey = U256::from(1); let hotkey = U256::from(2); - let netuid = 1u16; + let netuid = NetUid::from(1u16); // Setup initial state add_network(netuid, 13, 0); @@ -1260,9 +1304,9 @@ fn test_coldkey_swap_total() { let hotkey1 = U256::from(2); let hotkey2 = U256::from(3); let hotkey3 = U256::from(4); - let netuid1 = 1u16; - let netuid2 = 2u16; - let netuid3 = 3u16; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); + let netuid3 = NetUid::from(3); let stake = DefaultMinStake::::get() * 10; SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake * 6); SubtensorModule::add_balance_to_coldkey_account(&delegate1, stake * 2); @@ -1272,6 +1316,11 @@ fn test_coldkey_swap_total() { SubtensorModule::add_balance_to_coldkey_account(&nominator2, stake * 2); SubtensorModule::add_balance_to_coldkey_account(&nominator3, stake * 2); + let reserve = stake * 10; + mock::setup_reserves(netuid1, reserve, reserve); + mock::setup_reserves(netuid2, reserve, reserve); + mock::setup_reserves(netuid3, reserve, reserve); + // Setup initial state add_network(netuid1, 13, 0); add_network(netuid2, 14, 0); @@ -1610,10 +1659,13 @@ fn test_coldkey_delegations() { let owner = U256::from(1); let coldkey = U256::from(4); let delegate = U256::from(2); - let netuid = 0u16; // Stake to 0 - let netuid2 = 1u16; // Stake to 1 + let netuid = NetUid::from(0); // Stake to 0 + let netuid2 = NetUid::from(1); // Stake to 1 let stake = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + let reserve = stake * 1000; + + mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid2, reserve, reserve); add_network(netuid, 13, 0); // root add_network(netuid2, 13, 0); @@ -1625,6 +1677,11 @@ fn test_coldkey_delegations() { register_ok_neuron(netuid2, delegate, owner, 0); SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake * 10); + // since the reserves are equal and we stake the same amount to both networks, we can reuse + // this values for different networks. but you should take it into account in case of tests + // changes + let (expected_stake, fee) = mock::swap_tao_to_alpha(netuid, stake); + assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(coldkey), delegate, @@ -1649,28 +1706,27 @@ fn test_coldkey_delegations() { )); // Verify stake was moved for the delegate + let approx_total_stake = stake * 2 - fee * 2; assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&delegate), - stake * 2 - fee * 2, - epsilon = stake / 1000 + approx_total_stake, + epsilon = approx_total_stake / 100 ); assert_eq!(SubtensorModule::get_total_stake_for_coldkey(&coldkey), 0); assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), - stake * 2 - fee * 2, - epsilon = stake / 1000 + approx_total_stake, + epsilon = approx_total_stake / 100 ); - assert_abs_diff_eq!( + assert_eq!( Alpha::::get((delegate, new_coldkey, netuid)).to_num::(), - stake - fee, - epsilon = stake / 1000 + expected_stake ); assert_eq!(Alpha::::get((delegate, coldkey, netuid)), 0); - assert_abs_diff_eq!( + assert_eq!( Alpha::::get((delegate, new_coldkey, netuid2)).to_num::(), - stake - fee, - epsilon = stake / 1000 + expected_stake, ); assert_eq!(Alpha::::get((delegate, coldkey, netuid2)), 0); }); @@ -1750,8 +1806,11 @@ fn test_schedule_swap_coldkey_execution() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); let hotkey = U256::from(3); - let netuid = 1u16; + let netuid = NetUid::from(1u16); let stake_amount = DefaultMinStake::::get() * 10; + let reserve = stake_amount * 10; + + mock::setup_reserves(netuid, reserve, reserve); add_network(netuid, 13, 0); register_ok_neuron(netuid, hotkey, old_coldkey, 0); @@ -1799,7 +1858,7 @@ fn test_schedule_swap_coldkey_execution() { run_to_block(execution_block); // Run on_initialize for the execution block - SubtensorModule::on_initialize(execution_block); + >::on_initialize(execution_block); // Also run Scheduler's on_initialize as OnInitialize>::on_initialize( @@ -1954,7 +2013,7 @@ fn test_coldkey_swap_delegate_identity_updated() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid = 1; + let netuid = NetUid::from(1); let burn_cost = 10; let tempo = 1; @@ -1962,6 +2021,7 @@ fn test_coldkey_swap_delegate_identity_updated() { add_network(netuid, tempo, 0); SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 100_000_000_000); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2006,7 +2066,7 @@ fn test_coldkey_swap_no_identity_no_changes() { let old_coldkey = U256::from(1); let new_coldkey = U256::from(2); - let netuid = 1; + let netuid = NetUid::from(1); let burn_cost = 10; let tempo = 1; @@ -2014,6 +2074,7 @@ fn test_coldkey_swap_no_identity_no_changes() { add_network(netuid, tempo, 0); SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 100_000_000_000); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2043,13 +2104,14 @@ fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() { let old_coldkey = U256::from(3); let new_coldkey = U256::from(4); - let netuid = 1; + let netuid = NetUid::from(1); let burn_cost = 10; let tempo = 1; SubtensorModule::set_burn(netuid, burn_cost); add_network(netuid, tempo, 0); SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 100_000_000_000); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2113,13 +2175,17 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { // while a coldkey swap is scheduled. new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let coldkey = U256::from(0); let new_coldkey = U256::from(1); let hotkey: U256 = U256::from(2); // Add the hotkey field assert_ne!(hotkey, coldkey); // Ensure hotkey is NOT the same as coldkey !!! - let fee = DefaultStakingFee::::get(); + + let stake = 100_000_000_000; + let reserve = stake * 100; + + mock::setup_reserves(netuid, reserve, reserve); let who = coldkey; // The coldkey signs this transaction @@ -2154,7 +2220,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { <::RuntimeOrigin>::signed(who), hotkey, netuid, - 100_000_000_000 + stake )); // Schedule the coldkey for a swap @@ -2168,7 +2234,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { // Setup the extension let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Try each call @@ -2176,35 +2242,46 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { let call = RuntimeCall::SubtensorModule(SubtensorCall::add_stake { hotkey, netuid, - amount_staked: 100_000_000_000, + amount_staked: stake, }); - let result: Result = - extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Add stake limit let call = RuntimeCall::SubtensorModule(SubtensorCall::add_stake_limit { hotkey, netuid, - amount_staked: 100_000_000_000, - limit_price: 100_000_000_000, + amount_staked: stake, + limit_price: stake, allow_partial: false, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Swap stake @@ -2212,16 +2289,22 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: 100_000_000_000, + alpha_amount: stake, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Swap stake limit @@ -2229,18 +2312,24 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: 100_000_000_000, - limit_price: 100_000_000_000, + alpha_amount: stake, + limit_price: stake, allow_partial: false, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Move stake @@ -2249,16 +2338,22 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { destination_hotkey: hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: 100_000_000_000, + alpha_amount: stake, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Transfer stake @@ -2267,16 +2362,22 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: 100_000_000_000, + alpha_amount: stake, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Transfer all @@ -2284,14 +2385,20 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { dest: new_coldkey, keep_alive: false, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Transfer keep alive @@ -2299,14 +2406,20 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { dest: new_coldkey, value: 100_000_000_000, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Transfer allow death @@ -2314,26 +2427,38 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { dest: new_coldkey, value: 100_000_000_000, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Burned register let call = RuntimeCall::SubtensorModule(SubtensorCall::burned_register { netuid, hotkey }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); // Remove stake @@ -2342,7 +2467,15 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { netuid, amount_unstaked: 1_000_000, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should pass, not in list. assert_ok!(result); @@ -2354,7 +2487,15 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { limit_price: 123456789, // should be low enough allow_partial: true, }); - let result = extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should pass, not in list. assert_ok!(result); }); @@ -2368,13 +2509,16 @@ fn test_coldkey_in_swap_schedule_prevents_critical_calls() { // while a coldkey swap is scheduled. new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let coldkey = U256::from(0); let new_coldkey = U256::from(1); let hotkey: U256 = U256::from(2); // Add the hotkey field assert_ne!(hotkey, coldkey); // Ensure hotkey is NOT the same as coldkey !!! - let fee = DefaultStakingFee::::get(); + let stake = 100_000_000_000; + let reserve = stake * 10; + + mock::setup_reserves(netuid, reserve, reserve); let who = coldkey; // The coldkey signs this transaction @@ -2396,7 +2540,7 @@ fn test_coldkey_in_swap_schedule_prevents_critical_calls() { <::RuntimeOrigin>::signed(who), hotkey, netuid, - 100_000_000_000 + stake )); // Schedule the coldkey for a swap @@ -2410,22 +2554,27 @@ fn test_coldkey_in_swap_schedule_prevents_critical_calls() { // Setup the extension let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Try each call // Dissolve network let call = RuntimeCall::SubtensorModule(SubtensorCall::dissolve_network { netuid, coldkey }); - let result: Result = - extension.validate(&who, &call.clone(), &info, 10); + let result = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::ColdkeyInSwapSchedule.into() - )) + result.unwrap_err(), + CustomTransactionError::ColdkeyInSwapSchedule.into() ); }); } diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index a82972c2f7..05e095292a 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -5,12 +5,14 @@ use codec::Encode; use frame_support::weights::Weight; use frame_support::{assert_err, assert_noop, assert_ok}; use frame_system::{Config, RawOrigin}; - -use super::mock::*; -use crate::*; use sp_core::{Get, H256, U256}; use sp_runtime::SaturatedConversion; use substrate_fixed::types::U64F64; +use subtensor_swap_interface::SwapHandler; + +use super::mock; +use super::mock::*; +use crate::*; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner --exact --nocapture #[test] @@ -22,7 +24,7 @@ fn test_swap_owner() { let mut weight = Weight::zero(); Owner::::insert(old_hotkey, coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -44,7 +46,7 @@ fn test_swap_owned_hotkeys() { let mut weight = Weight::zero(); OwnedHotkeys::::insert(coldkey, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -66,15 +68,18 @@ fn test_swap_total_hotkey_stake() { let coldkey = U256::from(3); let amount = DefaultMinStake::::get() * 10; let mut weight = Weight::zero(); - let fee = DefaultStakingFee::::get(); //add network - let netuid: u16 = add_dynamic_network(&old_hotkey, &coldkey); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + + mock::setup_reserves(netuid, amount * 100, amount * 100); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey, amount); // Add stake + let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, amount); + assert!(expected_alpha > 0); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey), old_hotkey, @@ -83,10 +88,9 @@ fn test_swap_total_hotkey_stake() { )); // Check if stake has increased - assert_abs_diff_eq!( - SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), - amount - fee, - epsilon = amount / 1000, + assert_eq!( + TotalHotkeyAlpha::::get(old_hotkey, netuid), + expected_alpha ); assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), @@ -95,7 +99,7 @@ fn test_swap_total_hotkey_stake() { ); // Swap hotkey - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -108,10 +112,9 @@ fn test_swap_total_hotkey_stake() { 0, epsilon = 1, ); - assert_abs_diff_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), - amount - fee, - epsilon = amount / 1000, + assert_eq!( + TotalHotkeyAlpha::::get(new_hotkey, netuid), + expected_alpha ); }); } @@ -125,9 +128,12 @@ fn test_swap_senate_members() { let coldkey = U256::from(3); let mut weight = Weight::zero(); - // Assuming there's a way to add a member to the senate - // SenateMembers::add_member(&old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SenateMembers::add_member(RuntimeOrigin::root(), old_hotkey)); + let members = SenateMembers::members(); + assert!(members.contains(&old_hotkey)); + assert!(!members.contains(&new_hotkey)); + + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -135,8 +141,9 @@ fn test_swap_senate_members() { )); // Assert that the old_hotkey is no longer a member and new_hotkey is now a member - // assert!(!SenateMembers::is_member(&old_hotkey)); - // assert!(SenateMembers::is_member(&new_hotkey)); + let members = SenateMembers::members(); + assert!(!members.contains(&old_hotkey)); + assert!(members.contains(&new_hotkey)); }); } @@ -150,7 +157,7 @@ fn test_swap_delegates() { let mut weight = Weight::zero(); Delegates::::insert(old_hotkey, 100); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -169,12 +176,12 @@ fn test_swap_subnet_membership() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let mut weight = Weight::zero(); add_network(netuid, 1, 1); IsNetworkMember::::insert(old_hotkey, netuid, true); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -193,7 +200,7 @@ fn test_swap_uids_and_keys() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let uid = 5u16; let mut weight = Weight::zero(); @@ -202,7 +209,7 @@ fn test_swap_uids_and_keys() { Uids::::insert(netuid, old_hotkey, uid); Keys::::insert(netuid, uid, old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -222,7 +229,7 @@ fn test_swap_prometheus() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let prometheus_info = PrometheusInfo::default(); let mut weight = Weight::zero(); @@ -230,7 +237,7 @@ fn test_swap_prometheus() { IsNetworkMember::::insert(old_hotkey, netuid, true); Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -252,7 +259,7 @@ fn test_swap_axons() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let axon_info = AxonInfo::default(); let mut weight = Weight::zero(); @@ -260,7 +267,7 @@ fn test_swap_axons() { IsNetworkMember::::insert(old_hotkey, netuid, true); Axons::::insert(netuid, old_hotkey, axon_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -279,7 +286,7 @@ fn test_swap_certificates() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let certificate = NeuronCertificate::try_from(vec![1, 2, 3]).unwrap(); let mut weight = Weight::zero(); @@ -287,7 +294,7 @@ fn test_swap_certificates() { IsNetworkMember::::insert(old_hotkey, netuid, true); NeuronCertificates::::insert(netuid, old_hotkey, certificate.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -311,7 +318,7 @@ fn test_swap_weight_commits() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let mut weight_commits: VecDeque<(H256, u64, u64, u64)> = VecDeque::new(); weight_commits.push_back((H256::from_low_u64_be(100), 200, 1, 1)); let mut weight = Weight::zero(); @@ -320,7 +327,7 @@ fn test_swap_weight_commits() { IsNetworkMember::::insert(old_hotkey, netuid, true); WeightCommits::::insert(netuid, old_hotkey, weight_commits.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -342,7 +349,7 @@ fn test_swap_loaded_emission() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let server_emission = 1000u64; let validator_emission = 1000u64; let mut weight = Weight::zero(); @@ -354,7 +361,7 @@ fn test_swap_loaded_emission() { vec![(old_hotkey, server_emission, validator_emission)], ); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -376,13 +383,18 @@ fn test_swap_staking_hotkeys() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); + + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let mut weight = Weight::zero(); - let netuid = 1; + let netuid = NetUid::from(1); StakingHotkeys::::insert(coldkey, vec![old_hotkey]); Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(100)); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -437,7 +449,7 @@ fn test_swap_hotkey_with_multiple_coldkeys() { let stake1_before = SubtensorModule::get_total_stake_for_coldkey(&coldkey1); let stake2_before = SubtensorModule::get_total_stake_for_coldkey(&coldkey2); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey1, @@ -464,8 +476,8 @@ fn test_swap_hotkey_with_multiple_subnets() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid1 = 0; - let netuid2 = 1; + let netuid1 = NetUid::from(0); + let netuid2 = NetUid::from(1); let mut weight = Weight::zero(); add_network(netuid1, 1, 1); @@ -473,7 +485,7 @@ fn test_swap_hotkey_with_multiple_subnets() { IsNetworkMember::::insert(old_hotkey, netuid1, true); IsNetworkMember::::insert(old_hotkey, netuid2, true); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -506,6 +518,8 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { // Set up initial state StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(coldkey2, vec![old_hotkey, staker5]); + Alpha::::insert((old_hotkey, coldkey1, netuid), U64F64::from_num(100)); + Alpha::::insert((old_hotkey, coldkey2, netuid), U64F64::from_num(100)); SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); SubtensorModule::add_balance_to_coldkey_account( @@ -529,7 +543,7 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { stake )); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey1, @@ -564,7 +578,7 @@ fn test_swap_hotkey_with_no_stake() { // Set up initial state with no stake Owner::::insert(old_hotkey, coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey, @@ -589,8 +603,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { let new_hotkey = U256::from(2); let coldkey1 = U256::from(3); let coldkey2 = U256::from(4); - let netuid1 = 1; - let netuid2 = 2; + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); let stake = DefaultMinStake::::get() * 10; let mut weight = Weight::zero(); @@ -600,6 +614,9 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { register_ok_neuron(netuid1, old_hotkey, coldkey1, 1234); register_ok_neuron(netuid2, old_hotkey, coldkey1, 1234); + mock::setup_reserves(netuid1, stake * 100, stake * 100); + mock::setup_reserves(netuid2, stake * 100, stake * 100); + // Add balance to both coldkeys SubtensorModule::add_balance_to_coldkey_account(&coldkey1, stake + 1_000); SubtensorModule::add_balance_to_coldkey_account(&coldkey2, stake + 1_000); @@ -635,7 +652,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { let total_hk_stake = SubtensorModule::get_total_stake_for_hotkey(&old_hotkey); assert!(total_hk_stake > 0); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &old_hotkey, &new_hotkey, &coldkey1, @@ -714,7 +731,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { #[test] fn test_swap_hotkey_tx_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let old_hotkey = U256::from(1); let new_hotkey_1 = U256::from(2); @@ -742,7 +759,8 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { assert_ok!(SubtensorModule::do_swap_hotkey( <::RuntimeOrigin>::signed(coldkey), &old_hotkey, - &new_hotkey_1 + &new_hotkey_1, + None )); // Attempt to perform another swap immediately, which should fail due to rate limit @@ -750,7 +768,8 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { SubtensorModule::do_swap_hotkey( <::RuntimeOrigin>::signed(coldkey), &new_hotkey_1, - &new_hotkey_2 + &new_hotkey_2, + None ), Error::::HotKeySetTxRateLimitExceeded ); @@ -760,7 +779,8 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { assert_ok!(SubtensorModule::do_swap_hotkey( <::RuntimeOrigin>::signed(coldkey), &new_hotkey_1, - &new_hotkey_2 + &new_hotkey_2, + None )); }); } @@ -769,7 +789,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { #[test] fn test_do_swap_hotkey_err_not_owner() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); @@ -787,34 +807,14 @@ fn test_do_swap_hotkey_err_not_owner() { SubtensorModule::do_swap_hotkey( <::RuntimeOrigin>::signed(not_owner_coldkey), &old_hotkey, - &new_hotkey + &new_hotkey, + None ), Error::::NonAssociatedColdKey ); }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_success --exact --nocapture -#[test] -fn test_swap_owner_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey - Owner::::insert(old_hotkey, coldkey); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_old_hotkey_not_exist --exact --nocapture #[test] fn test_swap_owner_old_hotkey_not_exist() { @@ -828,7 +828,12 @@ fn test_swap_owner_old_hotkey_not_exist() { assert!(!Owner::::contains_key(old_hotkey)); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -851,7 +856,12 @@ fn test_swap_owner_new_hotkey_already_exists() { Owner::::insert(new_hotkey, another_coldkey); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -859,28 +869,6 @@ fn test_swap_owner_new_hotkey_already_exists() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::swap_hotkey::test_swap_delegates_success --exact --show-output -#[test] -fn test_swap_delegates_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let delegate_take = 10u16; - let mut weight = Weight::zero(); - - // Initialize Delegates for old_hotkey - Delegates::::insert(old_hotkey, delegate_take); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Delegates::::get(new_hotkey), delegate_take); - assert!(!Delegates::::contains_key(old_hotkey)); - }); -} - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_success --exact --nocapture #[test] fn test_swap_stake_success() { @@ -904,7 +892,12 @@ fn test_swap_stake_success() { TaoDividendsPerSubnet::::insert(netuid, old_hotkey, amount); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify the swap assert_eq!(TotalHotkeyAlpha::::get(old_hotkey, netuid), 0); @@ -953,9 +946,13 @@ fn test_swap_stake_old_hotkey_not_exist() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let alpha_share = U64F64::from_num(1234); let mut weight = Weight::zero(); - let netuid = 1; + let netuid = NetUid::from(1); // Initialize Stake for old_hotkey Alpha::::insert((old_hotkey, coldkey, netuid), alpha_share); @@ -964,7 +961,12 @@ fn test_swap_stake_old_hotkey_not_exist() { assert!(Alpha::::contains_key((old_hotkey, coldkey, netuid))); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify that new_hotkey has the stake and old_hotkey does not assert!(Alpha::::contains_key((new_hotkey, coldkey, netuid))); @@ -986,7 +988,7 @@ fn test_swap_stake_old_hotkey_not_exist() { // TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // // Perform the swap -// SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); +// SubtensorModule::perform_hotkey_swap_on_all_subnets(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // // Verify the swap // assert_eq!( @@ -1015,11 +1017,12 @@ fn test_swap_hotkey_error_cases() { // Test not enough balance let swap_cost = SubtensorModule::get_key_swap_cost(); - assert_noop!( + assert_err!( SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &new_hotkey + &new_hotkey, + None ), Error::::NotEnoughBalanceToPaySwapHotKey ); @@ -1032,29 +1035,32 @@ fn test_swap_hotkey_error_cases() { SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &old_hotkey + &old_hotkey, + None ), Error::::NewHotKeyIsSameWithOld ); // Test new hotkey already registered - IsNetworkMember::::insert(new_hotkey, 0, true); + IsNetworkMember::::insert(new_hotkey, NetUid::ROOT, true); assert_noop!( SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &new_hotkey + &new_hotkey, + None ), Error::::HotKeyAlreadyRegisteredInSubNet ); - IsNetworkMember::::remove(new_hotkey, 0); + IsNetworkMember::::remove(new_hotkey, NetUid::ROOT); // Test non-associated coldkey assert_noop!( SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(wrong_coldkey), &old_hotkey, - &new_hotkey + &new_hotkey, + None ), Error::::NonAssociatedColdKey ); @@ -1063,7 +1069,8 @@ fn test_swap_hotkey_error_cases() { assert_ok!(SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &new_hotkey + &new_hotkey, + None )); // Check balance after swap @@ -1078,7 +1085,7 @@ fn test_swap_child_keys() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let children = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; let mut weight = Weight::zero(); @@ -1087,7 +1094,12 @@ fn test_swap_child_keys() { ChildKeys::::insert(old_hotkey, netuid, children.clone()); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify the swap assert_eq!(ChildKeys::::get(new_hotkey, netuid), children); @@ -1102,7 +1114,7 @@ fn test_swap_parent_keys() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let parents = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; let mut weight = Weight::zero(); @@ -1115,7 +1127,12 @@ fn test_swap_parent_keys() { ChildKeys::::insert(U256::from(5), netuid, vec![(200u64, old_hotkey)]); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify ParentKeys swap assert_eq!(ParentKeys::::get(new_hotkey, netuid), parents); @@ -1140,8 +1157,8 @@ fn test_swap_multiple_subnets() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid1 = 0u16; - let netuid2 = 1u16; + let netuid1 = NetUid::from(0); + let netuid2 = NetUid::from(1); let children1 = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; let children2 = vec![(300u64, U256::from(6))]; let mut weight = Weight::zero(); @@ -1154,7 +1171,12 @@ fn test_swap_multiple_subnets() { ChildKeys::::insert(old_hotkey, netuid2, children2.clone()); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify the swap for both subnets assert_eq!(ChildKeys::::get(new_hotkey, netuid1), children1); @@ -1171,7 +1193,7 @@ fn test_swap_complex_parent_child_structure() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let netuid = 0u16; + let netuid = NetUid::from(0u16); let parent1 = U256::from(4); let parent2 = U256::from(5); let child1 = U256::from(6); @@ -1199,7 +1221,12 @@ fn test_swap_complex_parent_child_structure() { ); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Verify ParentKeys swap assert_eq!( @@ -1230,7 +1257,7 @@ fn test_swap_complex_parent_child_structure() { #[test] fn test_swap_parent_hotkey_childkey_maps() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let parent_old = U256::from(1); let coldkey = U256::from(2); let child = U256::from(3); @@ -1259,7 +1286,7 @@ fn test_swap_parent_hotkey_childkey_maps() { // Swap let mut weight = Weight::zero(); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &parent_old, &parent_new, &coldkey, @@ -1285,7 +1312,7 @@ fn test_swap_parent_hotkey_childkey_maps() { #[test] fn test_swap_child_hotkey_childkey_maps() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let parent = U256::from(1); let coldkey = U256::from(2); let child_old = U256::from(3); @@ -1314,7 +1341,7 @@ fn test_swap_child_hotkey_childkey_maps() { // Swap let mut weight = Weight::zero(); - assert_ok!(SubtensorModule::perform_hotkey_swap( + assert_ok!(SubtensorModule::perform_hotkey_swap_on_all_subnets( &child_old, &child_new, &coldkey, @@ -1352,7 +1379,12 @@ fn test_swap_hotkey_is_sn_owner_hotkey() { assert_eq!(SubnetOwnerHotkey::::get(netuid), old_hotkey); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); // Check for SubnetOwnerHotkey assert_eq!(SubnetOwnerHotkey::::get(netuid), new_hotkey); @@ -1366,7 +1398,8 @@ fn test_swap_hotkey_swap_rate_limits() { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); let coldkey = U256::from(3); - let mut weight = Weight::zero(); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); let last_tx_block = 123; let delegate_take_block = 4567; @@ -1380,7 +1413,12 @@ fn test_swap_hotkey_swap_rate_limits() { LastTxBlockChildKeyTake::::insert(old_hotkey, child_key_take_block); // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + None + )); // Check for new hotkey assert_eq!(LastTxBlock::::get(new_hotkey), last_tx_block); diff --git a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs new file mode 100644 index 0000000000..5654498011 --- /dev/null +++ b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs @@ -0,0 +1,1558 @@ +#![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] + +use approx::assert_abs_diff_eq; +use codec::Encode; +use frame_support::weights::Weight; +use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::{Config, RawOrigin}; + +use super::mock::*; +use crate::*; +use sp_core::{Get, H256, U256}; +use sp_runtime::SaturatedConversion; +use substrate_fixed::types::U64F64; +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owner --exact --nocapture +#[test] +fn test_swap_owner() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + Owner::::insert(old_hotkey, coldkey); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert_eq!(Owner::::get(old_hotkey), coldkey); + assert_eq!(Owner::::get(new_hotkey), coldkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owned_hotkeys --exact --nocapture +#[test] +fn test_swap_owned_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + OwnedHotkeys::::insert(coldkey, vec![old_hotkey]); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + let hotkeys = OwnedHotkeys::::get(coldkey); + assert!(hotkeys.contains(&old_hotkey)); + assert!(hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_total_hotkey_stake --exact --nocapture +#[test] +fn test_swap_total_hotkey_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let amount = DefaultMinStake::::get() * 10; + + let fee = (amount as f64 * 0.003) as u64; + + //add network + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + + // Give it some $$$ in his coldkey balance + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Add stake + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + old_hotkey, + netuid, + amount + )); + + // Check if stake has increased + assert_abs_diff_eq!( + SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), + amount - fee, + epsilon = amount / 1000, + ); + assert_abs_diff_eq!( + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), + 0, + epsilon = 1, + ); + + // Swap hotkey + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + // Verify that total hotkey stake swapped + assert_abs_diff_eq!( + SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), + 0, + epsilon = 1, + ); + assert_abs_diff_eq!( + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), + amount - fee, + epsilon = amount / 1000, + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_senate_members --exact --nocapture +#[test] +fn test_swap_senate_members() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + assert_ok!(SenateMembers::add_member(RuntimeOrigin::root(), old_hotkey)); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + let members = SenateMembers::members(); + assert!(members.contains(&old_hotkey)); + assert!(!members.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_delegates --exact --nocapture +#[test] +fn test_swap_delegates() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + Delegates::::insert(old_hotkey, 100); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(Delegates::::contains_key(old_hotkey)); + assert!(!Delegates::::contains_key(new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_subnet_membership --exact --nocapture +#[test] +fn test_swap_subnet_membership() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); + assert!(IsNetworkMember::::get(new_hotkey, netuid)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_uids_and_keys --exact --nocapture +#[test] +fn test_swap_uids_and_keys() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + Uids::::insert(netuid, old_hotkey, uid); + Keys::::insert(netuid, uid, old_hotkey); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert_eq!(Uids::::get(netuid, old_hotkey), None); + assert_eq!(Uids::::get(netuid, new_hotkey), Some(uid)); + assert_eq!(Keys::::get(netuid, uid), new_hotkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_prometheus --exact --nocapture +#[test] +fn test_swap_prometheus() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let prometheus_info = PrometheusInfo::default(); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(!Prometheus::::contains_key(netuid, old_hotkey)); + assert_eq!( + Prometheus::::get(netuid, new_hotkey), + Some(prometheus_info) + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_axons --exact --nocapture +#[test] +fn test_swap_axons() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let axon_info = AxonInfo::default(); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + Axons::::insert(netuid, old_hotkey, axon_info.clone()); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(!Axons::::contains_key(netuid, old_hotkey)); + assert_eq!(Axons::::get(netuid, new_hotkey), Some(axon_info)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_certificates --exact --nocapture +#[test] +fn test_swap_certificates() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let certificate = NeuronCertificate::try_from(vec![1, 2, 3]).unwrap(); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + NeuronCertificates::::insert(netuid, old_hotkey, certificate.clone()); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(!NeuronCertificates::::contains_key( + netuid, old_hotkey + )); + assert_eq!( + NeuronCertificates::::get(netuid, new_hotkey), + Some(certificate) + ); + }); +} +use sp_std::collections::vec_deque::VecDeque; +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_weight_commits --exact --nocapture +#[test] +fn test_swap_weight_commits() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let mut weight_commits: VecDeque<(H256, u64, u64, u64)> = VecDeque::new(); + weight_commits.push_back((H256::from_low_u64_be(100), 200, 1, 1)); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + WeightCommits::::insert(netuid, old_hotkey, weight_commits.clone()); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert!(!WeightCommits::::contains_key(netuid, old_hotkey)); + assert_eq!( + WeightCommits::::get(netuid, new_hotkey), + Some(weight_commits) + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_loaded_emission --exact --nocapture +#[test] +fn test_swap_loaded_emission() { + new_test_ext(1).execute_with(|| { + let uid = 5u16; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let server_emission = 1000u64; + let validator_emission = 1000u64; + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + IsNetworkMember::::insert(old_hotkey, netuid, true); + LoadedEmission::::insert( + netuid, + vec![(old_hotkey, server_emission, validator_emission)], + ); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + let new_loaded_emission = LoadedEmission::::get(netuid); + assert_eq!( + new_loaded_emission, + Some(vec![(new_hotkey, server_emission, validator_emission)]) + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_staking_hotkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + StakingHotkeys::::insert(coldkey, vec![old_hotkey]); + Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(100)); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + let staking_hotkeys = StakingHotkeys::::get(coldkey); + assert!(staking_hotkeys.contains(&old_hotkey)); + assert!(staking_hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::swap_hotkey::test_swap_hotkey_with_multiple_coldkeys --exact --show-output --nocapture +#[test] +fn test_swap_hotkey_with_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + + let stake = 1_000_000_000; + + StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(coldkey2, vec![old_hotkey]); + SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX); + SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX); + + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey1), + old_hotkey, + netuid, + stake + )); + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey2), + old_hotkey, + netuid, + stake / 2 + )); + let stake1_before = SubtensorModule::get_total_stake_for_coldkey(&coldkey1); + let stake2_before = SubtensorModule::get_total_stake_for_coldkey(&coldkey2); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey1), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert_eq!( + SubtensorModule::get_total_stake_for_coldkey(&coldkey1), + SubtensorModule::get_total_stake_for_coldkey(&coldkey1), + ); + assert_eq!( + SubtensorModule::get_total_stake_for_coldkey(&coldkey2), + SubtensorModule::get_total_stake_for_coldkey(&coldkey2), + ); + + assert_eq!( + SubtensorModule::get_total_stake_for_coldkey(&coldkey1), + stake1_before + ); + assert_eq!( + SubtensorModule::get_total_stake_for_coldkey(&coldkey2), + stake2_before + ); + + assert!(StakingHotkeys::::get(coldkey1).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(coldkey2).contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_with_multiple_subnets --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let new_hotkey_2 = U256::from(3); + let coldkey = U256::from(4); + + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + let netuid1 = add_dynamic_network(&old_hotkey, &coldkey); + let netuid2 = add_dynamic_network(&old_hotkey, &coldkey); + + IsNetworkMember::::insert(old_hotkey, netuid1, true); + IsNetworkMember::::insert(old_hotkey, netuid2, true); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid1) + )); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey_2, + Some(netuid2) + )); + + assert!(IsNetworkMember::::get(new_hotkey, netuid1)); + assert!(IsNetworkMember::::get(new_hotkey_2, netuid2)); + assert!(!IsNetworkMember::::get(old_hotkey, netuid1)); + assert!(!IsNetworkMember::::get(old_hotkey, netuid2)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_staking_hotkeys_multiple_coldkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let staker5 = U256::from(5); + + let stake = 1_000_000_000; + SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX); + SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX); + + // Set up initial state + StakingHotkeys::::insert(coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(coldkey2, vec![old_hotkey, staker5]); + + SubtensorModule::create_account_if_non_existent(&coldkey1, &old_hotkey); + + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey1), + old_hotkey, + netuid, + stake + )); + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey2), + old_hotkey, + netuid, + stake + )); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey1), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + // Check if new_hotkey replaced old_hotkey in StakingHotkeys + assert!(StakingHotkeys::::get(coldkey1).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(coldkey1).contains(&old_hotkey)); + + // Check if new_hotkey replaced old_hotkey for coldkey2 as well + assert!(StakingHotkeys::::get(coldkey2).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(coldkey2).contains(&old_hotkey)); + assert!(StakingHotkeys::::get(coldkey2).contains(&staker5)); + // Other hotkeys should remain + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_with_no_stake --exact --nocapture +#[test] +fn test_swap_hotkey_with_no_stake() { + new_test_ext(1).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Set up initial state with no stake + Owner::::insert(old_hotkey, coldkey); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + // Check if ownership transferred + assert!(Owner::::contains_key(old_hotkey)); + assert_eq!(Owner::::get(new_hotkey), coldkey); + + // Ensure no unexpected changes in Stake + assert!(!Alpha::::contains_key((old_hotkey, coldkey, netuid))); + assert!(!Alpha::::contains_key((new_hotkey, coldkey, netuid))); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::swap_hotkey::test_swap_hotkey_with_multiple_coldkeys_and_subnets --exact --show-output +#[test] +fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let new_hotkey_2 = U256::from(3); + let coldkey1 = U256::from(4); + let coldkey2 = U256::from(5); + let netuid1 = NetUid::from(1); + let netuid2 = NetUid::from(2); + let stake = DefaultMinStake::::get() * 10; + + // Set up initial state + add_network(netuid1, 1, 1); + add_network(netuid2, 1, 1); + register_ok_neuron(netuid1, old_hotkey, coldkey1, 1234); + register_ok_neuron(netuid2, old_hotkey, coldkey1, 1234); + + // Add balance to both coldkeys + SubtensorModule::add_balance_to_coldkey_account(&coldkey1, u64::MAX); + SubtensorModule::add_balance_to_coldkey_account(&coldkey2, u64::MAX); + + // Stake with coldkey1 + assert_ok!(SubtensorModule::add_stake( + <::RuntimeOrigin>::signed(coldkey1), + old_hotkey, + netuid1, + stake + )); + + // Stake with coldkey2 also + assert_ok!(SubtensorModule::add_stake( + <::RuntimeOrigin>::signed(coldkey2), + old_hotkey, + netuid2, + stake + )); + + let ck1_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &old_hotkey, + &coldkey1, + netuid1, + ); + let ck2_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &old_hotkey, + &coldkey2, + netuid2, + ); + assert!(ck1_stake > 0); + assert!(ck2_stake > 0); + let total_hk_stake = SubtensorModule::get_total_stake_for_hotkey(&old_hotkey); + assert!(total_hk_stake > 0); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey1), + &old_hotkey, + &new_hotkey, + Some(netuid1) + )); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey1), + &old_hotkey, + &new_hotkey_2, + Some(netuid2) + )); + + // Check ownership transfer + assert_eq!( + SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey), + coldkey1 + ); + assert!(!SubtensorModule::get_owned_hotkeys(&coldkey2).contains(&new_hotkey)); + assert_eq!( + SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey_2), + coldkey1 + ); + assert!(!SubtensorModule::get_owned_hotkeys(&coldkey2).contains(&new_hotkey_2)); + + // Check stake transfer + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &new_hotkey, + &coldkey1, + netuid1 + ), + ck1_stake + ); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &new_hotkey_2, + &coldkey2, + netuid2 + ), + ck2_stake + ); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &old_hotkey, + &coldkey1, + netuid1 + ), + 0 + ); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &old_hotkey, + &coldkey2, + netuid2 + ), + 0 + ); + + // Check subnet membership transfer + assert!(SubtensorModule::is_hotkey_registered_on_network( + netuid1, + &new_hotkey + )); + assert!(SubtensorModule::is_hotkey_registered_on_network( + netuid2, + &new_hotkey_2 + )); + assert!(!SubtensorModule::is_hotkey_registered_on_network( + netuid1, + &old_hotkey + )); + assert!(!SubtensorModule::is_hotkey_registered_on_network( + netuid2, + &old_hotkey + )); + + // Check total stake transfer + assert_eq!( + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey) + + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey_2), + total_hk_stake + ); + assert_eq!(SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), 0); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_tx_rate_limit_exceeded --exact --nocapture +#[test] +fn test_swap_hotkey_tx_rate_limit_exceeded() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(1); + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey_1 = U256::from(2); + let new_hotkey_2 = U256::from(4); + let coldkey = U256::from(3); + let swap_cost = 1_000_000_000u64 * 2; + + let tx_rate_limit = 1; + + // Get the current transaction rate limit + let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit(); + log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); + + // Set the transaction rate limit + SubtensorModule::set_tx_rate_limit(tx_rate_limit); + // assert the rate limit is set to 1000 blocks + assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + + // Perform the first swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey_1, + Some(netuid) + ),); + + // Attempt to perform another swap immediately, which should fail due to rate limit + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey_1, + Some(netuid) + ), + Error::::HotKeySetTxRateLimitExceeded + ); + + // move in time past the rate limit + step_block(1001); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &new_hotkey_1, + &new_hotkey_2, + None + )); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_do_swap_hotkey_err_not_owner --exact --nocapture +#[test] +fn test_do_swap_hotkey_err_not_owner() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(1); + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let not_owner_coldkey = U256::from(4); + let swap_cost = 1_000_000_000u64; + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); + + // Attempt the swap with a non-owner coldkey + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(not_owner_coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::NonAssociatedColdKey + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owner_old_hotkey_not_exist --exact --nocapture +#[test] +fn test_swap_owner_old_hotkey_not_exist() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&new_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Ensure old_hotkey does not exist + assert!(!Owner::::contains_key(old_hotkey)); + + // Perform the swap + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::NonAssociatedColdKey + ); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owner_new_hotkey_already_exists --exact --nocapture +#[test] +fn test_swap_owner_new_hotkey_already_exists() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let another_coldkey = U256::from(4); + + let netuid = add_dynamic_network(&new_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Initialize Owner for old_hotkey and new_hotkey + Owner::::insert(old_hotkey, coldkey); + Owner::::insert(new_hotkey, another_coldkey); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + + // Verify the swap + assert_eq!(Owner::::get(old_hotkey), coldkey); + assert!(Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_stake_success --exact --nocapture +#[test] +fn test_swap_stake_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + let amount = 10_000; + let shares = U64F64::from_num(123456); + + // Initialize staking variables for old_hotkey + TotalHotkeyAlpha::::insert(old_hotkey, netuid, amount); + TotalHotkeyAlphaLastEpoch::::insert(old_hotkey, netuid, amount * 2); + TotalHotkeyShares::::insert(old_hotkey, netuid, U64F64::from_num(shares)); + Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(amount)); + AlphaDividendsPerSubnet::::insert(netuid, old_hotkey, amount); + TaoDividendsPerSubnet::::insert(netuid, old_hotkey, amount); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Verify the swap + assert_eq!(TotalHotkeyAlpha::::get(old_hotkey, netuid), 0); + assert_eq!(TotalHotkeyAlpha::::get(new_hotkey, netuid), amount); + assert_eq!( + TotalHotkeyAlphaLastEpoch::::get(old_hotkey, netuid), + 0 + ); + assert_eq!( + TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid), + amount * 2 + ); + assert_eq!( + TotalHotkeyShares::::get(old_hotkey, netuid), + U64F64::from_num(0) + ); + assert_eq!( + TotalHotkeyShares::::get(new_hotkey, netuid), + U64F64::from_num(shares) + ); + assert_eq!( + Alpha::::get((old_hotkey, coldkey, netuid)), + U64F64::from_num(0) + ); + assert_eq!( + Alpha::::get((new_hotkey, coldkey, netuid)), + U64F64::from_num(amount) + ); + assert_eq!(AlphaDividendsPerSubnet::::get(netuid, old_hotkey), 0); + assert_eq!( + AlphaDividendsPerSubnet::::get(netuid, new_hotkey), + amount + ); + assert_eq!(TaoDividendsPerSubnet::::get(netuid, old_hotkey), 0); + assert_eq!( + TaoDividendsPerSubnet::::get(netuid, new_hotkey), + amount + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_error_cases --exact --nocapture +#[test] +fn test_swap_hotkey_error_cases() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let wrong_coldkey = U256::from(4); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + + // Set up initial state + Owner::::insert(old_hotkey, coldkey); + TotalNetworks::::put(1); + LastTxBlock::::insert(coldkey, 0); + + // Test not enough balance + let swap_cost = SubtensorModule::get_key_swap_cost(); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + + let initial_balance = SubtensorModule::get_key_swap_cost() + 1000; + SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + + // Test new hotkey same as old + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_noop!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &old_hotkey, + Some(netuid) + ), + Error::::NewHotKeyIsSameWithOld + ); + + // Test new hotkey already registered + IsNetworkMember::::insert(new_hotkey, netuid, true); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_noop!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + IsNetworkMember::::remove(new_hotkey, netuid); + + // Test non-associated coldkey + assert_noop!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(wrong_coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::NonAssociatedColdKey + ); + + // Run the successful swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_child_keys --exact --nocapture +#[test] +fn test_swap_child_keys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + let children = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; + + // Initialize ChildKeys for old_hotkey + ChildKeys::::insert(old_hotkey, netuid, children.clone()); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Verify the swap + assert_eq!(ChildKeys::::get(new_hotkey, netuid), children); + assert!(ChildKeys::::get(old_hotkey, netuid).is_empty()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_parent_keys --exact --nocapture +#[test] +fn test_swap_parent_keys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + let parents = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; + + // Initialize ParentKeys for old_hotkey + ParentKeys::::insert(old_hotkey, netuid, parents.clone()); + + // Initialize ChildKeys for parent + ChildKeys::::insert(U256::from(4), netuid, vec![(100u64, old_hotkey)]); + ChildKeys::::insert(U256::from(5), netuid, vec![(200u64, old_hotkey)]); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Verify ParentKeys swap + assert_eq!(ParentKeys::::get(new_hotkey, netuid), parents); + assert!(ParentKeys::::get(old_hotkey, netuid).is_empty()); + + // Verify ChildKeys update for parents + assert_eq!( + ChildKeys::::get(U256::from(4), netuid), + vec![(100u64, new_hotkey)] + ); + assert_eq!( + ChildKeys::::get(U256::from(5), netuid), + vec![(200u64, new_hotkey)] + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_multiple_subnets --exact --nocapture +#[test] +fn test_swap_multiple_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let new_hotkey_2 = U256::from(3); + let coldkey = U256::from(4); + let netuid1 = add_dynamic_network(&old_hotkey, &coldkey); + let netuid2 = add_dynamic_network(&old_hotkey, &coldkey); + + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + let children1 = vec![(100u64, U256::from(4)), (200u64, U256::from(5))]; + let children2 = vec![(300u64, U256::from(6))]; + + // Initialize ChildKeys for old_hotkey in multiple subnets + ChildKeys::::insert(old_hotkey, netuid1, children1.clone()); + ChildKeys::::insert(old_hotkey, netuid2, children2.clone()); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid1) + ),); + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey_2, + Some(netuid2) + ),); + + // Verify the swap for both subnets + assert_eq!(ChildKeys::::get(new_hotkey, netuid1), children1); + assert_eq!(ChildKeys::::get(new_hotkey_2, netuid2), children2); + assert!(ChildKeys::::get(old_hotkey, netuid1).is_empty()); + assert!(ChildKeys::::get(old_hotkey, netuid2).is_empty()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_complex_parent_child_structure --exact --nocapture +#[test] +fn test_swap_complex_parent_child_structure() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + let parent1 = U256::from(4); + let parent2 = U256::from(5); + let child1 = U256::from(6); + let child2 = U256::from(7); + + // Set up complex parent-child structure + ParentKeys::::insert( + old_hotkey, + netuid, + vec![(100u64, parent1), (200u64, parent2)], + ); + ChildKeys::::insert(old_hotkey, netuid, vec![(300u64, child1), (400u64, child2)]); + ChildKeys::::insert( + parent1, + netuid, + vec![(100u64, old_hotkey), (500u64, U256::from(8))], + ); + ChildKeys::::insert( + parent2, + netuid, + vec![(200u64, old_hotkey), (600u64, U256::from(9))], + ); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Verify ParentKeys swap + assert_eq!( + ParentKeys::::get(new_hotkey, netuid), + vec![(100u64, parent1), (200u64, parent2)] + ); + assert!(ParentKeys::::get(old_hotkey, netuid).is_empty()); + + // Verify ChildKeys swap + assert_eq!( + ChildKeys::::get(new_hotkey, netuid), + vec![(300u64, child1), (400u64, child2)] + ); + assert!(ChildKeys::::get(old_hotkey, netuid).is_empty()); + + // Verify parent's ChildKeys update + assert_eq!( + ChildKeys::::get(parent1, netuid), + vec![(100u64, new_hotkey), (500u64, U256::from(8))] + ); + assert_eq!( + ChildKeys::::get(parent2, netuid), + vec![(200u64, new_hotkey), (600u64, U256::from(9))] + ); + }); +} + +#[test] +fn test_swap_parent_hotkey_childkey_maps() { + new_test_ext(1).execute_with(|| { + let parent_old = U256::from(1); + let coldkey = U256::from(2); + let child = U256::from(3); + let child_other = U256::from(4); + let parent_new = U256::from(4); + + let netuid = add_dynamic_network(&parent_old, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + SubtensorModule::create_account_if_non_existent(&coldkey, &parent_old); + + // Set child and verify state maps + mock_set_children(&coldkey, &parent_old, netuid, &[(u64::MAX, child)]); + // Wait rate limit + step_rate_limit(&TransactionType::SetChildren, netuid); + // Schedule some pending child keys. + mock_schedule_children(&coldkey, &parent_old, netuid, &[(u64::MAX, child_other)]); + + assert_eq!( + ParentKeys::::get(child, netuid), + vec![(u64::MAX, parent_old)] + ); + assert_eq!( + ChildKeys::::get(parent_old, netuid), + vec![(u64::MAX, child)] + ); + let existing_pending_child_keys = PendingChildKeys::::get(netuid, parent_old); + assert_eq!(existing_pending_child_keys.0, vec![(u64::MAX, child_other)]); + + // Swap + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &parent_old, + &parent_new, + Some(netuid) + ),); + + // Verify parent and child keys updates + assert_eq!( + ParentKeys::::get(child, netuid), + vec![(u64::MAX, parent_new)] + ); + assert_eq!( + ChildKeys::::get(parent_new, netuid), + vec![(u64::MAX, child)] + ); + assert_eq!( + PendingChildKeys::::get(netuid, parent_new), + existing_pending_child_keys // Entry under new hotkey. + ); + }) +} + +#[test] +fn test_swap_child_hotkey_childkey_maps() { + new_test_ext(1).execute_with(|| { + let parent = U256::from(1); + let coldkey = U256::from(2); + let child_old = U256::from(3); + let child_new = U256::from(4); + let netuid = add_dynamic_network(&child_old, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + SubtensorModule::create_account_if_non_existent(&coldkey, &child_old); + SubtensorModule::create_account_if_non_existent(&coldkey, &parent); + + // Set child and verify state maps + mock_set_children(&coldkey, &parent, netuid, &[(u64::MAX, child_old)]); + // Wait rate limit + step_rate_limit(&TransactionType::SetChildren, netuid); + // Schedule some pending child keys. + mock_schedule_children(&coldkey, &parent, netuid, &[(u64::MAX, child_old)]); + + assert_eq!( + ParentKeys::::get(child_old, netuid), + vec![(u64::MAX, parent)] + ); + assert_eq!( + ChildKeys::::get(parent, netuid), + vec![(u64::MAX, child_old)] + ); + let existing_pending_child_keys = PendingChildKeys::::get(netuid, parent); + assert_eq!(existing_pending_child_keys.0, vec![(u64::MAX, child_old)]); + + // Swap + + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &child_old, + &child_new, + Some(netuid) + ),); + + // Verify parent and child keys updates + assert_eq!( + ParentKeys::::get(child_new, netuid), + vec![(u64::MAX, parent)] + ); + assert_eq!( + ChildKeys::::get(parent, netuid), + vec![(u64::MAX, child_new)] + ); + assert_eq!( + PendingChildKeys::::get(netuid, parent), + (vec![(u64::MAX, child_new)], existing_pending_child_keys.1) // Same cooldown block. + ); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_is_sn_owner_hotkey --exact --nocapture +#[test] +fn test_swap_hotkey_is_sn_owner_hotkey() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + // Create dynamic network + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Check for SubnetOwnerHotkey + assert_eq!(SubnetOwnerHotkey::::get(netuid), old_hotkey); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Check for SubnetOwnerHotkey + assert_eq!(SubnetOwnerHotkey::::get(netuid), new_hotkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_swap_rate_limits --exact --nocapture +#[test] +fn test_swap_hotkey_swap_rate_limits() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let last_tx_block = 123; + let delegate_take_block = 4567; + let child_key_take_block = 8910; + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + + // Set the last tx block for the old hotkey + LastTxBlock::::insert(old_hotkey, last_tx_block); + // Set the last delegate take block for the old hotkey + LastTxBlockDelegateTake::::insert(old_hotkey, delegate_take_block); + // Set last childkey take block for the old hotkey + LastTxBlockChildKeyTake::::insert(old_hotkey, child_key_take_block); + + // Perform the swap + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ),); + + // Check for new hotkey + assert_eq!(LastTxBlock::::get(new_hotkey), last_tx_block); + assert_eq!( + LastTxBlockDelegateTake::::get(new_hotkey), + delegate_take_block + ); + assert_eq!( + LastTxBlockChildKeyTake::::get(new_hotkey), + child_key_take_block + ); + }); +} + +#[test] +fn test_swap_owner_failed_interval_not_passed() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + Owner::::insert(old_hotkey, coldkey); + assert_err!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::HotKeySwapOnSubnetIntervalNotPassed, + ); + }); +} + +#[test] +fn test_swap_owner_check_swap_block_set() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + Owner::::insert(old_hotkey, coldkey); + let new_block_number = System::block_number() + HotkeySwapOnSubnetInterval::get(); + System::set_block_number(new_block_number); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert_eq!( + LastHotkeySwapOnNetuid::::get(netuid, coldkey), + new_block_number + ); + }); +} + +#[test] +fn test_swap_owner_check_swap_record_clean_up() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); + Owner::::insert(old_hotkey, coldkey); + let new_block_number = System::block_number() + HotkeySwapOnSubnetInterval::get(); + System::set_block_number(new_block_number); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + )); + + assert_eq!( + LastHotkeySwapOnNetuid::::get(netuid, coldkey), + new_block_number + ); + + step_block((HotkeySwapOnSubnetInterval::get() as u16 + u16::from(netuid)) * 2); + assert!(!LastHotkeySwapOnNetuid::::contains_key( + netuid, coldkey + )); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_hotkey_error_cases --exact --nocapture +#[test] +fn test_swap_hotkey_registered_on_other_subnet() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let wrong_coldkey = U256::from(4); + let netuid = add_dynamic_network(&old_hotkey, &coldkey); + let other_netuid = add_dynamic_network(&old_hotkey, &coldkey); + + // Set up initial state + Owner::::insert(old_hotkey, coldkey); + TotalNetworks::::put(1); + LastTxBlock::::insert(coldkey, 0); + + let initial_balance = SubtensorModule::get_key_swap_cost() + 1000; + SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + + // Test new hotkey already registered on other subnet + IsNetworkMember::::insert(new_hotkey, other_netuid, true); + System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); + assert_noop!( + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey, + Some(netuid) + ), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + }); +} diff --git a/pallets/subtensor/src/tests/uids.rs b/pallets/subtensor/src/tests/uids.rs index 92a8a64048..49233f105c 100644 --- a/pallets/subtensor/src/tests/uids.rs +++ b/pallets/subtensor/src/tests/uids.rs @@ -18,7 +18,7 @@ use sp_core::U256; fn test_replace_neuron() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( @@ -149,7 +149,7 @@ fn test_replace_neuron() { fn test_bonds_cleared_on_replace() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( @@ -216,8 +216,8 @@ fn test_bonds_cleared_on_replace() { fn test_replace_neuron_multiple_subnets() { new_test_ext(1).execute_with(|| { let block_number: u64 = 0; - let netuid: u16 = 1; - let netuid1: u16 = 2; + let netuid = NetUid::from(1); + let netuid1 = NetUid::from(2); let tempo: u16 = 13; let hotkey_account_id = U256::from(1); let new_hotkey_account_id = U256::from(2); diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index 3d240750cf..3e1c2f7557 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -1,23 +1,24 @@ -#![allow(clippy::indexing_slicing)] +#![allow(clippy::indexing_slicing, clippy::unwrap_used)] -use super::mock::*; -use crate::coinbase::run_coinbase::WeightsTlockPayload; -use crate::*; use ark_serialize::CanonicalDeserialize; use frame_support::{ assert_err, assert_ok, dispatch::{DispatchClass, DispatchResult, GetDispatchInfo, Pays}, }; +use frame_system::RawOrigin; +use pallet_drand::types::Pulse; use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng}; use scale_info::prelude::collections::HashMap; use sha2::Digest; +use sp_core::Encode; use sp_core::{Get, H256, U256}; use sp_runtime::{ BoundedVec, DispatchError, - traits::{BlakeTwo256, ConstU32, Hash, SignedExtension}, + traits::{BlakeTwo256, ConstU32, Hash, TxBaseImplication}, }; use sp_std::collections::vec_deque::VecDeque; use substrate_fixed::types::I32F32; +use subtensor_swap_interface::SwapHandler; use tle::{ curves::drand::TinyBLS381, ibe::fullident::Identity, @@ -26,8 +27,10 @@ use tle::{ }; use w3f_bls::EngineBLS; -use pallet_drand::types::Pulse; -use sp_core::Encode; +use super::mock; +use super::mock::*; +use crate::coinbase::run_coinbase::WeightsTlockPayload; +use crate::*; /*************************** pub fn set_weights() tests @@ -40,7 +43,7 @@ fn test_set_weights_dispatch_info_ok() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let call = RuntimeCall::SubtensorModule(SubtensorCall::set_weights { netuid, @@ -64,12 +67,12 @@ fn test_set_rootweights_validate() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let coldkey = U256::from(0); let hotkey: U256 = U256::from(1); // Add the hotkey field assert_ne!(hotkey, coldkey); // Ensure hotkey is NOT the same as coldkey !!! - let fee = DefaultStakingFee::::get(); + let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated let who = coldkey; // The coldkey signs this transaction @@ -98,16 +101,22 @@ fn test_set_rootweights_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result_no_stake, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into() - )) + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); // Increase the stake to be equal to the minimum @@ -125,7 +134,15 @@ fn test_set_rootweights_validate() { ); // Submit to the signed extension validate function - let result_min_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_min_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call should pass assert_ok!(result_min_stake); @@ -140,7 +157,15 @@ fn test_set_rootweights_validate() { // Verify stake is more than minimum assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) > min_stake); - let result_more_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_more_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // The call should still pass assert_ok!(result_more_stake); }); @@ -152,7 +177,7 @@ fn test_commit_weights_dispatch_info_ok() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let hotkey: U256 = U256::from(1); @@ -180,13 +205,12 @@ fn test_commit_weights_validate() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let coldkey = U256::from(0); let hotkey: U256 = U256::from(1); // Add the hotkey field assert_ne!(hotkey, coldkey); // Ensure hotkey is NOT the same as coldkey !!! - let fee = DefaultStakingFee::::get(); let who = hotkey; // The hotkey signs this transaction @@ -207,40 +231,55 @@ fn test_commit_weights_validate() { SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX); let min_stake = 500_000_000_000; - // Set the minimum stake - SubtensorModule::set_stake_threshold(min_stake); - - // Verify stake is less than minimum - assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) < min_stake); - let info: crate::DispatchInfo = - crate::DispatchInfoOf::<::RuntimeCall>::default(); - - let extension = crate::SubtensorSignedExtension::::new(); - // Submit to the signed extension validate function - let result_no_stake = extension.validate(&who, &call.clone(), &info, 10); - // Should fail - assert_err!( - // Should get an invalid transaction error - result_no_stake, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom(1)) - ); + let reserve = min_stake * 1000; + mock::setup_reserves(netuid, reserve, reserve); - // Increase the stake to be equal to the minimum + // Stake some TAO and read what get_total_stake_for_hotkey it gets + // It will be a different value due to the slippage assert_ok!(SubtensorModule::do_add_stake( RuntimeOrigin::signed(hotkey), hotkey, netuid, - min_stake + fee + min_stake )); + let min_stake_with_slippage = SubtensorModule::get_total_stake_for_hotkey(&hotkey); - // Verify stake is equal to minimum + // Set the minimum stake above what hotkey has + SubtensorModule::set_stake_threshold(min_stake_with_slippage + 1); + + // Submit to the signed extension validate function + let info = crate::DispatchInfoOf::<::RuntimeCall>::default(); + let extension = crate::SubtensorTransactionExtension::::new(); + // Submit to the signed extension validate function + let result_no_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); + // Should fail assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&hotkey), - min_stake + // Should get an invalid transaction error + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); + // Set the minimum stake equal to what hotkey has + SubtensorModule::set_stake_threshold(min_stake_with_slippage); + // Submit to the signed extension validate function - let result_min_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_min_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call should pass assert_ok!(result_min_stake); @@ -253,9 +292,17 @@ fn test_commit_weights_validate() { )); // Verify stake is more than minimum - assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) > min_stake); + assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) > min_stake_with_slippage); - let result_more_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_more_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // The call should still pass assert_ok!(result_more_stake); }); @@ -267,7 +314,7 @@ fn test_reveal_weights_dispatch_info_ok() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; @@ -292,11 +339,10 @@ fn test_set_weights_validate() { // correctly filters the `set_weights` transaction. new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let coldkey = U256::from(0); let hotkey: U256 = U256::from(1); assert_ne!(hotkey, coldkey); - let fee = DefaultStakingFee::::get(); let who = hotkey; // The hotkey signs this transaction @@ -309,6 +355,7 @@ fn test_set_weights_validate() { // Create netuid add_network(netuid, 1, 0); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000); // Register the hotkey SubtensorModule::append_neuron(netuid, &hotkey, 0); crate::Owner::::insert(hotkey, coldkey); @@ -316,6 +363,7 @@ fn test_set_weights_validate() { SubtensorModule::add_balance_to_coldkey_account(&hotkey, u64::MAX); let min_stake = 500_000_000_000; + // Set the minimum stake SubtensorModule::set_stake_threshold(min_stake); @@ -324,33 +372,47 @@ fn test_set_weights_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail due to insufficient stake - assert_err!( - result_no_stake, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into() - )) + assert_eq!( + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); - // Increase the stake to be equal to the minimum + // Increase the stake and make it to be equal to the minimum threshold + let fee = + ::SwapInterface::approx_fee_amount(netuid.into(), min_stake); assert_ok!(SubtensorModule::do_add_stake( RuntimeOrigin::signed(hotkey), hotkey, netuid, min_stake + fee )); + let min_stake_with_slippage = SubtensorModule::get_total_stake_for_hotkey(&hotkey); - // Verify stake is equal to minimum - assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&hotkey), - min_stake - ); + // Set the minimum stake to what the hotkey has + SubtensorModule::set_stake_threshold(min_stake_with_slippage); // Submit to the signed extension validate function - let result_min_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_min_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call should pass assert_ok!(result_min_stake); }); @@ -365,13 +427,13 @@ fn test_reveal_weights_validate() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; let weights = vec![1, 1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let version_key: u64 = 0; let coldkey = U256::from(0); let hotkey: U256 = U256::from(1); // Add the hotkey field assert_ne!(hotkey, coldkey); // Ensure hotkey is NOT the same as coldkey !!! - let fee = DefaultStakingFee::::get(); + let fee: u64 = 0; // FIXME: DefaultStakingFee is deprecated let who = hotkey; // The hotkey signs this transaction @@ -399,16 +461,22 @@ fn test_reveal_weights_validate() { let info: crate::DispatchInfo = crate::DispatchInfoOf::<::RuntimeCall>::default(); - let extension = crate::SubtensorSignedExtension::::new(); + let extension = crate::SubtensorTransactionExtension::::new(); // Submit to the signed extension validate function - let result_no_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_no_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Should fail - assert_err!( + assert_eq!( // Should get an invalid transaction error - result_no_stake, - crate::TransactionValidityError::Invalid(crate::InvalidTransaction::Custom( - CustomTransactionError::StakeAmountTooLow.into() - )) + result_no_stake.unwrap_err(), + CustomTransactionError::StakeAmountTooLow.into() ); // Increase the stake to be equal to the minimum @@ -426,7 +494,15 @@ fn test_reveal_weights_validate() { ); // Submit to the signed extension validate function - let result_min_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_min_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // Now the call should pass assert_ok!(result_min_stake); @@ -441,7 +517,15 @@ fn test_reveal_weights_validate() { // Verify stake is more than minimum assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) > min_stake); - let result_more_stake = extension.validate(&who, &call.clone(), &info, 10); + let result_more_stake = extension.validate( + RawOrigin::Signed(who).into(), + &call.clone(), + &info, + 10, + (), + &TxBaseImplication(()), + TransactionSource::External, + ); // The call should still pass assert_ok!(result_more_stake); }); @@ -451,8 +535,6 @@ fn test_reveal_weights_validate() { #[test] fn test_set_weights_is_root_error() { new_test_ext(0).execute_with(|| { - let root_netuid: u16 = 0; - let uids = vec![0]; let weights = vec![1]; let version_key: u64 = 0; @@ -461,7 +543,7 @@ fn test_set_weights_is_root_error() { assert_err!( SubtensorModule::set_weights( RuntimeOrigin::signed(hotkey), - root_netuid, + NetUid::ROOT, uids.clone(), weights.clone(), version_key, @@ -477,7 +559,7 @@ fn test_set_weights_is_root_error() { fn test_weights_err_no_validator_permit() { new_test_ext(0).execute_with(|| { let hotkey_account_id = U256::from(55); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; add_network(netuid, tempo, 0); SubtensorModule::set_min_allowed_weights(netuid, 0); @@ -522,7 +604,7 @@ fn test_set_stake_threshold_failed() { new_test_ext(0).execute_with(|| { let dests = vec![0]; let weights = vec![1]; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let version_key: u64 = 0; let hotkey = U256::from(0); let coldkey = U256::from(0); @@ -586,8 +668,8 @@ fn test_weights_version_key() { new_test_ext(0).execute_with(|| { let hotkey = U256::from(55); let coldkey = U256::from(66); - let netuid0: u16 = 1; - let netuid1: u16 = 2; + let netuid0 = NetUid::from(1); + let netuid1 = NetUid::from(2); add_network(netuid0, 1, 0); add_network(netuid1, 1, 0); @@ -663,7 +745,7 @@ fn test_weights_version_key() { fn test_weights_err_setting_weights_too_fast() { new_test_ext(0).execute_with(|| { let hotkey_account_id = U256::from(55); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; add_network(netuid, tempo, 0); SubtensorModule::set_min_allowed_weights(netuid, 0); @@ -726,11 +808,11 @@ fn test_weights_err_setting_weights_too_fast() { fn test_weights_err_weights_vec_not_equal_size() { new_test_ext(0).execute_with(|| { let hotkey_account_id = U256::from(55); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); - register_ok_neuron(1, hotkey_account_id, U256::from(66), 0); + register_ok_neuron(netuid, hotkey_account_id, U256::from(66), 0); let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id) .expect("Not registered."); @@ -739,7 +821,7 @@ fn test_weights_err_weights_vec_not_equal_size() { let weight_values: Vec = vec![1, 2, 3, 4, 5]; // Uneven sizes let result = commit_reveal_set_weights( hotkey_account_id, - 1, + 1.into(), weights_keys.clone(), weight_values.clone(), salt.clone(), @@ -755,7 +837,7 @@ fn test_weights_err_weights_vec_not_equal_size() { fn test_weights_err_has_duplicate_ids() { new_test_ext(0).execute_with(|| { let hotkey_account_id = U256::from(666); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); @@ -816,7 +898,7 @@ fn test_weights_err_max_weight_limit() { //TO DO SAM: uncomment when we implement run_to_block fn new_test_ext(0).execute_with(|| { // Add network. - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 100; add_network(netuid, tempo, 0); @@ -878,8 +960,13 @@ fn test_weights_err_max_weight_limit() { // Non self-weight fails. let uids: Vec = vec![1, 2, 3, 4]; let values: Vec = vec![u16::MAX / 4, u16::MAX / 4, u16::MAX / 54, u16::MAX / 4]; - let result = - SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(0)), 1, uids, values, 0); + let result = SubtensorModule::set_weights( + RuntimeOrigin::signed(U256::from(0)), + 1.into(), + uids, + values, + 0, + ); assert_eq!(result, Err(Error::::MaxWeightExceeded.into())); // Self-weight is a success. @@ -887,7 +974,7 @@ fn test_weights_err_max_weight_limit() { let values: Vec = vec![u16::MAX]; // normalizes to u32::MAX assert_ok!(SubtensorModule::set_weights( RuntimeOrigin::signed(U256::from(0)), - 1, + 1.into(), uids, values, 0 @@ -902,7 +989,7 @@ fn test_no_signature() { new_test_ext(0).execute_with(|| { let uids: Vec = vec![]; let values: Vec = vec![]; - let result = SubtensorModule::set_weights(RuntimeOrigin::none(), 1, uids, values, 0); + let result = SubtensorModule::set_weights(RuntimeOrigin::none(), 1.into(), uids, values, 0); assert_eq!(result, Err(DispatchError::BadOrigin)); }); } @@ -912,21 +999,27 @@ fn test_no_signature() { #[test] fn test_set_weights_err_not_active() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); // Register one neuron. Should have uid 0 - register_ok_neuron(1, U256::from(666), U256::from(2), 100000); + register_ok_neuron(netuid, U256::from(666), U256::from(2), 100000); SubtensorModule::get_uid_for_net_and_hotkey(netuid, &U256::from(666)) .expect("Not registered."); let weights_keys: Vec = vec![0]; // Uid 0 is valid. let weight_values: Vec = vec![1]; // This hotkey is NOT registered. - let result = - commit_reveal_set_weights(U256::from(1), 1, weights_keys, weight_values, salt, 0); + let result = commit_reveal_set_weights( + U256::from(1), + 1.into(), + weights_keys, + weight_values, + salt, + 0, + ); assert_eq!( result, Err(Error::::HotKeyNotRegisteredInSubNet.into()) @@ -940,11 +1033,11 @@ fn test_set_weights_err_not_active() { fn test_set_weights_err_invalid_uid() { new_test_ext(0).execute_with(|| { let hotkey_account_id = U256::from(55); - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); - register_ok_neuron(1, hotkey_account_id, U256::from(66), 0); + register_ok_neuron(netuid, hotkey_account_id, U256::from(66), 0); let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id) .expect("Not registered."); @@ -959,8 +1052,14 @@ fn test_set_weights_err_invalid_uid() { ); let weight_keys: Vec = vec![9999]; // Does not exist let weight_values: Vec = vec![88]; // random value - let result = - commit_reveal_set_weights(hotkey_account_id, 1, weight_keys, weight_values, salt, 0); + let result = commit_reveal_set_weights( + hotkey_account_id, + netuid, + weight_keys, + weight_values, + salt, + 0, + ); assert_eq!(result, Err(Error::::UidVecContainInvalidOne.into())); }); } @@ -970,13 +1069,13 @@ fn test_set_weights_err_invalid_uid() { #[test] fn test_set_weight_not_enough_values() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; let account_id = U256::from(1); add_network(netuid, tempo, 0); - register_ok_neuron(1, account_id, U256::from(2), 100000); + register_ok_neuron(netuid, account_id, U256::from(2), 100000); let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &U256::from(1)) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); @@ -989,7 +1088,7 @@ fn test_set_weight_not_enough_values() { 1, ); - register_ok_neuron(1, U256::from(3), U256::from(4), 300000); + register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); SubtensorModule::set_min_allowed_weights(netuid, 2); // Should fail because we are only setting a single value and its not the self weight. @@ -997,7 +1096,7 @@ fn test_set_weight_not_enough_values() { let weight_values: Vec = vec![88]; // random value. let result = SubtensorModule::set_weights( RuntimeOrigin::signed(account_id), - 1, + 1.into(), weight_keys, weight_values, 0, @@ -1009,7 +1108,7 @@ fn test_set_weight_not_enough_values() { let weight_values: Vec = vec![88]; // random value. assert_ok!(SubtensorModule::set_weights( RuntimeOrigin::signed(account_id), - 1, + 1.into(), weight_keys, weight_values, 0 @@ -1021,7 +1120,7 @@ fn test_set_weight_not_enough_values() { SubtensorModule::set_min_allowed_weights(netuid, 1); assert_ok!(commit_reveal_set_weights( account_id, - 1, + 1.into(), weight_keys, weight_values, salt, @@ -1035,17 +1134,17 @@ fn test_set_weight_not_enough_values() { #[test] fn test_set_weight_too_many_uids() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; add_network(netuid, tempo, 0); - register_ok_neuron(1, U256::from(1), U256::from(2), 100_000); + register_ok_neuron(1.into(), U256::from(1), U256::from(2), 100_000); let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &U256::from(1)) .expect("Not registered."); SubtensorModule::set_validator_permit_for_uid(netuid, neuron_uid, true); - register_ok_neuron(1, U256::from(3), U256::from(4), 300_000); - SubtensorModule::set_min_allowed_weights(1, 2); + register_ok_neuron(1.into(), U256::from(3), U256::from(4), 300_000); + SubtensorModule::set_min_allowed_weights(1.into(), 2); SubtensorModule::set_max_weight_limit(netuid, u16::MAX); // Should fail because we are setting more weights than there are neurons. @@ -1053,7 +1152,7 @@ fn test_set_weight_too_many_uids() { let weight_values: Vec = vec![88, 102, 303, 1212, 11]; // random value. let result = SubtensorModule::set_weights( RuntimeOrigin::signed(U256::from(1)), - 1, + 1.into(), weight_keys, weight_values, 0, @@ -1068,7 +1167,7 @@ fn test_set_weight_too_many_uids() { let weight_values: Vec = vec![10, 10]; // random value. assert_ok!(SubtensorModule::set_weights( RuntimeOrigin::signed(U256::from(1)), - 1, + 1.into(), weight_keys, weight_values, 0 @@ -1081,12 +1180,12 @@ fn test_set_weight_too_many_uids() { #[test] fn test_set_weights_sum_larger_than_u16_max() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; add_network(netuid, tempo, 0); - register_ok_neuron(1, U256::from(1), U256::from(2), 100_000); + register_ok_neuron(1.into(), U256::from(1), U256::from(2), 100_000); let neuron_uid: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &U256::from(1)) .expect("Not registered."); SubtensorModule::set_stake_threshold(0); @@ -1100,8 +1199,8 @@ fn test_set_weights_sum_larger_than_u16_max() { 1, ); - register_ok_neuron(1, U256::from(3), U256::from(4), 300_000); - SubtensorModule::set_min_allowed_weights(1, 2); + register_ok_neuron(1.into(), U256::from(3), U256::from(4), 300_000); + SubtensorModule::set_min_allowed_weights(1.into(), 2); // Shouldn't fail because we are setting the right number of weights. let weight_keys: Vec = vec![0, 1]; @@ -1110,7 +1209,7 @@ fn test_set_weights_sum_larger_than_u16_max() { assert!(weight_values.iter().map(|x| *x as u64).sum::() > (u16::MAX as u64)); let result = - commit_reveal_set_weights(U256::from(1), 1, weight_keys, weight_values, salt, 0); + commit_reveal_set_weights(U256::from(1), 1.into(), weight_keys, weight_values, salt, 0); assert_ok!(result); // Get max-upscaled unnormalized weights. @@ -1126,7 +1225,7 @@ fn test_set_weights_sum_larger_than_u16_max() { #[test] fn test_check_length_allows_singleton() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_allowed: u16 = 1; let min_allowed_weights = max_allowed; @@ -1149,7 +1248,7 @@ fn test_check_length_allows_singleton() { #[test] fn test_check_length_weights_length_exceeds_min_allowed() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let max_allowed: u16 = 3; let min_allowed_weights = max_allowed; @@ -1172,7 +1271,7 @@ fn test_check_length_weights_length_exceeds_min_allowed() { #[test] fn test_check_length_to_few_weights() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let min_allowed_weights = 3; @@ -1180,13 +1279,13 @@ fn test_check_length_to_few_weights() { SubtensorModule::set_target_registrations_per_interval(netuid, 100); SubtensorModule::set_max_registrations_per_block(netuid, 100); // register morw than min allowed - register_ok_neuron(1, U256::from(1), U256::from(1), 300_000); - register_ok_neuron(1, U256::from(2), U256::from(2), 300_001); - register_ok_neuron(1, U256::from(3), U256::from(3), 300_002); - register_ok_neuron(1, U256::from(4), U256::from(4), 300_003); - register_ok_neuron(1, U256::from(5), U256::from(5), 300_004); - register_ok_neuron(1, U256::from(6), U256::from(6), 300_005); - register_ok_neuron(1, U256::from(7), U256::from(7), 300_006); + register_ok_neuron(1.into(), U256::from(1), U256::from(1), 300_000); + register_ok_neuron(1.into(), U256::from(2), U256::from(2), 300_001); + register_ok_neuron(1.into(), U256::from(3), U256::from(3), 300_002); + register_ok_neuron(1.into(), U256::from(4), U256::from(4), 300_003); + register_ok_neuron(1.into(), U256::from(5), U256::from(5), 300_004); + register_ok_neuron(1.into(), U256::from(6), U256::from(6), 300_005); + register_ok_neuron(1.into(), U256::from(7), U256::from(7), 300_006); SubtensorModule::set_min_allowed_weights(netuid, min_allowed_weights); let uids: Vec = Vec::from_iter((0..2).map(|id| id + 1)); @@ -1242,7 +1341,7 @@ fn test_max_weight_limited_allow_self_weights_to_exceed_max_weight_limit() { new_test_ext(0).execute_with(|| { let max_allowed: u16 = 1; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = Vec::from_iter((0..max_allowed).map(|id| id + 1)); let uid: u16 = uids[0]; let weights: Vec = vec![0]; @@ -1264,7 +1363,7 @@ fn test_max_weight_limited_when_weight_limit_is_u16_max() { new_test_ext(0).execute_with(|| { let max_allowed: u16 = 3; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = Vec::from_iter((0..max_allowed).map(|id| id + 1)); let uid: u16 = uids[0]; let weights: Vec = Vec::from_iter((0..max_allowed).map(|_id| u16::MAX)); @@ -1287,7 +1386,7 @@ fn test_max_weight_limited_when_max_weight_is_within_limit() { let max_allowed: u16 = 1; let max_weight_limit = u16::MAX / 5; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = Vec::from_iter((0..max_allowed).map(|id| id + 1)); let uid: u16 = uids[0]; let weights: Vec = Vec::from_iter((0..max_allowed).map(|id| max_weight_limit - id)); @@ -1312,7 +1411,7 @@ fn test_max_weight_limited_when_guard_checks_are_not_triggered() { let max_allowed: u16 = 3; let max_weight_limit = u16::MAX / 5; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = Vec::from_iter((0..max_allowed).map(|id| id + 1)); let uid: u16 = uids[0]; let weights: Vec = Vec::from_iter((0..max_allowed).map(|id| max_weight_limit + id)); @@ -1398,7 +1497,7 @@ fn test_is_self_weight_uid_in_uids() { #[test] fn test_check_len_uids_within_allowed_within_network_pool() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let modality: u16 = 0; @@ -1431,7 +1530,7 @@ fn test_check_len_uids_within_allowed_within_network_pool() { #[test] fn test_check_len_uids_within_allowed_not_within_network_pool() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let tempo: u16 = 13; let modality: u16 = 0; @@ -1464,7 +1563,7 @@ fn test_check_len_uids_within_allowed_not_within_network_pool() { #[test] fn test_set_weights_commit_reveal_enabled_error() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 1, 0); register_ok_neuron(netuid, U256::from(1), U256::from(2), 10); @@ -1502,7 +1601,7 @@ fn test_set_weights_commit_reveal_enabled_error() { #[test] fn test_reveal_weights_when_commit_reveal_disabled() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -1562,7 +1661,7 @@ fn test_reveal_weights_when_commit_reveal_disabled() { #[test] fn test_commit_reveal_weights_ok() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -1631,7 +1730,7 @@ fn test_commit_reveal_weights_ok() { #[test] fn test_commit_reveal_tempo_interval() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -1777,7 +1876,7 @@ fn test_commit_reveal_tempo_interval() { #[test] fn test_commit_reveal_hash() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -1869,7 +1968,7 @@ fn test_commit_reveal_hash() { #[test] fn test_commit_reveal_disabled_or_enabled() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -1946,7 +2045,7 @@ fn test_commit_reveal_disabled_or_enabled() { #[test] fn test_toggle_commit_reveal_weights_and_set_weights() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -2029,7 +2128,7 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { #[test] fn test_tempo_change_during_commit_reveal_process() { new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -2187,7 +2286,7 @@ fn test_tempo_change_during_commit_reveal_process() { #[test] fn test_commit_reveal_multiple_commits() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let version_key: u64 = 0; @@ -2553,7 +2652,7 @@ fn test_commit_reveal_multiple_commits() { fn commit_reveal_set_weights( hotkey: U256, - netuid: u16, + netuid: NetUid, uids: Vec, weights: Vec, salt: Vec, @@ -2590,7 +2689,7 @@ fn commit_reveal_set_weights( #[test] fn test_expired_commits_handling_in_commit_and_reveal() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: ::AccountId = U256::from(1); let version_key: u64 = 0; let uids: Vec = vec![0, 1]; @@ -2789,7 +2888,7 @@ fn test_expired_commits_handling_in_commit_and_reveal() { #[test] fn test_reveal_at_exact_epoch() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: ::AccountId = U256::from(1); let version_key: u64 = 0; let uids: Vec = vec![0, 1]; @@ -2939,7 +3038,7 @@ fn test_reveal_at_exact_epoch() { #[test] fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![42; 8]; @@ -3143,7 +3242,7 @@ fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { #[test] fn test_commit_reveal_order_enforcement() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: ::AccountId = U256::from(1); let version_key: u64 = 0; let uids: Vec = vec![0, 1]; @@ -3245,7 +3344,7 @@ fn test_commit_reveal_order_enforcement() { #[test] fn test_reveal_at_exact_block() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: ::AccountId = U256::from(1); let version_key: u64 = 0; let uids: Vec = vec![0, 1]; @@ -3304,7 +3403,7 @@ fn test_reveal_at_exact_block() { // Calculate the block number where the reveal epoch starts let tempo_plus_one = (tempo as u64).saturating_add(1); - let netuid_plus_one = (netuid as u64).saturating_add(1); + let netuid_plus_one = (u16::from(netuid) as u64).saturating_add(1); let reveal_epoch_start_block = reveal_epoch .saturating_mul(tempo_plus_one) .saturating_sub(netuid_plus_one); @@ -3415,7 +3514,7 @@ fn test_reveal_at_exact_block() { #[test] fn test_successful_batch_reveal() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0, 0, 0]; let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; @@ -3493,7 +3592,7 @@ fn test_successful_batch_reveal() { #[test] fn test_batch_reveal_with_expired_commits() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0, 0, 0]; let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; @@ -3614,7 +3713,7 @@ fn test_batch_reveal_with_expired_commits() { #[test] fn test_batch_reveal_with_invalid_input_lengths() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let tempo: u16 = 100; @@ -3712,7 +3811,7 @@ fn test_batch_reveal_with_invalid_input_lengths() { #[test] fn test_batch_reveal_with_no_commits() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0]; let uids_list: Vec> = vec![vec![0, 1]]; @@ -3742,7 +3841,7 @@ fn test_batch_reveal_with_no_commits() { #[test] fn test_batch_reveal_before_reveal_period() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0, 0]; let uids_list: Vec> = vec![vec![0, 1], vec![1, 0]]; @@ -3800,7 +3899,7 @@ fn test_batch_reveal_before_reveal_period() { #[test] fn test_batch_reveal_after_commits_expired() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0, 0]; let uids_list: Vec> = vec![vec![0, 1], vec![1, 0]]; @@ -3880,7 +3979,7 @@ fn test_batch_reveal_after_commits_expired() { #[test] fn test_batch_reveal_when_commit_reveal_disabled() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0]; let uids_list: Vec> = vec![vec![0, 1]]; @@ -3910,7 +4009,7 @@ fn test_batch_reveal_when_commit_reveal_disabled() { #[test] fn test_batch_reveal_with_out_of_order_commits() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey = U256::from(1); let version_keys: Vec = vec![0, 0, 0]; let uids_list: Vec> = vec![vec![0, 1], vec![1, 0], vec![0, 1]]; @@ -4022,7 +4121,7 @@ fn test_batch_reveal_with_out_of_order_commits() { fn test_highly_concurrent_commits_and_reveals_with_multiple_hotkeys() { new_test_ext(1).execute_with(|| { // ==== Test Configuration ==== - let netuid: u16 = 1; + let netuid = NetUid::from(1); let num_hotkeys: usize = 10; let max_unrevealed_commits: usize = 10; let commits_per_hotkey: usize = 20; @@ -4301,7 +4400,7 @@ fn test_highly_concurrent_commits_and_reveals_with_multiple_hotkeys() { fn test_get_reveal_blocks() { new_test_ext(1).execute_with(|| { // **1. Define Test Parameters** - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -4440,7 +4539,7 @@ fn test_get_reveal_blocks() { #[test] fn test_commit_weights_rate_limit() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let uids: Vec = vec![0, 1]; let weight_values: Vec = vec![10, 10]; let salt: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; @@ -4637,7 +4736,7 @@ fn test_reveal_crv3_commits_success() { new_test_ext(100).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey1: AccountId = U256::from(1); let hotkey2: AccountId = U256::from(2); let reveal_round: u64 = 1000; @@ -4793,7 +4892,7 @@ fn test_reveal_crv3_commits_cannot_reveal_after_reveal_epoch() { new_test_ext(100).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey1: AccountId = U256::from(1); let hotkey2: AccountId = U256::from(2); let reveal_round: u64 = 1000; @@ -4918,7 +5017,7 @@ fn test_reveal_crv3_commits_cannot_reveal_after_reveal_epoch() { #[test] fn test_do_commit_crv3_weights_success() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let commit_data: Vec = vec![1, 2, 3, 4, 5]; let reveal_round: u64 = 1000; @@ -4952,7 +5051,7 @@ fn test_do_commit_crv3_weights_success() { #[test] fn test_do_commit_crv3_weights_disabled() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let commit_data: Vec = vec![1, 2, 3, 4, 5]; let reveal_round: u64 = 1000; @@ -4980,7 +5079,7 @@ fn test_do_commit_crv3_weights_disabled() { #[test] fn test_do_commit_crv3_weights_hotkey_not_registered() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let unregistered_hotkey: AccountId = U256::from(99); let commit_data: Vec = vec![1, 2, 3, 4, 5]; let reveal_round: u64 = 1000; @@ -5009,7 +5108,7 @@ fn test_do_commit_crv3_weights_hotkey_not_registered() { #[test] fn test_do_commit_crv3_weights_committing_too_fast() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let commit_data_1: Vec = vec![1, 2, 3]; let commit_data_2: Vec = vec![4, 5, 6]; @@ -5078,7 +5177,7 @@ fn test_do_commit_crv3_weights_committing_too_fast() { #[test] fn test_do_commit_crv3_weights_too_many_unrevealed_commits() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey1: AccountId = U256::from(1); let hotkey2: AccountId = U256::from(2); let reveal_round: u64 = 1000; @@ -5183,7 +5282,7 @@ fn test_do_commit_crv3_weights_too_many_unrevealed_commits() { #[test] fn test_reveal_crv3_commits_decryption_failure() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5236,7 +5335,7 @@ fn test_reveal_crv3_commits_multiple_commits_some_fail_some_succeed() { new_test_ext(100).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey1: AccountId = U256::from(1); let hotkey2: AccountId = U256::from(2); let reveal_round: u64 = 1000; @@ -5360,7 +5459,7 @@ fn test_reveal_crv3_commits_do_set_weights_failure() { new_test_ext(1).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5446,7 +5545,7 @@ fn test_reveal_crv3_commits_payload_decoding_failure() { new_test_ext(1).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5525,7 +5624,7 @@ fn test_reveal_crv3_commits_signature_deserialization_failure() { new_test_ext(1).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5605,7 +5704,7 @@ fn test_reveal_crv3_commits_signature_deserialization_failure() { #[test] fn test_do_commit_crv3_weights_commit_size_exceeds_limit() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5648,7 +5747,7 @@ fn test_do_commit_crv3_weights_commit_size_exceeds_limit() { #[test] fn test_reveal_crv3_commits_with_empty_commit_queue() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); add_network(netuid, 5, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -5670,7 +5769,7 @@ fn test_reveal_crv3_commits_with_incorrect_identity_message() { new_test_ext(1).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5756,7 +5855,7 @@ fn test_reveal_crv3_commits_with_incorrect_identity_message() { #[test] fn test_multiple_commits_by_same_hotkey_within_limit() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5793,7 +5892,7 @@ fn test_multiple_commits_by_same_hotkey_within_limit() { #[test] fn test_reveal_crv3_commits_removes_past_epoch_commits() { new_test_ext(100).execute_with(|| { - let netuid: u16 = 1; + let netuid = NetUid::from(1); let hotkey: AccountId = U256::from(1); let reveal_round: u64 = 1000; @@ -5860,7 +5959,7 @@ fn test_reveal_crv3_commits_multiple_valid_commits_all_processed() { new_test_ext(100).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let reveal_round: u64 = 1000; // Initialize the network @@ -6049,7 +6148,7 @@ fn test_reveal_crv3_commits_max_neurons() { new_test_ext(100).execute_with(|| { use ark_serialize::CanonicalSerialize; - let netuid: u16 = 1; + let netuid = NetUid::from(1); let reveal_round: u64 = 1000; add_network(netuid, 5, 0); diff --git a/pallets/subtensor/src/utils/evm.rs b/pallets/subtensor/src/utils/evm.rs index 6877739f69..ba6214968d 100644 --- a/pallets/subtensor/src/utils/evm.rs +++ b/pallets/subtensor/src/utils/evm.rs @@ -5,6 +5,7 @@ use frame_support::ensure; use frame_system::ensure_signed; use sp_core::{H160, ecdsa::Signature, hashing::keccak_256}; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; const MESSAGE_PREFIX: &str = "\x19Ethereum Signed Message:\n"; @@ -42,18 +43,12 @@ impl Pallet { /// * `signature` - A signed message by the `evm_key` containing the `hotkey` and the hashed `block_number`. pub fn do_associate_evm_key( origin: T::RuntimeOrigin, - netuid: u16, - hotkey: T::AccountId, + netuid: NetUid, evm_key: H160, block_number: u64, mut signature: Signature, ) -> dispatch::DispatchResult { - let coldkey = ensure_signed(origin)?; - - ensure!( - Self::get_owning_coldkey_for_hotkey(&hotkey) == coldkey, - Error::::NonAssociatedColdKey - ); + let hotkey = ensure_signed(origin)?; // Normalize the v value to 0 or 1 if signature.0[64] >= 27 { @@ -91,7 +86,7 @@ impl Pallet { Ok(()) } - pub fn uid_lookup(netuid: u16, evm_key: H160, limit: u16) -> Vec<(u16, u64)> { + pub fn uid_lookup(netuid: NetUid, evm_key: H160, limit: u16) -> Vec<(u16, u64)> { let mut ret_val = AssociatedEvmAddress::::iter_prefix(netuid) .take(limit as usize) .filter_map(|(uid, (stored_evm_key, block_associated))| { diff --git a/pallets/subtensor/src/utils/identity.rs b/pallets/subtensor/src/utils/identity.rs index c4b9fdc821..059fe2a7a2 100644 --- a/pallets/subtensor/src/utils/identity.rs +++ b/pallets/subtensor/src/utils/identity.rs @@ -2,6 +2,7 @@ use super::*; use frame_support::ensure; use frame_system::ensure_signed; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; impl Pallet { /// Sets the identity for a coldkey. @@ -96,13 +97,14 @@ impl Pallet { /// Returns `Ok(())` if the subnet identity is successfully set, otherwise returns an error. pub fn do_set_subnet_identity( origin: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, subnet_name: Vec, github_repo: Vec, subnet_contact: Vec, subnet_url: Vec, discord: Vec, description: Vec, + logo_url: Vec, additional: Vec, ) -> dispatch::DispatchResult { // Ensure the call is signed and get the signer's (coldkey) account @@ -115,13 +117,14 @@ impl Pallet { ); // Create the identity struct with the provided information - let identity: SubnetIdentityOfV2 = SubnetIdentityOfV2 { + let identity: SubnetIdentityOfV3 = SubnetIdentityOfV3 { subnet_name, github_repo, subnet_contact, subnet_url, discord, description, + logo_url, additional, }; @@ -132,7 +135,7 @@ impl Pallet { ); // Store the validated identity in the blockchain state - SubnetIdentitiesV2::::insert(netuid, identity.clone()); + SubnetIdentitiesV3::::insert(netuid, identity.clone()); // Log the identity set event log::debug!("SubnetIdentitySet( netuid:{:?} ) ", netuid); @@ -185,20 +188,20 @@ impl Pallet { && identity.additional.len() <= 1024 } - /// Validates the given SubnetIdentityOf struct. + /// Validates the given SubnetIdentityOfV3 struct. /// - /// This function checks if the total length of all fields in the SubnetIdentityOf struct + /// This function checks if the total length of all fields in the SubnetIdentityOfV3 struct /// is less than or equal to 2304 bytes, and if each individual field is also /// within its respective maximum byte limit. /// /// # Arguments /// - /// * `identity` - A reference to the SubnetIdentityOf struct to be validated. + /// * `identity` - A reference to the SubnetIdentityOfV3 struct to be validated. /// /// # Returns /// - /// * `bool` - Returns true if the SubnetIdentity is valid, false otherwise. - pub fn is_valid_subnet_identity(identity: &SubnetIdentityOfV2) -> bool { + /// * `bool` - Returns true if the SubnetIdentityV3 is valid, false otherwise. + pub fn is_valid_subnet_identity(identity: &SubnetIdentityOfV3) -> bool { let total_length = identity .subnet_name .len() @@ -211,6 +214,7 @@ impl Pallet { .saturating_add(1024) .saturating_add(256) .saturating_add(1024) + .saturating_add(1024) .saturating_add(1024); total_length <= max_length @@ -220,6 +224,7 @@ impl Pallet { && identity.subnet_url.len() <= 1024 && identity.discord.len() <= 256 && identity.description.len() <= 1024 + && identity.logo_url.len() <= 1024 && identity.additional.len() <= 1024 } } diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 899fa83646..9641cfb0ee 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -8,11 +8,12 @@ use sp_core::Get; use sp_core::U256; use sp_runtime::Saturating; use substrate_fixed::types::{I32F32, U96F32}; +use subtensor_runtime_common::NetUid; impl Pallet { pub fn ensure_subnet_owner_or_root( o: T::RuntimeOrigin, - netuid: u16, + netuid: NetUid, ) -> Result<(), DispatchError> { let coldkey = ensure_signed_or_root(o); match coldkey { @@ -23,7 +24,7 @@ impl Pallet { } } - pub fn ensure_subnet_owner(o: T::RuntimeOrigin, netuid: u16) -> Result<(), DispatchError> { + pub fn ensure_subnet_owner(o: T::RuntimeOrigin, netuid: NetUid) -> Result<(), DispatchError> { let coldkey = ensure_signed(o); match coldkey { Ok(who) if SubnetOwner::::get(netuid) == who => Ok(()), @@ -35,30 +36,33 @@ impl Pallet { // ======================== // ==== Global Setters ==== // ======================== - pub fn set_tempo(netuid: u16, tempo: u16) { + pub fn set_tempo(netuid: NetUid, tempo: u16) { Tempo::::insert(netuid, tempo); Self::deposit_event(Event::TempoSet(netuid, tempo)); } - pub fn set_last_adjustment_block(netuid: u16, last_adjustment_block: u64) { + pub fn set_last_adjustment_block(netuid: NetUid, last_adjustment_block: u64) { LastAdjustmentBlock::::insert(netuid, last_adjustment_block); } - pub fn set_blocks_since_last_step(netuid: u16, blocks_since_last_step: u64) { + pub fn set_blocks_since_last_step(netuid: NetUid, blocks_since_last_step: u64) { BlocksSinceLastStep::::insert(netuid, blocks_since_last_step); } - pub fn set_registrations_this_block(netuid: u16, registrations_this_block: u16) { + pub fn set_registrations_this_block(netuid: NetUid, registrations_this_block: u16) { RegistrationsThisBlock::::insert(netuid, registrations_this_block); } - pub fn set_last_mechanism_step_block(netuid: u16, last_mechanism_step_block: u64) { + pub fn set_last_mechanism_step_block(netuid: NetUid, last_mechanism_step_block: u64) { LastMechansimStepBlock::::insert(netuid, last_mechanism_step_block); } - pub fn set_registrations_this_interval(netuid: u16, registrations_this_interval: u16) { + pub fn set_registrations_this_interval(netuid: NetUid, registrations_this_interval: u16) { RegistrationsThisInterval::::insert(netuid, registrations_this_interval); } - pub fn set_pow_registrations_this_interval(netuid: u16, pow_registrations_this_interval: u16) { + pub fn set_pow_registrations_this_interval( + netuid: NetUid, + pow_registrations_this_interval: u16, + ) { POWRegistrationsThisInterval::::insert(netuid, pow_registrations_this_interval); } pub fn set_burn_registrations_this_interval( - netuid: u16, + netuid: NetUid, burn_registrations_this_interval: u16, ) { BurnRegistrationsThisInterval::::insert(netuid, burn_registrations_this_interval); @@ -79,44 +83,44 @@ impl Pallet { // ============================== // ==== YumaConsensus params ==== // ============================== - pub fn get_rank(netuid: u16) -> Vec { + pub fn get_rank(netuid: NetUid) -> Vec { Rank::::get(netuid) } - pub fn get_trust(netuid: u16) -> Vec { + pub fn get_trust(netuid: NetUid) -> Vec { Trust::::get(netuid) } - pub fn get_active(netuid: u16) -> Vec { + pub fn get_active(netuid: NetUid) -> Vec { Active::::get(netuid) } - pub fn get_emission(netuid: u16) -> Vec { + pub fn get_emission(netuid: NetUid) -> Vec { Emission::::get(netuid) } - pub fn get_consensus(netuid: u16) -> Vec { + pub fn get_consensus(netuid: NetUid) -> Vec { Consensus::::get(netuid) } - pub fn get_incentive(netuid: u16) -> Vec { + pub fn get_incentive(netuid: NetUid) -> Vec { Incentive::::get(netuid) } - pub fn get_dividends(netuid: u16) -> Vec { + pub fn get_dividends(netuid: NetUid) -> Vec { Dividends::::get(netuid) } - pub fn get_last_update(netuid: u16) -> Vec { + pub fn get_last_update(netuid: NetUid) -> Vec { LastUpdate::::get(netuid) } - pub fn get_pruning_score(netuid: u16) -> Vec { + pub fn get_pruning_score(netuid: NetUid) -> Vec { PruningScores::::get(netuid) } - pub fn get_validator_trust(netuid: u16) -> Vec { + pub fn get_validator_trust(netuid: NetUid) -> Vec { ValidatorTrust::::get(netuid) } - pub fn get_validator_permit(netuid: u16) -> Vec { + pub fn get_validator_permit(netuid: NetUid) -> Vec { ValidatorPermit::::get(netuid) } // ================================== // ==== YumaConsensus UID params ==== // ================================== - pub fn set_last_update_for_uid(netuid: u16, uid: u16, last_update: u64) { + pub fn set_last_update_for_uid(netuid: NetUid, uid: u16, last_update: u64) { let mut updated_last_update_vec = Self::get_last_update(netuid); let Some(updated_last_update) = updated_last_update_vec.get_mut(uid as usize) else { return; @@ -124,7 +128,7 @@ impl Pallet { *updated_last_update = last_update; LastUpdate::::insert(netuid, updated_last_update_vec); } - pub fn set_active_for_uid(netuid: u16, uid: u16, active: bool) { + pub fn set_active_for_uid(netuid: NetUid, uid: u16, active: bool) { let mut updated_active_vec = Self::get_active(netuid); let Some(updated_active) = updated_active_vec.get_mut(uid as usize) else { return; @@ -132,7 +136,7 @@ impl Pallet { *updated_active = active; Active::::insert(netuid, updated_active_vec); } - pub fn set_pruning_score_for_uid(netuid: u16, uid: u16, pruning_score: u16) { + pub fn set_pruning_score_for_uid(netuid: NetUid, uid: u16, pruning_score: u16) { log::debug!("netuid = {:?}", netuid); log::debug!( "SubnetworkN::::get( netuid ) = {:?}", @@ -146,7 +150,7 @@ impl Pallet { } }); } - pub fn set_validator_permit_for_uid(netuid: u16, uid: u16, validator_permit: bool) { + pub fn set_validator_permit_for_uid(netuid: NetUid, uid: u16, validator_permit: bool) { let mut updated_validator_permits = Self::get_validator_permit(netuid); let Some(updated_validator_permit) = updated_validator_permits.get_mut(uid as usize) else { return; @@ -159,47 +163,47 @@ impl Pallet { Self::deposit_event(Event::StakeThresholdSet(min_stake)); } - pub fn get_rank_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_rank_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = Rank::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_trust_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_trust_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = Trust::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_emission_for_uid(netuid: u16, uid: u16) -> u64 { + pub fn get_emission_for_uid(netuid: NetUid, uid: u16) -> u64 { let vec = Emission::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_active_for_uid(netuid: u16, uid: u16) -> bool { + pub fn get_active_for_uid(netuid: NetUid, uid: u16) -> bool { let vec = Active::::get(netuid); vec.get(uid as usize).copied().unwrap_or(false) } - pub fn get_consensus_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_consensus_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = Consensus::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_incentive_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_incentive_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = Incentive::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_dividends_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_dividends_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = Dividends::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_last_update_for_uid(netuid: u16, uid: u16) -> u64 { + pub fn get_last_update_for_uid(netuid: NetUid, uid: u16) -> u64 { let vec = LastUpdate::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_pruning_score_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_pruning_score_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = PruningScores::::get(netuid); vec.get(uid as usize).copied().unwrap_or(u16::MAX) } - pub fn get_validator_trust_for_uid(netuid: u16, uid: u16) -> u16 { + pub fn get_validator_trust_for_uid(netuid: NetUid, uid: u16) -> u16 { let vec = ValidatorTrust::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_validator_permit_for_uid(netuid: u16, uid: u16) -> bool { + pub fn get_validator_permit_for_uid(netuid: NetUid, uid: u16) -> bool { let vec = ValidatorPermit::::get(netuid); vec.get(uid as usize).copied().unwrap_or(false) } @@ -210,37 +214,37 @@ impl Pallet { // ============================ // ==== Subnetwork Getters ==== // ============================ - pub fn get_tempo(netuid: u16) -> u16 { + pub fn get_tempo(netuid: NetUid) -> u16 { Tempo::::get(netuid) } - pub fn get_pending_emission(netuid: u16) -> u64 { + pub fn get_pending_emission(netuid: NetUid) -> u64 { PendingEmission::::get(netuid) } - pub fn get_last_adjustment_block(netuid: u16) -> u64 { + pub fn get_last_adjustment_block(netuid: NetUid) -> u64 { LastAdjustmentBlock::::get(netuid) } - pub fn get_blocks_since_last_step(netuid: u16) -> u64 { + pub fn get_blocks_since_last_step(netuid: NetUid) -> u64 { BlocksSinceLastStep::::get(netuid) } - pub fn get_difficulty(netuid: u16) -> U256 { + pub fn get_difficulty(netuid: NetUid) -> U256 { U256::from(Self::get_difficulty_as_u64(netuid)) } - pub fn get_registrations_this_block(netuid: u16) -> u16 { + pub fn get_registrations_this_block(netuid: NetUid) -> u16 { RegistrationsThisBlock::::get(netuid) } - pub fn get_last_mechanism_step_block(netuid: u16) -> u64 { + pub fn get_last_mechanism_step_block(netuid: NetUid) -> u64 { LastMechansimStepBlock::::get(netuid) } - pub fn get_registrations_this_interval(netuid: u16) -> u16 { + pub fn get_registrations_this_interval(netuid: NetUid) -> u16 { RegistrationsThisInterval::::get(netuid) } - pub fn get_pow_registrations_this_interval(netuid: u16) -> u16 { + pub fn get_pow_registrations_this_interval(netuid: NetUid) -> u16 { POWRegistrationsThisInterval::::get(netuid) } - pub fn get_burn_registrations_this_interval(netuid: u16) -> u16 { + pub fn get_burn_registrations_this_interval(netuid: NetUid) -> u16 { BurnRegistrationsThisInterval::::get(netuid) } - pub fn get_neuron_block_at_registration(netuid: u16, neuron_uid: u16) -> u64 { + pub fn get_neuron_block_at_registration(netuid: NetUid, neuron_uid: u16) -> u64 { BlockAtRegistration::::get(netuid, neuron_uid) } @@ -273,10 +277,10 @@ impl Pallet { TotalIssuance::::put(TotalIssuance::::get().saturating_add(amount)); } - pub fn set_subnet_locked_balance(netuid: u16, amount: u64) { + pub fn set_subnet_locked_balance(netuid: NetUid, amount: u64) { SubnetLocked::::insert(netuid, amount); } - pub fn get_subnet_locked_balance(netuid: u16) -> u64 { + pub fn get_subnet_locked_balance(netuid: NetUid) -> u64 { SubnetLocked::::get(netuid) } pub fn get_total_subnet_locked() -> u64 { @@ -352,42 +356,42 @@ impl Pallet { MaxChildkeyTake::::get() } - pub fn get_serving_rate_limit(netuid: u16) -> u64 { + pub fn get_serving_rate_limit(netuid: NetUid) -> u64 { ServingRateLimit::::get(netuid) } - pub fn set_serving_rate_limit(netuid: u16, serving_rate_limit: u64) { + pub fn set_serving_rate_limit(netuid: NetUid, serving_rate_limit: u64) { ServingRateLimit::::insert(netuid, serving_rate_limit); Self::deposit_event(Event::ServingRateLimitSet(netuid, serving_rate_limit)); } - pub fn get_min_difficulty(netuid: u16) -> u64 { + pub fn get_min_difficulty(netuid: NetUid) -> u64 { MinDifficulty::::get(netuid) } - pub fn set_min_difficulty(netuid: u16, min_difficulty: u64) { + pub fn set_min_difficulty(netuid: NetUid, min_difficulty: u64) { MinDifficulty::::insert(netuid, min_difficulty); Self::deposit_event(Event::MinDifficultySet(netuid, min_difficulty)); } - pub fn get_max_difficulty(netuid: u16) -> u64 { + pub fn get_max_difficulty(netuid: NetUid) -> u64 { MaxDifficulty::::get(netuid) } - pub fn set_max_difficulty(netuid: u16, max_difficulty: u64) { + pub fn set_max_difficulty(netuid: NetUid, max_difficulty: u64) { MaxDifficulty::::insert(netuid, max_difficulty); Self::deposit_event(Event::MaxDifficultySet(netuid, max_difficulty)); } - pub fn get_weights_version_key(netuid: u16) -> u64 { + pub fn get_weights_version_key(netuid: NetUid) -> u64 { WeightsVersionKey::::get(netuid) } - pub fn set_weights_version_key(netuid: u16, weights_version_key: u64) { + pub fn set_weights_version_key(netuid: NetUid, weights_version_key: u64) { WeightsVersionKey::::insert(netuid, weights_version_key); Self::deposit_event(Event::WeightsVersionKeySet(netuid, weights_version_key)); } - pub fn get_weights_set_rate_limit(netuid: u16) -> u64 { + pub fn get_weights_set_rate_limit(netuid: NetUid) -> u64 { WeightsSetRateLimit::::get(netuid) } - pub fn set_weights_set_rate_limit(netuid: u16, weights_set_rate_limit: u64) { + pub fn set_weights_set_rate_limit(netuid: NetUid, weights_set_rate_limit: u64) { WeightsSetRateLimit::::insert(netuid, weights_set_rate_limit); Self::deposit_event(Event::WeightsSetRateLimitSet( netuid, @@ -395,126 +399,126 @@ impl Pallet { )); } - pub fn get_adjustment_interval(netuid: u16) -> u16 { + pub fn get_adjustment_interval(netuid: NetUid) -> u16 { AdjustmentInterval::::get(netuid) } - pub fn set_adjustment_interval(netuid: u16, adjustment_interval: u16) { + pub fn set_adjustment_interval(netuid: NetUid, adjustment_interval: u16) { AdjustmentInterval::::insert(netuid, adjustment_interval); Self::deposit_event(Event::AdjustmentIntervalSet(netuid, adjustment_interval)); } - pub fn get_adjustment_alpha(netuid: u16) -> u64 { + pub fn get_adjustment_alpha(netuid: NetUid) -> u64 { AdjustmentAlpha::::get(netuid) } - pub fn set_adjustment_alpha(netuid: u16, adjustment_alpha: u64) { + pub fn set_adjustment_alpha(netuid: NetUid, adjustment_alpha: u64) { AdjustmentAlpha::::insert(netuid, adjustment_alpha); Self::deposit_event(Event::AdjustmentAlphaSet(netuid, adjustment_alpha)); } - pub fn set_validator_prune_len(netuid: u16, validator_prune_len: u64) { + pub fn set_validator_prune_len(netuid: NetUid, validator_prune_len: u64) { ValidatorPruneLen::::insert(netuid, validator_prune_len); Self::deposit_event(Event::ValidatorPruneLenSet(netuid, validator_prune_len)); } - pub fn get_scaling_law_power(netuid: u16) -> u16 { + pub fn get_scaling_law_power(netuid: NetUid) -> u16 { ScalingLawPower::::get(netuid) } - pub fn set_scaling_law_power(netuid: u16, scaling_law_power: u16) { + pub fn set_scaling_law_power(netuid: NetUid, scaling_law_power: u16) { ScalingLawPower::::insert(netuid, scaling_law_power); Self::deposit_event(Event::ScalingLawPowerSet(netuid, scaling_law_power)); } - pub fn get_max_weight_limit(netuid: u16) -> u16 { + pub fn get_max_weight_limit(netuid: NetUid) -> u16 { MaxWeightsLimit::::get(netuid) } - pub fn set_max_weight_limit(netuid: u16, max_weight_limit: u16) { + pub fn set_max_weight_limit(netuid: NetUid, max_weight_limit: u16) { MaxWeightsLimit::::insert(netuid, max_weight_limit); Self::deposit_event(Event::MaxWeightLimitSet(netuid, max_weight_limit)); } - pub fn get_immunity_period(netuid: u16) -> u16 { + pub fn get_immunity_period(netuid: NetUid) -> u16 { ImmunityPeriod::::get(netuid) } - pub fn set_immunity_period(netuid: u16, immunity_period: u16) { + pub fn set_immunity_period(netuid: NetUid, immunity_period: u16) { ImmunityPeriod::::insert(netuid, immunity_period); Self::deposit_event(Event::ImmunityPeriodSet(netuid, immunity_period)); } /// Check if a neuron is in immunity based on the current block - pub fn get_neuron_is_immune(netuid: u16, uid: u16) -> bool { + pub fn get_neuron_is_immune(netuid: NetUid, uid: u16) -> bool { let registered_at = Self::get_neuron_block_at_registration(netuid, uid); let current_block = Self::get_current_block_as_u64(); let immunity_period = Self::get_immunity_period(netuid); current_block.saturating_sub(registered_at) < u64::from(immunity_period) } - pub fn get_min_allowed_weights(netuid: u16) -> u16 { + pub fn get_min_allowed_weights(netuid: NetUid) -> u16 { MinAllowedWeights::::get(netuid) } - pub fn set_min_allowed_weights(netuid: u16, min_allowed_weights: u16) { + pub fn set_min_allowed_weights(netuid: NetUid, min_allowed_weights: u16) { MinAllowedWeights::::insert(netuid, min_allowed_weights); Self::deposit_event(Event::MinAllowedWeightSet(netuid, min_allowed_weights)); } - pub fn get_max_allowed_uids(netuid: u16) -> u16 { + pub fn get_max_allowed_uids(netuid: NetUid) -> u16 { MaxAllowedUids::::get(netuid) } - pub fn set_max_allowed_uids(netuid: u16, max_allowed: u16) { + pub fn set_max_allowed_uids(netuid: NetUid, max_allowed: u16) { MaxAllowedUids::::insert(netuid, max_allowed); Self::deposit_event(Event::MaxAllowedUidsSet(netuid, max_allowed)); } - pub fn get_kappa(netuid: u16) -> u16 { + pub fn get_kappa(netuid: NetUid) -> u16 { Kappa::::get(netuid) } - pub fn set_kappa(netuid: u16, kappa: u16) { + pub fn set_kappa(netuid: NetUid, kappa: u16) { Kappa::::insert(netuid, kappa); Self::deposit_event(Event::KappaSet(netuid, kappa)); } - pub fn get_commit_reveal_weights_enabled(netuid: u16) -> bool { + pub fn get_commit_reveal_weights_enabled(netuid: NetUid) -> bool { CommitRevealWeightsEnabled::::get(netuid) } - pub fn set_commit_reveal_weights_enabled(netuid: u16, enabled: bool) { + pub fn set_commit_reveal_weights_enabled(netuid: NetUid, enabled: bool) { CommitRevealWeightsEnabled::::set(netuid, enabled); Self::deposit_event(Event::CommitRevealEnabled(netuid, enabled)); } - pub fn get_rho(netuid: u16) -> u16 { + pub fn get_rho(netuid: NetUid) -> u16 { Rho::::get(netuid) } - pub fn set_rho(netuid: u16, rho: u16) { + pub fn set_rho(netuid: NetUid, rho: u16) { Rho::::insert(netuid, rho); } - pub fn get_activity_cutoff(netuid: u16) -> u16 { + pub fn get_activity_cutoff(netuid: NetUid) -> u16 { ActivityCutoff::::get(netuid) } - pub fn set_activity_cutoff(netuid: u16, activity_cutoff: u16) { + pub fn set_activity_cutoff(netuid: NetUid, activity_cutoff: u16) { ActivityCutoff::::insert(netuid, activity_cutoff); Self::deposit_event(Event::ActivityCutoffSet(netuid, activity_cutoff)); } // Registration Toggle utils - pub fn get_network_registration_allowed(netuid: u16) -> bool { + pub fn get_network_registration_allowed(netuid: NetUid) -> bool { NetworkRegistrationAllowed::::get(netuid) } - pub fn set_network_registration_allowed(netuid: u16, registration_allowed: bool) { + pub fn set_network_registration_allowed(netuid: NetUid, registration_allowed: bool) { NetworkRegistrationAllowed::::insert(netuid, registration_allowed); Self::deposit_event(Event::RegistrationAllowed(netuid, registration_allowed)); } - pub fn get_network_pow_registration_allowed(netuid: u16) -> bool { + pub fn get_network_pow_registration_allowed(netuid: NetUid) -> bool { NetworkPowRegistrationAllowed::::get(netuid) } - pub fn set_network_pow_registration_allowed(netuid: u16, registration_allowed: bool) { + pub fn set_network_pow_registration_allowed(netuid: NetUid, registration_allowed: bool) { NetworkPowRegistrationAllowed::::insert(netuid, registration_allowed); Self::deposit_event(Event::PowRegistrationAllowed(netuid, registration_allowed)); } - pub fn get_target_registrations_per_interval(netuid: u16) -> u16 { + pub fn get_target_registrations_per_interval(netuid: NetUid) -> u16 { TargetRegistrationsPerInterval::::get(netuid) } pub fn set_target_registrations_per_interval( - netuid: u16, + netuid: NetUid, target_registrations_per_interval: u16, ) { TargetRegistrationsPerInterval::::insert(netuid, target_registrations_per_interval); @@ -524,41 +528,41 @@ impl Pallet { )); } - pub fn get_burn_as_u64(netuid: u16) -> u64 { + pub fn get_burn_as_u64(netuid: NetUid) -> u64 { Burn::::get(netuid) } - pub fn set_burn(netuid: u16, burn: u64) { + pub fn set_burn(netuid: NetUid, burn: u64) { Burn::::insert(netuid, burn); } - pub fn get_min_burn_as_u64(netuid: u16) -> u64 { + pub fn get_min_burn_as_u64(netuid: NetUid) -> u64 { MinBurn::::get(netuid) } - pub fn set_min_burn(netuid: u16, min_burn: u64) { + pub fn set_min_burn(netuid: NetUid, min_burn: u64) { MinBurn::::insert(netuid, min_burn); Self::deposit_event(Event::MinBurnSet(netuid, min_burn)); } - pub fn get_max_burn_as_u64(netuid: u16) -> u64 { + pub fn get_max_burn_as_u64(netuid: NetUid) -> u64 { MaxBurn::::get(netuid) } - pub fn set_max_burn(netuid: u16, max_burn: u64) { + pub fn set_max_burn(netuid: NetUid, max_burn: u64) { MaxBurn::::insert(netuid, max_burn); Self::deposit_event(Event::MaxBurnSet(netuid, max_burn)); } - pub fn get_difficulty_as_u64(netuid: u16) -> u64 { + pub fn get_difficulty_as_u64(netuid: NetUid) -> u64 { Difficulty::::get(netuid) } - pub fn set_difficulty(netuid: u16, difficulty: u64) { + pub fn set_difficulty(netuid: NetUid, difficulty: u64) { Difficulty::::insert(netuid, difficulty); Self::deposit_event(Event::DifficultySet(netuid, difficulty)); } - pub fn get_max_allowed_validators(netuid: u16) -> u16 { + pub fn get_max_allowed_validators(netuid: NetUid) -> u16 { MaxAllowedValidators::::get(netuid) } - pub fn set_max_allowed_validators(netuid: u16, max_allowed_validators: u16) { + pub fn set_max_allowed_validators(netuid: NetUid, max_allowed_validators: u16) { MaxAllowedValidators::::insert(netuid, max_allowed_validators); Self::deposit_event(Event::MaxAllowedValidatorsSet( netuid, @@ -566,34 +570,34 @@ impl Pallet { )); } - pub fn get_bonds_moving_average(netuid: u16) -> u64 { + pub fn get_bonds_moving_average(netuid: NetUid) -> u64 { BondsMovingAverage::::get(netuid) } - pub fn set_bonds_moving_average(netuid: u16, bonds_moving_average: u64) { + pub fn set_bonds_moving_average(netuid: NetUid, bonds_moving_average: u64) { BondsMovingAverage::::insert(netuid, bonds_moving_average); Self::deposit_event(Event::BondsMovingAverageSet(netuid, bonds_moving_average)); } - pub fn get_bonds_penalty(netuid: u16) -> u16 { + pub fn get_bonds_penalty(netuid: NetUid) -> u16 { BondsPenalty::::get(netuid) } - pub fn set_bonds_penalty(netuid: u16, bonds_penalty: u16) { + pub fn set_bonds_penalty(netuid: NetUid, bonds_penalty: u16) { BondsPenalty::::insert(netuid, bonds_penalty); Self::deposit_event(Event::BondsPenaltySet(netuid, bonds_penalty)); } - pub fn get_bonds_reset(netuid: u16) -> bool { + pub fn get_bonds_reset(netuid: NetUid) -> bool { BondsResetOn::::get(netuid) } - pub fn set_bonds_reset(netuid: u16, bonds_reset: bool) { + pub fn set_bonds_reset(netuid: NetUid, bonds_reset: bool) { BondsResetOn::::insert(netuid, bonds_reset); Self::deposit_event(Event::BondsResetOnSet(netuid, bonds_reset)); } - pub fn get_max_registrations_per_block(netuid: u16) -> u16 { + pub fn get_max_registrations_per_block(netuid: NetUid) -> u16 { MaxRegistrationsPerBlock::::get(netuid) } - pub fn set_max_registrations_per_block(netuid: u16, max_registrations_per_block: u16) { + pub fn set_max_registrations_per_block(netuid: NetUid, max_registrations_per_block: u16) { MaxRegistrationsPerBlock::::insert(netuid, max_registrations_per_block); Self::deposit_event(Event::MaxRegistrationsPerBlockSet( netuid, @@ -601,7 +605,7 @@ impl Pallet { )); } - pub fn get_subnet_owner(netuid: u16) -> T::AccountId { + pub fn get_subnet_owner(netuid: NetUid) -> T::AccountId { SubnetOwner::::get(netuid) } pub fn get_subnet_owner_cut() -> u16 { @@ -627,14 +631,14 @@ impl Pallet { TotalIssuance::::put(total_issuance); } - pub fn get_rao_recycled(netuid: u16) -> u64 { + pub fn get_rao_recycled(netuid: NetUid) -> u64 { RAORecycledForRegistration::::get(netuid) } - pub fn set_rao_recycled(netuid: u16, rao_recycled: u64) { + pub fn set_rao_recycled(netuid: NetUid, rao_recycled: u64) { RAORecycledForRegistration::::insert(netuid, rao_recycled); Self::deposit_event(Event::RAORecycledForRegistrationSet(netuid, rao_recycled)); } - pub fn increase_rao_recycled(netuid: u16, inc_rao_recycled: u64) { + pub fn increase_rao_recycled(netuid: NetUid, inc_rao_recycled: u64) { let curr_rao_recycled = Self::get_rao_recycled(netuid); let rao_recycled = curr_rao_recycled.saturating_add(inc_rao_recycled); Self::set_rao_recycled(netuid, rao_recycled); @@ -675,17 +679,17 @@ impl Pallet { T::KeySwapCost::get() } - pub fn get_alpha_values(netuid: u16) -> (u16, u16) { + pub fn get_alpha_values(netuid: NetUid) -> (u16, u16) { AlphaValues::::get(netuid) } - pub fn set_alpha_values_32(netuid: u16, low: I32F32, high: I32F32) { + pub fn set_alpha_values_32(netuid: NetUid, low: I32F32, high: I32F32) { let low = (low.saturating_mul(I32F32::saturating_from_num(u16::MAX))).to_num::(); let high = (high.saturating_mul(I32F32::saturating_from_num(u16::MAX))).to_num::(); AlphaValues::::insert(netuid, (low, high)); } - pub fn get_alpha_values_32(netuid: u16) -> (I32F32, I32F32) { + pub fn get_alpha_values_32(netuid: NetUid) -> (I32F32, I32F32) { let (alpha_low, alpha_high): (u16, u16) = AlphaValues::::get(netuid); let converted_low = I32F32::saturating_from_num(alpha_low).safe_div(I32F32::saturating_from_num(u16::MAX)); @@ -695,30 +699,38 @@ impl Pallet { (converted_low, converted_high) } - pub fn set_alpha_sigmoid_steepness(netuid: u16, steepness: u16) { + pub fn set_alpha_sigmoid_steepness(netuid: NetUid, steepness: i16) { AlphaSigmoidSteepness::::insert(netuid, steepness); } - pub fn get_alpha_sigmoid_steepness(netuid: u16) -> I32F32 { + pub fn get_alpha_sigmoid_steepness(netuid: NetUid) -> I32F32 { let alpha = AlphaSigmoidSteepness::::get(netuid); I32F32::saturating_from_num(alpha) } - pub fn set_liquid_alpha_enabled(netuid: u16, enabled: bool) { + pub fn set_liquid_alpha_enabled(netuid: NetUid, enabled: bool) { LiquidAlphaOn::::set(netuid, enabled); } - pub fn get_liquid_alpha_enabled(netuid: u16) -> bool { + pub fn get_liquid_alpha_enabled(netuid: NetUid) -> bool { LiquidAlphaOn::::get(netuid) } - pub fn set_yuma3_enabled(netuid: u16, enabled: bool) { + pub fn set_yuma3_enabled(netuid: NetUid, enabled: bool) { Yuma3On::::set(netuid, enabled); } - pub fn get_yuma3_enabled(netuid: u16) -> bool { + pub fn get_yuma3_enabled(netuid: NetUid) -> bool { Yuma3On::::get(netuid) } + pub fn get_subtoken_enabled(netuid: NetUid) -> bool { + SubtokenEnabled::::get(netuid) + } + + pub fn get_transfer_toggle(netuid: NetUid) -> bool { + TransferToggle::::get(netuid) + } + /// Set the duration for coldkey swap /// /// # Arguments @@ -760,13 +772,13 @@ impl Pallet { /// /// * Update the SubnetOwnerHotkey storage. /// * Emits a SubnetOwnerHotkeySet event. - pub fn set_subnet_owner_hotkey(netuid: u16, hotkey: &T::AccountId) { + pub fn set_subnet_owner_hotkey(netuid: NetUid, hotkey: &T::AccountId) { SubnetOwnerHotkey::::insert(netuid, hotkey.clone()); Self::deposit_event(Event::SubnetOwnerHotkeySet(netuid, hotkey.clone())); } // Get the uid of the Owner Hotkey for a subnet. - pub fn get_owner_uid(netuid: u16) -> Option { + pub fn get_owner_uid(netuid: NetUid) -> Option { match SubnetOwnerHotkey::::try_get(netuid) { Ok(owner_hotkey) => Uids::::get(netuid, &owner_hotkey), Err(_) => None, diff --git a/pallets/subtensor/src/utils/rate_limiting.rs b/pallets/subtensor/src/utils/rate_limiting.rs index 7edaebc98a..eeb5b96ddb 100644 --- a/pallets/subtensor/src/utils/rate_limiting.rs +++ b/pallets/subtensor/src/utils/rate_limiting.rs @@ -1,3 +1,5 @@ +use subtensor_runtime_common::NetUid; + use super::*; /// Enum representing different types of transactions @@ -54,7 +56,7 @@ impl Pallet { } } - pub fn get_rate_limit_on_subnet(tx_type: &TransactionType, netuid: u16) -> u64 { + pub fn get_rate_limit_on_subnet(tx_type: &TransactionType, netuid: NetUid) -> u64 { #[allow(clippy::match_single_binding)] match tx_type { TransactionType::SetWeightsVersionKey => (Tempo::::get(netuid) as u64) @@ -82,7 +84,7 @@ impl Pallet { pub fn passes_rate_limit_on_subnet( tx_type: &TransactionType, hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, ) -> bool { let block: u64 = Self::get_current_block_as_u64(); let limit: u64 = Self::get_rate_limit_on_subnet(tx_type, netuid); @@ -95,14 +97,14 @@ impl Pallet { pub fn get_last_transaction_block(key: &T::AccountId, tx_type: &TransactionType) -> u64 { match tx_type { TransactionType::RegisterNetwork => Self::get_network_last_lock_block(), - _ => Self::get_last_transaction_block_on_subnet(key, 0, tx_type), + _ => Self::get_last_transaction_block_on_subnet(key, NetUid::ROOT, tx_type), } } /// Get the block number of the last transaction for a specific hotkey, network, and transaction type pub fn get_last_transaction_block_on_subnet( hotkey: &T::AccountId, - netuid: u16, + netuid: NetUid, tx_type: &TransactionType, ) -> u64 { match tx_type { @@ -121,14 +123,14 @@ impl Pallet { pub fn set_last_transaction_block(key: &T::AccountId, tx_type: &TransactionType, block: u64) { match tx_type { TransactionType::RegisterNetwork => Self::set_network_last_lock_block(block), - _ => Self::set_last_transaction_block_on_subnet(key, 0, tx_type, block), + _ => Self::set_last_transaction_block_on_subnet(key, NetUid::ROOT, tx_type, block), } } /// Set the block number of the last transaction for a specific hotkey, network, and transaction type pub fn set_last_transaction_block_on_subnet( key: &T::AccountId, - netuid: u16, + netuid: NetUid, tx_type: &TransactionType, block: u64, ) { diff --git a/pallets/subtensor/src/utils/try_state.rs b/pallets/subtensor/src/utils/try_state.rs index 1fb75fd4bb..f5e8d5ffb9 100644 --- a/pallets/subtensor/src/utils/try_state.rs +++ b/pallets/subtensor/src/utils/try_state.rs @@ -41,7 +41,7 @@ impl Pallet { let total_staked = SubnetTAO::::iter().fold(0u64, |acc, (netuid, stake)| { let acc = acc.saturating_add(stake); - if netuid == Self::get_root_netuid() { + if netuid.is_root() { // root network doesn't have initial pool TAO acc } else { diff --git a/pallets/swap-interface/Cargo.toml b/pallets/swap-interface/Cargo.toml new file mode 100644 index 0000000000..5af146881c --- /dev/null +++ b/pallets/swap-interface/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "subtensor-swap-interface" +version = "0.1.0" +edition.workspace = true + +[dependencies] +codec = { workspace = true } +frame-support = { workspace = true } +scale-info = { workspace = true } +substrate-fixed = { workspace = true } +subtensor-runtime-common = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "scale-info/std", + "substrate-fixed/std", + "subtensor-runtime-common/std", +] diff --git a/pallets/swap-interface/src/lib.rs b/pallets/swap-interface/src/lib.rs new file mode 100644 index 0000000000..10f3cb0fb2 --- /dev/null +++ b/pallets/swap-interface/src/lib.rs @@ -0,0 +1,51 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::pallet_prelude::*; +use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OrderType { + Sell, + Buy, +} + +pub trait SwapHandler { + fn swap( + netuid: NetUid, + order_t: OrderType, + amount: u64, + price_limit: u64, + should_rollback: bool, + ) -> Result; + fn sim_swap( + netuid: NetUid, + order_t: OrderType, + amount: u64, + ) -> Result; + fn approx_fee_amount(netuid: NetUid, amount: u64) -> u64; + fn current_alpha_price(netuid: NetUid) -> U96F32; + fn max_price() -> u64; + fn min_price() -> u64; + fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64); + fn is_user_liquidity_enabled(netuid: NetUid) -> bool; +} + +#[derive(Debug, PartialEq)] +pub struct SwapResult { + pub amount_paid_in: u64, + pub amount_paid_out: u64, + pub fee_paid: u64, + // For calculation of new tao/alpha reserves + pub tao_reserve_delta: i64, + pub alpha_reserve_delta: i64, +} + +#[derive(Debug, PartialEq)] +pub struct UpdateLiquidityResult { + pub tao: u64, + pub alpha: u64, + pub fee_tao: u64, + pub fee_alpha: u64, + pub removed: bool, +} diff --git a/pallets/swap/Cargo.toml b/pallets/swap/Cargo.toml new file mode 100644 index 0000000000..7cf8e98191 --- /dev/null +++ b/pallets/swap/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "pallet-subtensor-swap" +version = "0.1.0" +edition = { workspace = true } + +[dependencies] +alloy-primitives = { workspace = true } +approx = { workspace = true } +codec = { workspace = true } +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } +safe-math = { workspace = true } +scale-info = { workspace = true } +serde = { workspace = true, optional = true } +sp-arithmetic = { workspace = true } +sp-core = { workspace = true } +sp-io = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } +substrate-fixed = { workspace = true } + +pallet-subtensor-swap-runtime-api = { workspace = true } +subtensor-macros = { workspace = true } +subtensor-runtime-common = {workspace = true} +subtensor-swap-interface = { workspace = true } + +[dev-dependencies] +sp-tracing = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["std"] +std = [ + "alloy-primitives/std", + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-subtensor-swap-runtime-api/std", + "safe-math/std", + "scale-info/std", + "serde/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-tracing/std", + "sp-std/std", + "substrate-fixed/std", + "subtensor-runtime-common/std", + "subtensor-swap-interface/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/pallets/swap/rpc/Cargo.toml b/pallets/swap/rpc/Cargo.toml new file mode 100644 index 0000000000..cc5fbc9067 --- /dev/null +++ b/pallets/swap/rpc/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "pallet-subtensor-swap-rpc" +version = "1.0.0" +description = "RPC interface for the Swap pallet" +edition = { workspace = true } + +[dependencies] +codec = { workspace = true } +jsonrpsee = { workspace = true } +sp-api = { workspace = true } +sp-blockchain = { workspace = true } +sp-runtime = { workspace = true } +pallet-subtensor-swap-runtime-api = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "pallet-subtensor-swap-runtime-api/std", + "sp-api/std", + "sp-runtime/std", +] diff --git a/pallets/swap/rpc/src/lib.rs b/pallets/swap/rpc/src/lib.rs new file mode 100644 index 0000000000..e8fa85493d --- /dev/null +++ b/pallets/swap/rpc/src/lib.rs @@ -0,0 +1,78 @@ +//! RPC interface for the Swap pallet + +use std::sync::Arc; + +use jsonrpsee::{ + core::RpcResult, + proc_macros::rpc, + types::{ErrorObjectOwned, error::ErrorObject}, +}; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::traits::Block as BlockT; + +pub use pallet_subtensor_swap_runtime_api::SwapRuntimeApi; + +#[rpc(client, server)] +pub trait SwapRpcApi { + #[method(name = "swap_currentAlphaPrice")] + fn current_alpha_price(&self, netuid: u16, at: Option) -> RpcResult; +} + +/// Error type of this RPC api. +pub enum Error { + /// The call to runtime failed. + RuntimeError(String), +} + +impl From for ErrorObjectOwned { + fn from(e: Error) -> Self { + match e { + Error::RuntimeError(e) => ErrorObject::owned(1, e, None::<()>), + } + } +} + +impl From for i32 { + fn from(e: Error) -> i32 { + match e { + Error::RuntimeError(_) => 1, + } + } +} + +/// Swap RPC implementation. +pub struct Swap { + client: Arc, + _marker: std::marker::PhantomData, +} + +impl Swap { + /// Create new `Swap` instance with the given reference to the client. + pub fn new(client: Arc) -> Self { + Self { + client, + _marker: Default::default(), + } + } +} + +impl SwapRpcApiServer<::Hash> for Swap +where + Block: BlockT, + C: ProvideRuntimeApi + HeaderBackend + Send + Sync + 'static, + C::Api: SwapRuntimeApi, +{ + fn current_alpha_price( + &self, + netuid: u16, + at: Option<::Hash>, + ) -> RpcResult { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + api.current_alpha_price(at, netuid).map_err(|e| { + Error::RuntimeError(format!("Unable to get current alpha price: {:?}", e)).into() + }) + } +} diff --git a/pallets/swap/runtime-api/Cargo.toml b/pallets/swap/runtime-api/Cargo.toml new file mode 100644 index 0000000000..d871adb651 --- /dev/null +++ b/pallets/swap/runtime-api/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "pallet-subtensor-swap-runtime-api" +version = "1.0.0" +description = "Runtime API for the Swap pallet" +edition = { workspace = true } + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +sp-api = { workspace = true } +sp-std = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "sp-api/std", + "sp-std/std", +] diff --git a/pallets/swap/runtime-api/src/lib.rs b/pallets/swap/runtime-api/src/lib.rs new file mode 100644 index 0000000000..5db91a5a26 --- /dev/null +++ b/pallets/swap/runtime-api/src/lib.rs @@ -0,0 +1,7 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +sp_api::decl_runtime_apis! { + pub trait SwapRuntimeApi { + fn current_alpha_price(netuid: u16) -> u64; + } +} diff --git a/pallets/swap/scripts/benchmark.sh b/pallets/swap/scripts/benchmark.sh new file mode 100755 index 0000000000..20feb6b270 --- /dev/null +++ b/pallets/swap/scripts/benchmark.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +cargo build --profile production --features runtime-benchmarks +./target/production/node-subtensor benchmark pallet \ + --chain=local \ + --pallet=pallet_subtensor_swap \ + --extrinsic="*" \ + --steps 50 \ + --repeat 20 \ + --output=pallets/swap/src/weights.rs \ + --template=./.maintain/frame-weight-template.hbs \ No newline at end of file diff --git a/pallets/swap/src/benchmarking.rs b/pallets/swap/src/benchmarking.rs new file mode 100644 index 0000000000..0d926a640f --- /dev/null +++ b/pallets/swap/src/benchmarking.rs @@ -0,0 +1,147 @@ +//! Benchmarking setup for pallet-subtensor-swap +#![allow(clippy::unwrap_used)] +#![allow(clippy::multiple_bound_locations)] + +use core::marker::PhantomData; + +use frame_benchmarking::v2::*; +use frame_support::traits::Get; +use frame_system::RawOrigin; +use substrate_fixed::types::{I64F64, U64F64}; +use subtensor_runtime_common::NetUid; + +use crate::{ + pallet::{ + AlphaSqrtPrice, Call, Config, CurrentLiquidity, CurrentTick, EnabledUserLiquidity, Pallet, + Positions, SwapV3Initialized, + }, + position::{Position, PositionId}, + tick::TickIndex, +}; + +#[benchmarks(where T: Config)] +mod benchmarks { + use super::*; + + #[benchmark] + fn set_fee_rate() { + let netuid = NetUid::from(1); + let rate: u16 = 100; // Some arbitrary fee rate value + + #[extrinsic_call] + set_fee_rate(RawOrigin::Root, netuid, rate); + } + + #[benchmark] + fn add_liquidity() { + let netuid = NetUid::from(1); + + if !SwapV3Initialized::::get(netuid) { + SwapV3Initialized::::insert(netuid, true); + AlphaSqrtPrice::::insert(netuid, U64F64::from_num(1)); + CurrentTick::::insert(netuid, TickIndex::new(0).unwrap()); + CurrentLiquidity::::insert(netuid, T::MinimumLiquidity::get()); + } + + let caller: T::AccountId = whitelisted_caller(); + let hotkey: T::AccountId = account("hotkey", 0, 0); + let tick_low = TickIndex::new_unchecked(-1000); + let tick_high = TickIndex::new_unchecked(1000); + + #[extrinsic_call] + add_liquidity( + RawOrigin::Signed(caller), + hotkey, + netuid, + tick_low, + tick_high, + 1000, + ); + } + + #[benchmark] + fn remove_liquidity() { + let netuid = NetUid::from(1); + + if !SwapV3Initialized::::get(netuid) { + SwapV3Initialized::::insert(netuid, true); + AlphaSqrtPrice::::insert(netuid, U64F64::from_num(1)); + CurrentTick::::insert(netuid, TickIndex::new(0).unwrap()); + CurrentLiquidity::::insert(netuid, T::MinimumLiquidity::get()); + } + + let caller: T::AccountId = whitelisted_caller(); + let hotkey: T::AccountId = account("hotkey", 0, 0); + let id = PositionId::from(1u128); + + Positions::::insert( + (netuid, caller.clone(), id), + Position { + id, + netuid, + tick_low: TickIndex::new(-10000).unwrap(), + tick_high: TickIndex::new(10000).unwrap(), + liquidity: 1000, + fees_tao: I64F64::from_num(0), + fees_alpha: I64F64::from_num(0), + _phantom: PhantomData, + }, + ); + + #[extrinsic_call] + remove_liquidity(RawOrigin::Signed(caller), hotkey, netuid.into(), id.into()); + } + + #[benchmark] + fn modify_position() { + let netuid = NetUid::from(1); + + if !SwapV3Initialized::::get(netuid) { + SwapV3Initialized::::insert(netuid, true); + AlphaSqrtPrice::::insert(netuid, U64F64::from_num(1)); + CurrentTick::::insert(netuid, TickIndex::new(0).unwrap()); + CurrentLiquidity::::insert(netuid, T::MinimumLiquidity::get()); + } + + let caller: T::AccountId = whitelisted_caller(); + let hotkey: T::AccountId = account("hotkey", 0, 0); + let id = PositionId::from(1u128); + + Positions::::insert( + (netuid, caller.clone(), id), + Position { + id, + netuid, + tick_low: TickIndex::new(-10000).unwrap(), + tick_high: TickIndex::new(10000).unwrap(), + liquidity: 10000, + fees_tao: I64F64::from_num(0), + fees_alpha: I64F64::from_num(0), + _phantom: PhantomData, + }, + ); + + #[extrinsic_call] + modify_position( + RawOrigin::Signed(caller), + hotkey, + netuid.into(), + id.into(), + -5000, + ); + } + + #[benchmark] + fn toggle_user_liquidity() { + let netuid = NetUid::from(101); + + assert!(!EnabledUserLiquidity::::get(netuid)); + + #[extrinsic_call] + toggle_user_liquidity(RawOrigin::Root, netuid.into(), true); + + assert!(EnabledUserLiquidity::::get(netuid)); + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/swap/src/lib.rs b/pallets/swap/src/lib.rs new file mode 100644 index 0000000000..b9d05bd435 --- /dev/null +++ b/pallets/swap/src/lib.rs @@ -0,0 +1,19 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use substrate_fixed::types::U64F64; +use subtensor_swap_interface::OrderType; + +pub mod pallet; +pub mod position; +pub mod tick; +pub mod weights; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + +#[cfg(test)] +pub(crate) mod mock; + +type SqrtPrice = U64F64; diff --git a/pallets/swap/src/mock.rs b/pallets/swap/src/mock.rs new file mode 100644 index 0000000000..36e8797031 --- /dev/null +++ b/pallets/swap/src/mock.rs @@ -0,0 +1,205 @@ +#![allow(clippy::unwrap_used)] + +use core::num::NonZeroU64; + +use frame_support::construct_runtime; +use frame_support::pallet_prelude::*; +use frame_support::{ + PalletId, parameter_types, + traits::{ConstU32, Everything}, +}; +use frame_system::{self as system}; +use sp_core::H256; +use sp_runtime::{ + BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, +}; +use subtensor_runtime_common::{BalanceOps, NetUid, SubnetInfo}; + +use crate::pallet::EnabledUserLiquidity; + +construct_runtime!( + pub enum Test { + System: frame_system = 0, + Swap: crate::pallet = 1, + } +); + +pub type Block = frame_system::mocking::MockBlock; +pub type AccountId = u32; +pub const OK_COLDKEY_ACCOUNT_ID: AccountId = 1; +pub const OK_HOTKEY_ACCOUNT_ID: AccountId = 1000; +pub const OK_COLDKEY_ACCOUNT_ID_2: AccountId = 2; +pub const OK_HOTKEY_ACCOUNT_ID_2: AccountId = 1001; +pub const OK_COLDKEY_ACCOUNT_ID_RICH: AccountId = 5; +pub const OK_HOTKEY_ACCOUNT_ID_RICH: AccountId = 1005; +pub const NOT_SUBNET_OWNER: AccountId = 666; +pub const NON_EXISTENT_NETUID: u16 = 999; +pub const WRAPPING_FEES_NETUID: u16 = 124; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + type Nonce = u64; + type Block = Block; + type RuntimeTask = (); + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); + type ExtensionsWeightInfo = (); +} + +parameter_types! { + pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap"); + pub const MaxFeeRate: u16 = 10000; // 15.26% + pub const MaxPositions: u32 = 100; + pub const MinimumLiquidity: u64 = 1_000; + pub const MinimumReserves: NonZeroU64 = NonZeroU64::new(1).unwrap(); +} + +// Mock implementor of SubnetInfo trait +pub struct MockLiquidityProvider; + +impl SubnetInfo for MockLiquidityProvider { + fn tao_reserve(netuid: NetUid) -> u64 { + match netuid.into() { + 123u16 => 10_000, + WRAPPING_FEES_NETUID => 100_000_000_000, + _ => 1_000_000_000_000, + } + } + + fn alpha_reserve(netuid: NetUid) -> u64 { + match netuid.into() { + 123u16 => 10_000, + WRAPPING_FEES_NETUID => 400_000_000_000, + _ => 4_000_000_000_000, + } + } + + fn exists(netuid: NetUid) -> bool { + netuid != NON_EXISTENT_NETUID.into() + } + + fn mechanism(netuid: NetUid) -> u16 { + if netuid == NetUid::from(0) { 0 } else { 1 } + } + + fn is_owner(account_id: &AccountId, _netuid: NetUid) -> bool { + *account_id != NOT_SUBNET_OWNER + } +} + +pub struct MockBalanceOps; + +impl BalanceOps for MockBalanceOps { + fn tao_balance(account_id: &AccountId) -> u64 { + match *account_id { + OK_COLDKEY_ACCOUNT_ID => 100_000_000_000_000, + OK_COLDKEY_ACCOUNT_ID_2 => 100_000_000_000_000, + OK_COLDKEY_ACCOUNT_ID_RICH => 900_000_000_000_000_000_u64, + _ => 1_000_000_000, + } + } + + fn alpha_balance( + _: NetUid, + coldkey_account_id: &AccountId, + hotkey_account_id: &AccountId, + ) -> u64 { + match (coldkey_account_id, hotkey_account_id) { + (&OK_COLDKEY_ACCOUNT_ID, &OK_HOTKEY_ACCOUNT_ID) => 100_000_000_000_000, + (&OK_COLDKEY_ACCOUNT_ID_2, &OK_HOTKEY_ACCOUNT_ID_2) => 100_000_000_000_000, + (&OK_COLDKEY_ACCOUNT_ID_RICH, &OK_HOTKEY_ACCOUNT_ID_RICH) => { + 900_000_000_000_000_000_u64 + } + _ => 1_000_000_000, + } + } + + fn increase_balance(_coldkey: &AccountId, _tao: u64) {} + + fn decrease_balance(_coldkey: &AccountId, tao: u64) -> Result { + Ok(tao) + } + + fn increase_stake( + _coldkey: &AccountId, + _hotkey: &AccountId, + _netuid: NetUid, + _alpha: u64, + ) -> Result<(), DispatchError> { + Ok(()) + } + + fn decrease_stake( + _coldkey: &AccountId, + _hotkey: &AccountId, + _netuid: NetUid, + alpha: u64, + ) -> Result { + Ok(alpha) + } + + fn increase_provided_tao_reserve(_netuid: NetUid, _tao: u64) {} + fn decrease_provided_tao_reserve(_netuid: NetUid, _tao: u64) {} + fn increase_provided_alpha_reserve(_netuid: NetUid, _alpha: u64) {} + fn decrease_provided_alpha_reserve(_netuid: NetUid, _alpha: u64) {} +} + +impl crate::pallet::Config for Test { + type RuntimeEvent = RuntimeEvent; + type SubnetInfo = MockLiquidityProvider; + type BalanceOps = MockBalanceOps; + type ProtocolId = SwapProtocolId; + type MaxFeeRate = MaxFeeRate; + type MaxPositions = MaxPositions; + type MinimumLiquidity = MinimumLiquidity; + type MinimumReserve = MinimumReserves; + type WeightInfo = (); +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let storage = system::GenesisConfig::::default() + .build_storage() + .unwrap(); + let mut ext = sp_io::TestExternalities::new(storage); + ext.execute_with(|| { + System::set_block_number(1); + + for netuid in 0u16..=100 { + // enable V3 for this range of netuids + EnabledUserLiquidity::::set(NetUid::from(netuid), true); + } + EnabledUserLiquidity::::set(NetUid::from(WRAPPING_FEES_NETUID), true); + }); + ext +} diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs new file mode 100644 index 0000000000..08cd2c4b74 --- /dev/null +++ b/pallets/swap/src/pallet/impls.rs @@ -0,0 +1,1212 @@ +use core::marker::PhantomData; +use core::ops::Neg; + +use frame_support::storage::{TransactionOutcome, transactional}; +use frame_support::{ensure, pallet_prelude::DispatchError, traits::Get}; +use safe_math::*; +use sp_arithmetic::helpers_128bit; +use sp_runtime::traits::AccountIdConversion; +use substrate_fixed::types::{I64F64, U64F64, U96F32}; +use subtensor_runtime_common::{BalanceOps, NetUid, SubnetInfo}; +use subtensor_swap_interface::{SwapHandler, SwapResult, UpdateLiquidityResult}; + +use super::pallet::*; +use crate::{ + OrderType, SqrtPrice, + position::{Position, PositionId}, + tick::{ActiveTickIndexManager, Tick, TickIndex}, +}; + +const MAX_SWAP_ITERATIONS: u16 = 1000; + +/// A struct representing a single swap step with all its parameters and state +struct SwapStep { + // Input parameters + netuid: NetUid, + order_type: OrderType, + + // Computed values + current_liquidity: U64F64, + possible_delta_in: u64, + + // Ticks and prices (current, limit, edge, target) + target_sqrt_price: SqrtPrice, + limit_sqrt_price: SqrtPrice, + current_sqrt_price: SqrtPrice, + edge_sqrt_price: SqrtPrice, + edge_tick: TickIndex, + + // Result values + action: SwapStepAction, + delta_in: u64, + final_price: SqrtPrice, + fee: u64, + + // Phantom data to use T + _phantom: PhantomData, +} + +impl SwapStep { + /// Creates and initializes a new swap step + fn new( + netuid: NetUid, + order_type: OrderType, + amount_remaining: u64, + limit_sqrt_price: SqrtPrice, + ) -> Self { + // Calculate prices and ticks + let current_tick = CurrentTick::::get(netuid); + let current_sqrt_price = Pallet::::current_price_sqrt(netuid); + let edge_tick = Pallet::::tick_edge(netuid, current_tick, order_type); + let edge_sqrt_price = edge_tick.as_sqrt_price_bounded(); + + let fee = Pallet::::calculate_fee_amount(netuid, amount_remaining); + let possible_delta_in = amount_remaining.saturating_sub(fee); + + // Target price and quantities + let current_liquidity = U64F64::saturating_from_num(CurrentLiquidity::::get(netuid)); + let target_sqrt_price = Pallet::::sqrt_price_target( + order_type, + current_liquidity, + current_sqrt_price, + possible_delta_in, + ); + + Self { + netuid, + order_type, + target_sqrt_price, + limit_sqrt_price, + current_sqrt_price, + edge_sqrt_price, + edge_tick, + possible_delta_in, + current_liquidity, + action: SwapStepAction::Stop, + delta_in: 0, + final_price: target_sqrt_price, + fee, + _phantom: PhantomData, + } + } + + /// Execute the swap step and return the result + fn execute(&mut self) -> Result> { + self.determine_action(); + self.process_swap() + } + + /// Returns True if sq_price1 is closer to the current price than sq_price2 + /// in terms of order direction. + /// For buying: sq_price1 <= sq_price2 + /// For selling: sq_price1 >= sq_price2 + /// + fn price_is_closer(&self, sq_price1: &SqrtPrice, sq_price2: &SqrtPrice) -> bool { + match self.order_type { + OrderType::Buy => sq_price1 <= sq_price2, + OrderType::Sell => sq_price1 >= sq_price2, + } + } + + /// Determine the appropriate action for this swap step + fn determine_action(&mut self) { + let mut recalculate_fee = false; + + // Calculate the stopping price: The price at which we either reach the limit price, + // exchange the full amount, or reach the edge price. + if self.price_is_closer(&self.target_sqrt_price, &self.limit_sqrt_price) + && self.price_is_closer(&self.target_sqrt_price, &self.edge_sqrt_price) + { + // Case 1. target_quantity is the lowest + // The trade completely happens within one tick, no tick crossing happens. + self.action = SwapStepAction::Stop; + self.final_price = self.target_sqrt_price; + self.delta_in = self.possible_delta_in; + } else if self.price_is_closer(&self.limit_sqrt_price, &self.target_sqrt_price) + && self.price_is_closer(&self.limit_sqrt_price, &self.edge_sqrt_price) + { + // Case 2. lim_quantity is the lowest + // The trade also completely happens within one tick, no tick crossing happens. + self.action = SwapStepAction::Stop; + self.final_price = self.limit_sqrt_price; + self.delta_in = Self::delta_in( + self.order_type, + self.current_liquidity, + self.current_sqrt_price, + self.limit_sqrt_price, + ); + recalculate_fee = true; + } else { + // Case 3. edge_quantity is the lowest + // Tick crossing is likely + self.action = SwapStepAction::Crossing; + self.delta_in = Self::delta_in( + self.order_type, + self.current_liquidity, + self.current_sqrt_price, + self.edge_sqrt_price, + ); + self.final_price = self.edge_sqrt_price; + recalculate_fee = true; + } + + log::trace!("\tAction : {:?}", self.action); + log::trace!( + "\tCurrent Price : {}", + self.current_sqrt_price + .saturating_mul(self.current_sqrt_price) + ); + log::trace!( + "\tTarget Price : {}", + self.target_sqrt_price + .saturating_mul(self.target_sqrt_price) + ); + log::trace!( + "\tLimit Price : {}", + self.limit_sqrt_price.saturating_mul(self.limit_sqrt_price) + ); + log::trace!( + "\tEdge Price : {}", + self.edge_sqrt_price.saturating_mul(self.edge_sqrt_price) + ); + log::trace!("\tDelta In : {}", self.delta_in); + + // Because on step creation we calculate fee off the total amount, we might need to recalculate it + // in case if we hit the limit price or the edge price. + if recalculate_fee { + let u16_max = U64F64::saturating_from_num(u16::MAX); + let fee_rate = U64F64::saturating_from_num(FeeRate::::get(self.netuid)); + let delta_fixed = U64F64::saturating_from_num(self.delta_in); + self.fee = delta_fixed + .saturating_mul(fee_rate.safe_div(u16_max.saturating_sub(fee_rate))) + .saturating_to_num::(); + } + + // Now correct the action if we stopped exactly at the edge no matter what was the case above + // Because order type buy moves the price up and tick semi-open interval doesn't include its right + // point, we cross on buys and stop on sells. + let natural_reason_stop_price = + if self.price_is_closer(&self.limit_sqrt_price, &self.target_sqrt_price) { + self.limit_sqrt_price + } else { + self.target_sqrt_price + }; + if natural_reason_stop_price == self.edge_sqrt_price { + self.action = match self.order_type { + OrderType::Buy => SwapStepAction::Crossing, + OrderType::Sell => SwapStepAction::Stop, + }; + } + } + + /// Process a single step of a swap + fn process_swap(&self) -> Result> { + // Hold the fees + Pallet::::add_fees(self.netuid, self.order_type, self.fee); + let delta_out = Pallet::::convert_deltas(self.netuid, self.order_type, self.delta_in); + log::trace!("\tDelta Out : {:?}", delta_out); + + if self.action == SwapStepAction::Crossing { + let mut tick = Ticks::::get(self.netuid, self.edge_tick).unwrap_or_default(); + tick.fees_out_tao = I64F64::saturating_from_num(FeeGlobalTao::::get(self.netuid)) + .saturating_sub(tick.fees_out_tao); + tick.fees_out_alpha = + I64F64::saturating_from_num(FeeGlobalAlpha::::get(self.netuid)) + .saturating_sub(tick.fees_out_alpha); + Pallet::::update_liquidity_at_crossing(self.netuid, self.order_type)?; + Ticks::::insert(self.netuid, self.edge_tick, tick); + } + + // Update current price + AlphaSqrtPrice::::set(self.netuid, self.final_price); + + // Update current tick + let new_current_tick = TickIndex::from_sqrt_price_bounded(self.final_price); + CurrentTick::::set(self.netuid, new_current_tick); + + Ok(SwapStepResult { + amount_to_take: self.delta_in.saturating_add(self.fee), + fee_paid: self.fee, + delta_in: self.delta_in, + delta_out, + }) + } + + /// Get the input amount needed to reach the target price + fn delta_in( + order_type: OrderType, + liquidity_curr: U64F64, + sqrt_price_curr: SqrtPrice, + sqrt_price_target: SqrtPrice, + ) -> u64 { + let one = U64F64::saturating_from_num(1); + + (match order_type { + OrderType::Sell => liquidity_curr.saturating_mul( + one.safe_div(sqrt_price_target.into()) + .saturating_sub(one.safe_div(sqrt_price_curr)), + ), + OrderType::Buy => { + liquidity_curr.saturating_mul(sqrt_price_target.saturating_sub(sqrt_price_curr)) + } + }) + .saturating_to_num::() + } +} + +impl Pallet { + pub fn current_price(netuid: NetUid) -> U96F32 { + match T::SubnetInfo::mechanism(netuid.into()) { + 1 => { + if SwapV3Initialized::::get(netuid) { + let sqrt_price = AlphaSqrtPrice::::get(netuid); + U96F32::saturating_from_num(sqrt_price.saturating_mul(sqrt_price)) + } else { + let tao_reserve = T::SubnetInfo::tao_reserve(netuid.into()); + let alpha_reserve = T::SubnetInfo::alpha_reserve(netuid.into()); + if alpha_reserve > 0 { + U96F32::saturating_from_num(tao_reserve) + .saturating_div(U96F32::saturating_from_num(alpha_reserve)) + } else { + U96F32::saturating_from_num(0) + } + } + } + _ => U96F32::saturating_from_num(1), + } + } + + pub fn current_price_sqrt(netuid: NetUid) -> SqrtPrice { + AlphaSqrtPrice::::get(netuid) + } + + // initializes V3 swap for a subnet if needed + pub(super) fn maybe_initialize_v3(netuid: NetUid) -> Result<(), Error> { + if SwapV3Initialized::::get(netuid) { + return Ok(()); + } + + // Initialize the v3: + // Reserves are re-purposed, nothing to set, just query values for liquidity and price calculation + let tao_reserve = ::SubnetInfo::tao_reserve(netuid.into()); + let alpha_reserve = ::SubnetInfo::alpha_reserve(netuid.into()); + + // Set price + let price = U64F64::saturating_from_num(tao_reserve) + .safe_div(U64F64::saturating_from_num(alpha_reserve)); + + let epsilon = U64F64::saturating_from_num(0.000000000001); + + let current_sqrt_price = price.checked_sqrt(epsilon).unwrap_or(U64F64::from_num(0)); + AlphaSqrtPrice::::set(netuid, current_sqrt_price); + + // Set current tick + let current_tick = TickIndex::from_sqrt_price_bounded(current_sqrt_price); + CurrentTick::::set(netuid, current_tick); + + // Set initial (protocol owned) liquidity and positions + // Protocol liquidity makes one position from TickIndex::MIN to TickIndex::MAX + // We are using the sp_arithmetic sqrt here, which works for u128 + let liquidity = + helpers_128bit::sqrt((tao_reserve as u128).saturating_mul(alpha_reserve as u128)) + as u64; + let protocol_account_id = Self::protocol_account_id(); + + let (position, _, _) = Self::add_liquidity_not_insert( + netuid, + &protocol_account_id, + TickIndex::MIN, + TickIndex::MAX, + liquidity, + )?; + + Positions::::insert(&(netuid, protocol_account_id, position.id), position); + + Ok(()) + } + + /// Adjusts protocol liquidity with new values of TAO and Alpha reserve + pub(super) fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64) { + // Update protocol position with new liquidity + let protocol_account_id = Self::protocol_account_id(); + let mut positions = + Positions::::iter_prefix_values((netuid, protocol_account_id.clone())) + .collect::>(); + + if let Some(position) = positions.get_mut(0) { + let current_sqrt_price = Pallet::::current_price_sqrt(netuid); + let maybe_token_amounts = position.to_token_amounts(current_sqrt_price); + if let Ok((tao, alpha)) = maybe_token_amounts { + // Get updated reserves, calculate liquidity + let new_tao_reserve = tao.saturating_add(tao_delta); + let new_alpha_reserve = alpha.saturating_add(alpha_delta); + let new_liquidity = helpers_128bit::sqrt( + (new_tao_reserve as u128).saturating_mul(new_alpha_reserve as u128), + ) as u64; + + position.liquidity = new_liquidity; + Positions::::insert( + (netuid, protocol_account_id, position.id), + position.clone(), + ); + } + } + } + + /// Executes a token swap on the specified subnet. + /// + /// # Parameters + /// - `netuid`: The identifier of the subnet on which the swap is performed. + /// - `order_type`: The type of the swap (e.g., Buy or Sell). + /// - `amount`: The amount of tokens to swap. + /// - `limit_sqrt_price`: A price limit (expressed as a square root) to bound the swap. + /// - `simulate`: If `true`, the function runs in simulation mode and does not persist any changes. + /// + /// # Returns + /// Returns a [`Result`] with a [`SwapResult`] on success, or a [`DispatchError`] on failure. + /// + /// The [`SwapResult`] contains: + /// - `amount_paid_out`: The amount of tokens received from the swap. + /// - `refund`: Any unswapped portion of the input amount, refunded to the caller. + /// + /// # Simulation Mode + /// When `simulate` is set to `true`, the function: + /// 1. Executes all logic without persisting any state changes (i.e., performs a dry run). + /// 2. Skips reserve checks — it may return an `amount_paid_out` greater than the available reserve. + /// + /// Use simulation mode to preview the outcome of a swap without modifying the blockchain state. + pub fn do_swap( + netuid: NetUid, + order_type: OrderType, + amount: u64, + limit_sqrt_price: SqrtPrice, + simulate: bool, + ) -> Result { + transactional::with_transaction(|| { + // Read alpha and tao reserves before transaction + let tao_reserve = T::SubnetInfo::tao_reserve(netuid.into()); + let alpha_reserve = T::SubnetInfo::alpha_reserve(netuid.into()); + + let mut result = + Self::swap_inner(netuid, order_type, amount, limit_sqrt_price).map_err(Into::into); + + if simulate || result.is_err() { + // Simulation only + TransactionOutcome::Rollback(result) + } else { + // Should persist changes + + // Check if reserves are overused + if let Ok(ref swap_result) = result { + let checked_reserve = match order_type { + OrderType::Buy => alpha_reserve, + OrderType::Sell => tao_reserve, + }; + + if checked_reserve < swap_result.amount_paid_out { + result = Err(Error::::InsufficientLiquidity.into()); + } + } + + TransactionOutcome::Commit(result) + } + }) + } + + fn swap_inner( + netuid: NetUid, + order_type: OrderType, + amount: u64, + limit_sqrt_price: SqrtPrice, + ) -> Result> { + ensure!( + T::SubnetInfo::tao_reserve(netuid.into()) >= T::MinimumReserve::get().get() + && T::SubnetInfo::alpha_reserve(netuid.into()) >= T::MinimumReserve::get().get(), + Error::::ReservesTooLow + ); + + Self::maybe_initialize_v3(netuid)?; + + let mut amount_remaining = amount; + let mut amount_paid_out: u64 = 0; + let mut iteration_counter: u16 = 0; + let mut in_acc: u64 = 0; + let mut fee_acc: u64 = 0; + + log::trace!("======== Start Swap ========"); + log::trace!("Amount Remaining: {}", amount_remaining); + + // Swap one tick at a time until we reach one of the stop conditions + while amount_remaining > 0 { + log::trace!("\nIteration: {}", iteration_counter); + log::trace!( + "\tCurrent Liquidity: {}", + CurrentLiquidity::::get(netuid) + ); + + // Create and execute a swap step + let mut swap_step = + SwapStep::::new(netuid, order_type, amount_remaining, limit_sqrt_price); + + let swap_result = swap_step.execute()?; + + in_acc = in_acc.saturating_add(swap_result.delta_in); + fee_acc = fee_acc.saturating_add(swap_result.fee_paid); + amount_remaining = amount_remaining.saturating_sub(swap_result.amount_to_take); + amount_paid_out = amount_paid_out.saturating_add(swap_result.delta_out); + + if swap_step.action == SwapStepAction::Stop { + amount_remaining = 0; + } + + // The swap step didn't exchange anything + if swap_result.amount_to_take == 0 { + amount_remaining = 0; + } + + iteration_counter = iteration_counter.saturating_add(1); + + ensure!( + iteration_counter <= MAX_SWAP_ITERATIONS, + Error::::TooManySwapSteps + ); + } + + log::trace!("\nAmount Paid Out: {}", amount_paid_out); + log::trace!("======== End Swap ========"); + + let (tao_reserve_delta, alpha_reserve_delta) = match order_type { + OrderType::Buy => (in_acc as i64, (amount_paid_out as i64).neg()), + OrderType::Sell => ((amount_paid_out as i64).neg(), in_acc as i64), + }; + + Ok(SwapResult { + amount_paid_in: in_acc, + amount_paid_out, + fee_paid: fee_acc, + tao_reserve_delta, + alpha_reserve_delta, + }) + } + + /// Get the tick at the current tick edge for the given direction (order type) If + /// order type is Buy, then edge tick is the high tick, otherwise it is the low + /// tick. + /// + /// If anything is wrong with tick math and it returns Err, we just abort the deal, i.e. return + /// the edge that is impossible to execute + fn tick_edge(netuid: NetUid, current_tick: TickIndex, order_type: OrderType) -> TickIndex { + match order_type { + OrderType::Buy => ActiveTickIndexManager::::find_closest_higher( + netuid, + current_tick.next().unwrap_or(TickIndex::MAX), + ) + .unwrap_or(TickIndex::MAX), + OrderType::Sell => { + let current_price = Pallet::::current_price_sqrt(netuid); + let current_tick_price = current_tick.as_sqrt_price_bounded(); + let is_active = ActiveTickIndexManager::::tick_is_active(netuid, current_tick); + + if is_active && current_price > current_tick_price { + ActiveTickIndexManager::::find_closest_lower(netuid, current_tick) + .unwrap_or(TickIndex::MIN) + } else { + ActiveTickIndexManager::::find_closest_lower( + netuid, + current_tick.prev().unwrap_or(TickIndex::MIN), + ) + .unwrap_or(TickIndex::MIN) + } + } + } + } + + /// Calculate fee amount + /// + /// Fee is provided by state ops as u16-normalized value. + fn calculate_fee_amount(netuid: NetUid, amount: u64) -> u64 { + let fee_rate = U64F64::saturating_from_num(FeeRate::::get(netuid)) + .safe_div(U64F64::saturating_from_num(u16::MAX)); + + U64F64::saturating_from_num(amount) + .saturating_mul(fee_rate) + .saturating_to_num::() + } + + /// Add fees to the global fee counters + fn add_fees(netuid: NetUid, order_type: OrderType, fee: u64) { + let liquidity_curr = Self::current_liquidity_safe(netuid); + + if liquidity_curr == 0 { + return; + } + + let fee_global_tao = FeeGlobalTao::::get(netuid); + let fee_global_alpha = FeeGlobalAlpha::::get(netuid); + let fee_fixed = U64F64::saturating_from_num(fee); + + match order_type { + OrderType::Sell => { + FeeGlobalAlpha::::set( + netuid, + fee_global_alpha.saturating_add(fee_fixed.safe_div(liquidity_curr)), + ); + } + OrderType::Buy => { + FeeGlobalTao::::set( + netuid, + fee_global_tao.saturating_add(fee_fixed.safe_div(liquidity_curr)), + ); + } + } + } + + /// Convert input amount (delta_in) to output amount (delta_out) + /// + /// This is the core method of uniswap V3 that tells how much output token is given for an + /// amount of input token within one price tick. + pub(super) fn convert_deltas(netuid: NetUid, order_type: OrderType, delta_in: u64) -> u64 { + // Skip conversion if delta_in is zero + if delta_in == 0 { + return 0; + } + + let liquidity_curr = SqrtPrice::saturating_from_num(CurrentLiquidity::::get(netuid)); + let sqrt_price_curr = Pallet::::current_price_sqrt(netuid); + let delta_fixed = SqrtPrice::saturating_from_num(delta_in); + + // Calculate result based on order type with proper fixed-point math + // Using safe math operations throughout to prevent overflows + let result = match order_type { + OrderType::Sell => { + // liquidity_curr / (liquidity_curr / sqrt_price_curr + delta_fixed); + let denom = liquidity_curr + .safe_div(sqrt_price_curr) + .saturating_add(delta_fixed); + let a = liquidity_curr.safe_div(denom); + // a * sqrt_price_curr; + let b = a.saturating_mul(sqrt_price_curr); + + // delta_fixed * b; + delta_fixed.saturating_mul(b) + } + OrderType::Buy => { + // (liquidity_curr * sqrt_price_curr + delta_fixed) * sqrt_price_curr; + let a = liquidity_curr + .saturating_mul(sqrt_price_curr) + .saturating_add(delta_fixed) + .saturating_mul(sqrt_price_curr); + // liquidity_curr / a; + let b = liquidity_curr.safe_div(a); + // b * delta_fixed; + b.saturating_mul(delta_fixed) + } + }; + + result.saturating_to_num::() + } + + /// Get the target square root price based on the input amount + /// + /// This is the price that would be reached if + /// - There are no liquidity positions other than protocol liquidity + /// - Full delta_in amount is executed + /// + fn sqrt_price_target( + order_type: OrderType, + liquidity_curr: U64F64, + sqrt_price_curr: SqrtPrice, + delta_in: u64, + ) -> SqrtPrice { + let delta_fixed = U64F64::saturating_from_num(delta_in); + let one = U64F64::saturating_from_num(1); + + // No liquidity means that price should go to the limit + if liquidity_curr == 0 { + return match order_type { + OrderType::Sell => SqrtPrice::saturating_from_num(Self::min_price()), + OrderType::Buy => SqrtPrice::saturating_from_num(Self::max_price()), + }; + } + + match order_type { + OrderType::Sell => one.safe_div( + delta_fixed + .safe_div(liquidity_curr) + .saturating_add(one.safe_div(sqrt_price_curr)), + ), + OrderType::Buy => delta_fixed + .safe_div(liquidity_curr) + .saturating_add(sqrt_price_curr), + } + } + + /// Update liquidity when crossing a tick + fn update_liquidity_at_crossing(netuid: NetUid, order_type: OrderType) -> Result<(), Error> { + let mut liquidity_curr = CurrentLiquidity::::get(netuid); + let current_tick_index = TickIndex::current_bounded::(netuid); + + // Find the appropriate tick based on order type + let tick = match order_type { + OrderType::Sell => { + // Self::find_closest_lower_active_tick(netuid, current_tick_index) + let current_price = Pallet::::current_price_sqrt(netuid); + let current_tick_price = current_tick_index.as_sqrt_price_bounded(); + let is_active = + ActiveTickIndexManager::::tick_is_active(netuid, current_tick_index); + + let lower_tick = if is_active && current_price > current_tick_price { + ActiveTickIndexManager::::find_closest_lower(netuid, current_tick_index) + .unwrap_or(TickIndex::MIN) + } else { + ActiveTickIndexManager::::find_closest_lower( + netuid, + current_tick_index.prev().unwrap_or(TickIndex::MIN), + ) + .unwrap_or(TickIndex::MIN) + }; + Ticks::::get(netuid, lower_tick) + } + OrderType::Buy => { + // Self::find_closest_higher_active_tick(netuid, current_tick_index), + let upper_tick = ActiveTickIndexManager::::find_closest_higher( + netuid, + current_tick_index.next().unwrap_or(TickIndex::MAX), + ) + .unwrap_or(TickIndex::MAX); + Ticks::::get(netuid, upper_tick) + } + } + .ok_or(Error::::InsufficientLiquidity)?; + + let liquidity_update_abs_u64 = tick.liquidity_net_as_u64(); + + // Update liquidity based on the sign of liquidity_net and the order type + liquidity_curr = match (order_type, tick.liquidity_net >= 0) { + (OrderType::Sell, true) | (OrderType::Buy, false) => { + liquidity_curr.saturating_sub(liquidity_update_abs_u64) + } + (OrderType::Sell, false) | (OrderType::Buy, true) => { + liquidity_curr.saturating_add(liquidity_update_abs_u64) + } + }; + + CurrentLiquidity::::set(netuid, liquidity_curr); + + Ok(()) + } + + pub fn find_closest_lower_active_tick(netuid: NetUid, index: TickIndex) -> Option { + ActiveTickIndexManager::::find_closest_lower(netuid, index) + .and_then(|ti| Ticks::::get(netuid, ti)) + } + + pub fn find_closest_higher_active_tick(netuid: NetUid, index: TickIndex) -> Option { + ActiveTickIndexManager::::find_closest_higher(netuid, index) + .and_then(|ti| Ticks::::get(netuid, ti)) + } + + /// Here we subtract minimum safe liquidity from current liquidity to stay in the safe range + fn current_liquidity_safe(netuid: NetUid) -> U64F64 { + U64F64::saturating_from_num( + CurrentLiquidity::::get(netuid).saturating_sub(T::MinimumLiquidity::get()), + ) + } + + /// Adds liquidity to the specified price range. + /// + /// This function allows an account to provide liquidity to a given range of price ticks. The + /// amount of liquidity to be added can be determined using + /// [`get_tao_based_liquidity`] and [`get_alpha_based_liquidity`], which compute the required + /// liquidity based on TAO and Alpha balances for the current price tick. + /// + /// ### Behavior: + /// - If the `protocol` flag is **not set** (`false`), the function will attempt to + /// **withdraw balances** from the account using `state_ops.withdraw_balances()`. + /// - If the `protocol` flag is **set** (`true`), the liquidity is added without modifying balances. + /// - If swap V3 was not initialized before, updates the value in storage. + /// + /// ### Parameters: + /// - `coldkey_account_id`: A reference to the account coldkey that is providing liquidity. + /// - `hotkey_account_id`: A reference to the account hotkey that is providing liquidity. + /// - `tick_low`: The lower bound of the price tick range. + /// - `tick_high`: The upper bound of the price tick range. + /// - `liquidity`: The amount of liquidity to be added. + /// + /// ### Returns: + /// - `Ok((u64, u64))`: (tao, alpha) amounts at new position + /// - `Err(SwapError)`: If the operation fails due to insufficient balance, invalid tick range, + /// or other swap-related errors. + /// + /// ### Errors: + /// - [`SwapError::InsufficientBalance`] if the account does not have enough balance. + /// - [`SwapError::InvalidTickRange`] if `tick_low` is greater than or equal to `tick_high`. + /// - Other [`SwapError`] variants as applicable. + pub fn do_add_liquidity( + netuid: NetUid, + coldkey_account_id: &T::AccountId, + hotkey_account_id: &T::AccountId, + tick_low: TickIndex, + tick_high: TickIndex, + liquidity: u64, + ) -> Result<(PositionId, u64, u64), Error> { + ensure!( + EnabledUserLiquidity::::get(netuid), + Error::::UserLiquidityDisabled + ); + + let (position, tao, alpha) = Self::add_liquidity_not_insert( + netuid, + coldkey_account_id, + tick_low, + tick_high, + liquidity, + )?; + let position_id = position.id; + + ensure!( + T::BalanceOps::tao_balance(coldkey_account_id) >= tao + && T::BalanceOps::alpha_balance( + netuid.into(), + coldkey_account_id, + hotkey_account_id + ) >= alpha, + Error::::InsufficientBalance + ); + + // Small delta is not allowed + ensure!( + liquidity >= T::MinimumLiquidity::get(), + Error::::InvalidLiquidityValue + ); + + Positions::::insert(&(netuid, coldkey_account_id, position.id), position); + + Ok((position_id, tao, alpha)) + } + + // add liquidity without inserting position into storage (used privately for v3 intiialization). + // unlike Self::add_liquidity it also doesn't perform account's balance check. + // + // the public interface is [`Self::add_liquidity`] + fn add_liquidity_not_insert( + netuid: NetUid, + coldkey_account_id: &T::AccountId, + tick_low: TickIndex, + tick_high: TickIndex, + liquidity: u64, + ) -> Result<(Position, u64, u64), Error> { + ensure!( + Self::count_positions(netuid, coldkey_account_id) <= T::MaxPositions::get() as usize, + Error::::MaxPositionsExceeded + ); + + // Add liquidity at tick + Self::add_liquidity_at_index(netuid, tick_low, liquidity, false); + Self::add_liquidity_at_index(netuid, tick_high, liquidity, true); + + // Update current tick liquidity + let current_tick_index = TickIndex::current_bounded::(netuid); + Self::clamp_sqrt_price(netuid, current_tick_index); + + Self::update_liquidity_if_needed(netuid, tick_low, tick_high, liquidity as i128); + + // New position + let position_id = PositionId::new::(); + let position = Position::new(position_id, netuid, tick_low, tick_high, liquidity); + + let current_price_sqrt = Pallet::::current_price_sqrt(netuid); + let (tao, alpha) = position.to_token_amounts(current_price_sqrt)?; + + SwapV3Initialized::::set(netuid, true); + + Ok((position, tao, alpha)) + } + + /// Remove liquidity and credit balances back to (coldkey_account_id, hotkey_account_id) stake. + /// Removing is allowed even when user liquidity is enabled. + /// + /// Account ID and Position ID identify position in the storage map + pub fn do_remove_liquidity( + netuid: NetUid, + coldkey_account_id: &T::AccountId, + position_id: PositionId, + ) -> Result> { + let Some(mut position) = Positions::::get((netuid, coldkey_account_id, position_id)) + else { + return Err(Error::::LiquidityNotFound); + }; + + // Collect fees and get tao and alpha amounts + let (fee_tao, fee_alpha) = position.collect_fees(); + let current_price = AlphaSqrtPrice::::get(netuid); + let (tao, alpha) = position.to_token_amounts(current_price)?; + + // Update liquidity at position ticks + Self::remove_liquidity_at_index(netuid, position.tick_low, position.liquidity, false); + Self::remove_liquidity_at_index(netuid, position.tick_high, position.liquidity, true); + + // Update current tick liquidity + Self::update_liquidity_if_needed( + netuid, + position.tick_low, + position.tick_high, + (position.liquidity as i128).neg(), + ); + + // Remove user position + Positions::::remove((netuid, coldkey_account_id, position_id)); + + Ok(UpdateLiquidityResult { + tao, + alpha, + fee_tao, + fee_alpha, + removed: true, + }) + } + + pub fn do_modify_position( + netuid: NetUid, + coldkey_account_id: &T::AccountId, + hotkey_account_id: &T::AccountId, + position_id: PositionId, + liquidity_delta: i64, + ) -> Result> { + ensure!( + EnabledUserLiquidity::::get(netuid), + Error::::UserLiquidityDisabled + ); + + // Find the position + let Some(mut position) = Positions::::get((netuid, coldkey_account_id, position_id)) + else { + return Err(Error::::LiquidityNotFound); + }; + + // Small delta is not allowed + ensure!( + liquidity_delta.abs() >= T::MinimumLiquidity::get() as i64, + Error::::InvalidLiquidityValue + ); + let mut delta_liquidity_abs = liquidity_delta.unsigned_abs(); + + // Determine the effective price for token calculations + let current_price_sqrt = Pallet::::current_price_sqrt(netuid); + let sqrt_pa: SqrtPrice = position + .tick_low + .try_to_sqrt_price() + .map_err(|_| Error::::InvalidTickRange)?; + let sqrt_pb: SqrtPrice = position + .tick_high + .try_to_sqrt_price() + .map_err(|_| Error::::InvalidTickRange)?; + let sqrt_price_box = if current_price_sqrt < sqrt_pa { + sqrt_pa + } else if current_price_sqrt > sqrt_pb { + sqrt_pb + } else { + // Update current liquidity if price is in range + let new_liquidity_curr = if liquidity_delta > 0 { + CurrentLiquidity::::get(netuid).saturating_add(delta_liquidity_abs) + } else { + CurrentLiquidity::::get(netuid).saturating_sub(delta_liquidity_abs) + }; + CurrentLiquidity::::set(netuid, new_liquidity_curr); + current_price_sqrt + }; + + // Calculate token amounts for the liquidity change + let mul = SqrtPrice::from_num(1) + .safe_div(sqrt_price_box) + .saturating_sub(SqrtPrice::from_num(1).safe_div(sqrt_pb)); + let alpha = SqrtPrice::saturating_from_num(delta_liquidity_abs).saturating_mul(mul); + let tao = SqrtPrice::saturating_from_num(delta_liquidity_abs) + .saturating_mul(sqrt_price_box.saturating_sub(sqrt_pa)); + + // Validate delta + if liquidity_delta > 0 { + // Check that user has enough balances + ensure!( + T::BalanceOps::tao_balance(coldkey_account_id) >= tao + && T::BalanceOps::alpha_balance(netuid, coldkey_account_id, hotkey_account_id) + >= alpha, + Error::::InsufficientBalance + ); + } else { + // Check that position has enough liquidity + ensure!( + position.liquidity >= delta_liquidity_abs, + Error::::InsufficientLiquidity + ); + } + + // Collect fees + let (fee_tao, fee_alpha) = position.collect_fees(); + + // If delta brings the position liquidity below MinimumLiquidity, eliminate position and + // withdraw full amounts + let mut remove = false; + if (liquidity_delta < 0) + && (position.liquidity.saturating_sub(delta_liquidity_abs) < T::MinimumLiquidity::get()) + { + delta_liquidity_abs = position.liquidity; + remove = true; + } + + // Adjust liquidity at the ticks based on the delta sign + if liquidity_delta > 0 { + // Add liquidity at tick + Self::add_liquidity_at_index(netuid, position.tick_low, delta_liquidity_abs, false); + Self::add_liquidity_at_index(netuid, position.tick_high, delta_liquidity_abs, true); + + // Add liquidity to user position + position.liquidity = position.liquidity.saturating_add(delta_liquidity_abs); + } else { + // Remove liquidity at tick + Self::remove_liquidity_at_index(netuid, position.tick_low, position.liquidity, false); + Self::remove_liquidity_at_index(netuid, position.tick_high, position.liquidity, true); + + // Remove liquidity from user position + position.liquidity = position.liquidity.saturating_sub(delta_liquidity_abs); + } + + // Update or, in case if full liquidity is removed, remove the position + if remove { + Positions::::remove((netuid, coldkey_account_id, position_id)); + } else { + Positions::::insert(&(netuid, coldkey_account_id, position.id), position); + } + + Ok(UpdateLiquidityResult { + tao: tao.saturating_to_num::(), + alpha: alpha.saturating_to_num::(), + fee_tao, + fee_alpha, + removed: remove, + }) + } + + /// Adds or updates liquidity at a specific tick index for a subnet + /// + /// # Arguments + /// * `netuid` - The subnet ID + /// * `tick_index` - The tick index to add liquidity to + /// * `liquidity` - The amount of liquidity to add + fn add_liquidity_at_index(netuid: NetUid, tick_index: TickIndex, liquidity: u64, upper: bool) { + // Convert liquidity to signed value, negating it for upper bounds + let net_liquidity_change = if upper { + (liquidity as i128).neg() + } else { + liquidity as i128 + }; + + Ticks::::mutate(netuid, tick_index, |maybe_tick| match maybe_tick { + Some(tick) => { + tick.liquidity_net = tick.liquidity_net.saturating_add(net_liquidity_change); + tick.liquidity_gross = tick.liquidity_gross.saturating_add(liquidity); + } + None => { + let current_tick = TickIndex::current_bounded::(netuid); + + let (fees_out_tao, fees_out_alpha) = if tick_index > current_tick { + ( + I64F64::saturating_from_num(FeeGlobalTao::::get(netuid)), + I64F64::saturating_from_num(FeeGlobalAlpha::::get(netuid)), + ) + } else { + ( + I64F64::saturating_from_num(0), + I64F64::saturating_from_num(0), + ) + }; + *maybe_tick = Some(Tick { + liquidity_net: net_liquidity_change, + liquidity_gross: liquidity, + fees_out_tao, + fees_out_alpha, + }); + } + }); + + // Update active ticks + ActiveTickIndexManager::::insert(netuid, tick_index); + } + + /// Remove liquidity at tick index. + fn remove_liquidity_at_index( + netuid: NetUid, + tick_index: TickIndex, + liquidity: u64, + upper: bool, + ) { + // Calculate net liquidity addition + let net_reduction = if upper { + (liquidity as i128).neg() + } else { + liquidity as i128 + }; + + Ticks::::mutate_exists(netuid, tick_index, |maybe_tick| { + if let Some(tick) = maybe_tick { + tick.liquidity_net = tick.liquidity_net.saturating_sub(net_reduction); + tick.liquidity_gross = tick.liquidity_gross.saturating_sub(liquidity); + + // If no liquidity is left at the tick, remove it + if tick.liquidity_gross == 0 { + *maybe_tick = None; + + // Update active ticks: Final liquidity is zero, remove this tick from active. + ActiveTickIndexManager::::remove(netuid, tick_index); + } + } + }); + } + + /// Updates the current liquidity for a subnet if the current tick index is within the specified + /// range + /// + /// This function handles both increasing and decreasing liquidity based on the sign of the + /// liquidity parameter. It uses i128 to safely handle values up to u64::MAX in both positive + /// and negative directions. + fn update_liquidity_if_needed( + netuid: NetUid, + tick_low: TickIndex, + tick_high: TickIndex, + liquidity: i128, + ) { + let current_tick_index = TickIndex::current_bounded::(netuid); + if (tick_low <= current_tick_index) && (current_tick_index < tick_high) { + CurrentLiquidity::::mutate(netuid, |current_liquidity| { + let is_neg = liquidity.is_negative(); + let liquidity = liquidity.abs().min(u64::MAX as i128) as u64; + if is_neg { + *current_liquidity = current_liquidity.saturating_sub(liquidity); + } else { + *current_liquidity = current_liquidity.saturating_add(liquidity); + } + }); + } + } + + /// Clamps the subnet's sqrt price when tick index is outside of valid bounds + fn clamp_sqrt_price(netuid: NetUid, tick_index: TickIndex) { + if tick_index >= TickIndex::MAX || tick_index <= TickIndex::MIN { + let corrected_price = tick_index.as_sqrt_price_bounded(); + AlphaSqrtPrice::::set(netuid, corrected_price); + } + } + + /// Returns the number of positions for an account in a specific subnet + /// + /// # Arguments + /// * `netuid` - The subnet ID + /// * `account_id` - The account ID + /// + /// # Returns + /// The number of positions that the account has in the specified subnet + pub(super) fn count_positions(netuid: NetUid, account_id: &T::AccountId) -> usize { + Positions::::iter_prefix_values((netuid, account_id.clone())).count() + } + + /// Returns the protocol account ID + /// + /// # Returns + /// The account ID of the protocol account + pub fn protocol_account_id() -> T::AccountId { + T::ProtocolId::get().into_account_truncating() + } +} + +impl SwapHandler for Pallet { + fn swap( + netuid: NetUid, + order_t: OrderType, + amount: u64, + price_limit: u64, + should_rollback: bool, + ) -> Result { + let limit_sqrt_price = SqrtPrice::saturating_from_num(price_limit) + .safe_div(SqrtPrice::saturating_from_num(1_000_000_000)) + .checked_sqrt(SqrtPrice::saturating_from_num(0.0000000001)) + .ok_or(Error::::PriceLimitExceeded)?; + + Self::do_swap( + NetUid::from(netuid), + order_t, + amount, + limit_sqrt_price, + should_rollback, + ) + .map_err(Into::into) + } + + fn sim_swap( + netuid: NetUid, + order_t: OrderType, + amount: u64, + ) -> Result { + match T::SubnetInfo::mechanism(netuid) { + 1 => { + let price_limit = match order_t { + OrderType::Buy => Self::max_price(), + OrderType::Sell => Self::min_price(), + }; + + Self::swap(netuid, order_t, amount, price_limit, true) + } + _ => Ok(SwapResult { + amount_paid_in: amount, + amount_paid_out: amount, + fee_paid: 0, + tao_reserve_delta: 0, + alpha_reserve_delta: 0, + }), + } + } + + fn approx_fee_amount(netuid: NetUid, amount: u64) -> u64 { + Self::calculate_fee_amount(netuid.into(), amount) + } + + fn current_alpha_price(netuid: NetUid) -> U96F32 { + Self::current_price(netuid.into()) + } + + fn min_price() -> u64 { + TickIndex::min_sqrt_price() + .saturating_mul(TickIndex::min_sqrt_price()) + .saturating_mul(SqrtPrice::saturating_from_num(1_000_000_000)) + .saturating_to_num() + } + + fn max_price() -> u64 { + TickIndex::max_sqrt_price() + .saturating_mul(TickIndex::max_sqrt_price()) + .saturating_mul(SqrtPrice::saturating_from_num(1_000_000_000)) + .saturating_round() + .saturating_to_num() + } + + fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64) { + Self::adjust_protocol_liquidity(netuid, tao_delta, alpha_delta); + } + + fn is_user_liquidity_enabled(netuid: NetUid) -> bool { + EnabledUserLiquidity::::get(netuid) + } +} + +#[derive(Debug, PartialEq)] +struct SwapStepResult { + amount_to_take: u64, + fee_paid: u64, + delta_in: u64, + delta_out: u64, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum SwapStepAction { + Crossing, + Stop, +} diff --git a/pallets/swap/src/pallet/mod.rs b/pallets/swap/src/pallet/mod.rs new file mode 100644 index 0000000000..d226605d40 --- /dev/null +++ b/pallets/swap/src/pallet/mod.rs @@ -0,0 +1,545 @@ +use core::num::NonZeroU64; +use core::ops::Neg; + +use frame_support::{PalletId, pallet_prelude::*, traits::Get}; +use frame_system::pallet_prelude::*; +use substrate_fixed::types::U64F64; +use subtensor_runtime_common::{BalanceOps, NetUid, SubnetInfo}; + +use crate::{ + position::{Position, PositionId}, + tick::{LayerLevel, Tick, TickIndex}, + weights::WeightInfo, +}; + +pub use pallet::*; + +mod impls; +#[cfg(test)] +mod tests; + +#[allow(clippy::module_inception)] +#[frame_support::pallet] +mod pallet { + use super::*; + use frame_system::{ensure_root, ensure_signed}; + + #[pallet::pallet] + pub struct Pallet(_); + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Implementor of + /// [`SubnetInfo`](subtensor_swap_interface::SubnetInfo). + type SubnetInfo: SubnetInfo; + + /// Implementor of + /// [`BalanceOps`](subtensor_swap_interface::BalanceOps). + type BalanceOps: BalanceOps; + + /// This type is used to derive protocol accoun ID. + #[pallet::constant] + type ProtocolId: Get; + + /// The maximum fee rate that can be set + #[pallet::constant] + type MaxFeeRate: Get; + + /// The maximum number of positions a user can have + #[pallet::constant] + type MaxPositions: Get; + + /// Minimum liquidity that is safe for rounding and integer math. + #[pallet::constant] + type MinimumLiquidity: Get; + + /// Minimum reserve for tao and alpha + #[pallet::constant] + type MinimumReserve: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + /// Default fee rate if not set + #[pallet::type_value] + pub fn DefaultFeeRate() -> u16 { + 196 // 0.3 % + } + + /// The fee rate applied to swaps per subnet, normalized value between 0 and u16::MAX + #[pallet::storage] + pub type FeeRate = StorageMap<_, Twox64Concat, NetUid, u16, ValueQuery, DefaultFeeRate>; + + // Global accrued fees in tao per subnet + #[pallet::storage] + pub type FeeGlobalTao = StorageMap<_, Twox64Concat, NetUid, U64F64, ValueQuery>; + + // Global accrued fees in alpha per subnet + #[pallet::storage] + pub type FeeGlobalAlpha = StorageMap<_, Twox64Concat, NetUid, U64F64, ValueQuery>; + + /// Storage for all ticks, using subnet ID as the primary key and tick index as the secondary key + #[pallet::storage] + pub type Ticks = StorageDoubleMap<_, Twox64Concat, NetUid, Twox64Concat, TickIndex, Tick>; + + /// Storage to determine whether swap V3 was initialized for a specific subnet. + #[pallet::storage] + pub type SwapV3Initialized = StorageMap<_, Twox64Concat, NetUid, bool, ValueQuery>; + + /// Storage for the square root price of Alpha token for each subnet. + #[pallet::storage] + pub type AlphaSqrtPrice = StorageMap<_, Twox64Concat, NetUid, U64F64, ValueQuery>; + + /// Storage for the current price tick. + #[pallet::storage] + pub type CurrentTick = StorageMap<_, Twox64Concat, NetUid, TickIndex, ValueQuery>; + + /// Storage for the current liquidity amount for each subnet. + #[pallet::storage] + pub type CurrentLiquidity = StorageMap<_, Twox64Concat, NetUid, u64, ValueQuery>; + + /// Indicates whether a subnet has been switched to V3 swap from V2. + /// If `true`, the subnet is permanently on V3 swap mode allowing add/remove liquidity + /// operations. Once set to `true` for a subnet, it cannot be changed back to `false`. + #[pallet::storage] + pub type EnabledUserLiquidity = StorageMap<_, Twox64Concat, NetUid, bool, ValueQuery>; + + /// Storage for user positions, using subnet ID and account ID as keys + /// The value is a bounded vector of Position structs with details about the liquidity positions + #[pallet::storage] + pub type Positions = StorageNMap< + _, + ( + NMapKey, // Subnet ID + NMapKey, // Account ID + NMapKey, // Position ID + ), + Position, + OptionQuery, + >; + + /// Position ID counter. + #[pallet::storage] + pub type LastPositionId = StorageValue<_, u128, ValueQuery>; + + /// Tick index bitmap words storage + #[pallet::storage] + pub type TickIndexBitmapWords = StorageNMap< + _, + ( + NMapKey, // Subnet ID + NMapKey, // Layer level + NMapKey, // word index + ), + u128, + ValueQuery, + >; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when the fee rate has been updated for a subnet + FeeRateSet { netuid: NetUid, rate: u16 }, + + /// Event emitted when user liquidity operations are enabled for a subnet. + /// First enable even indicates a switch from V2 to V3 swap. + UserLiquidityToggled { netuid: NetUid, enable: bool }, + + /// Event emitted when a liquidity position is added to a subnet's liquidity pool. + LiquidityAdded { + /// The coldkey account that owns the position + coldkey: T::AccountId, + /// The hotkey account where Alpha comes from + hotkey: T::AccountId, + /// The subnet identifier + netuid: NetUid, + /// Unique identifier for the liquidity position + position_id: PositionId, + /// The amount of liquidity added to the position + liquidity: u64, + /// The amount of TAO tokens committed to the position + tao: u64, + /// The amount of Alpha tokens committed to the position + alpha: u64, + }, + + /// Event emitted when a liquidity position is removed from a subnet's liquidity pool. + LiquidityRemoved { + /// The coldkey account that owns the position + coldkey: T::AccountId, + /// The hotkey account where Alpha goes to + hotkey: T::AccountId, + /// The subnet identifier + netuid: NetUid, + /// Unique identifier for the liquidity position + position_id: PositionId, + /// The amount of TAO tokens returned to the user + tao: u64, + /// The amount of Alpha tokens returned to the user + alpha: u64, + /// The amount of TAO fees earned from the position + fee_tao: u64, + /// The amount of Alpha fees earned from the position + fee_alpha: u64, + }, + + /// Event emitted when a liquidity position is modified in a subnet's liquidity pool. + /// Modifying causes the fees to be claimed. + LiquidityModified { + /// The coldkey account that owns the position + coldkey: T::AccountId, + /// The hotkey account where Alpha comes from or goes to + hotkey: T::AccountId, + /// The subnet identifier + netuid: NetUid, + /// Unique identifier for the liquidity position + position_id: PositionId, + /// The amount of liquidity added to or removed from the position + liquidity: i64, + /// The amount of TAO tokens returned to the user + tao: i64, + /// The amount of Alpha tokens returned to the user + alpha: i64, + /// The amount of TAO fees earned from the position + fee_tao: u64, + /// The amount of Alpha fees earned from the position + fee_alpha: u64, + }, + } + + #[pallet::error] + #[derive(PartialEq)] + pub enum Error { + /// The fee rate is too high + FeeRateTooHigh, + + /// The provided amount is insufficient for the swap. + InsufficientInputAmount, + + /// The provided liquidity is insufficient for the operation. + InsufficientLiquidity, + + /// The operation would exceed the price limit. + PriceLimitExceeded, + + /// The caller does not have enough balance for the operation. + InsufficientBalance, + + /// Attempted to remove liquidity that does not exist. + LiquidityNotFound, + + /// The provided tick range is invalid. + InvalidTickRange, + + /// Maximum user positions exceeded + MaxPositionsExceeded, + + /// Too many swap steps + TooManySwapSteps, + + /// Provided liquidity parameter is invalid (likely too small) + InvalidLiquidityValue, + + /// Reserves too low for operation. + ReservesTooLow, + + /// The subnet does not exist. + SubNetworkDoesNotExist, + + /// User liquidity operations are disabled for this subnet + UserLiquidityDisabled, + } + + #[pallet::call] + impl Pallet { + /// Set the fee rate for swaps on a specific subnet (normalized value). + /// For example, 0.3% is approximately 196. + /// + /// Only callable by the admin origin + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::set_fee_rate())] + pub fn set_fee_rate(origin: OriginFor, netuid: NetUid, rate: u16) -> DispatchResult { + if ensure_root(origin.clone()).is_err() { + let account_id: T::AccountId = ensure_signed(origin)?; + ensure!( + T::SubnetInfo::is_owner(&account_id, netuid.into()), + DispatchError::BadOrigin + ); + } + + // Ensure that the subnet exists. + ensure!( + T::SubnetInfo::exists(netuid.into()), + Error::::SubNetworkDoesNotExist + ); + + ensure!(rate <= T::MaxFeeRate::get(), Error::::FeeRateTooHigh); + + FeeRate::::insert(netuid, rate); + + Self::deposit_event(Event::FeeRateSet { netuid, rate }); + + Ok(()) + } + + /// Enable user liquidity operations for a specific subnet. This switches the + /// subnet from V2 to V3 swap mode. Thereafter, adding new user liquidity can be disabled + /// by toggling this flag to false, but the swap mode will remain V3 because of existing + /// user liquidity until all users withdraw their liquidity. + /// + /// Only sudo or subnet owner can enable user liquidity. + /// Only sudo can disable user liquidity. + #[pallet::call_index(4)] + #[pallet::weight(::WeightInfo::toggle_user_liquidity())] + pub fn toggle_user_liquidity( + origin: OriginFor, + netuid: NetUid, + enable: bool, + ) -> DispatchResult { + if ensure_root(origin.clone()).is_err() { + let account_id: T::AccountId = ensure_signed(origin)?; + // Only enabling is allowed to subnet owner + ensure!( + T::SubnetInfo::is_owner(&account_id, netuid.into()) && enable, + DispatchError::BadOrigin + ); + } + + ensure!( + T::SubnetInfo::exists(netuid.into()), + Error::::SubNetworkDoesNotExist + ); + + EnabledUserLiquidity::::insert(netuid, enable); + + Self::deposit_event(Event::UserLiquidityToggled { netuid, enable }); + + Ok(()) + } + + /// Add liquidity to a specific price range for a subnet. + /// + /// Parameters: + /// - origin: The origin of the transaction + /// - netuid: Subnet ID + /// - tick_low: Lower bound of the price range + /// - tick_high: Upper bound of the price range + /// - liquidity: Amount of liquidity to add + /// + /// Emits `Event::LiquidityAdded` on success + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::add_liquidity())] + pub fn add_liquidity( + origin: OriginFor, + hotkey: T::AccountId, + netuid: NetUid, + tick_low: TickIndex, + tick_high: TickIndex, + liquidity: u64, + ) -> DispatchResult { + let coldkey = ensure_signed(origin)?; + + // Ensure that the subnet exists. + ensure!( + T::SubnetInfo::exists(netuid.into()), + Error::::SubNetworkDoesNotExist + ); + + let (position_id, tao, alpha) = Self::do_add_liquidity( + netuid.into(), + &coldkey, + &hotkey, + tick_low, + tick_high, + liquidity, + )?; + + // Remove TAO and Alpha balances or fail transaction if they can't be removed exactly + let tao_provided = T::BalanceOps::decrease_balance(&coldkey, tao)?; + ensure!(tao_provided == tao, Error::::InsufficientBalance); + + let alpha_provided = + T::BalanceOps::decrease_stake(&coldkey, &hotkey, netuid.into(), alpha)?; + ensure!(alpha_provided == alpha, Error::::InsufficientBalance); + + // Add provided liquidity to user-provided reserves + T::BalanceOps::increase_provided_tao_reserve(netuid.into(), tao_provided); + T::BalanceOps::increase_provided_alpha_reserve(netuid.into(), alpha_provided); + + // Emit an event + Self::deposit_event(Event::LiquidityAdded { + coldkey, + hotkey, + netuid, + position_id, + liquidity, + tao, + alpha, + }); + + Ok(()) + } + + /// Remove liquidity from a specific position. + /// + /// Parameters: + /// - origin: The origin of the transaction + /// - netuid: Subnet ID + /// - position_id: ID of the position to remove + /// + /// Emits `Event::LiquidityRemoved` on success + #[pallet::call_index(2)] + #[pallet::weight(::WeightInfo::remove_liquidity())] + pub fn remove_liquidity( + origin: OriginFor, + hotkey: T::AccountId, + netuid: NetUid, + position_id: PositionId, + ) -> DispatchResult { + let coldkey = ensure_signed(origin)?; + + // Ensure that the subnet exists. + ensure!( + T::SubnetInfo::exists(netuid.into()), + Error::::SubNetworkDoesNotExist + ); + + // Remove liquidity + let result = Self::do_remove_liquidity(netuid, &coldkey, position_id)?; + + // Credit the returned tao and alpha to the account + T::BalanceOps::increase_balance(&coldkey, result.tao.saturating_add(result.fee_tao)); + T::BalanceOps::increase_stake( + &coldkey, + &hotkey, + netuid.into(), + result.alpha.saturating_add(result.fee_alpha), + )?; + + // Remove withdrawn liquidity from user-provided reserves + T::BalanceOps::decrease_provided_tao_reserve(netuid.into(), result.tao); + T::BalanceOps::decrease_provided_alpha_reserve(netuid.into(), result.alpha); + + // Emit an event + Self::deposit_event(Event::LiquidityRemoved { + coldkey, + hotkey, + netuid: netuid.into(), + position_id, + tao: result.tao, + alpha: result.alpha, + fee_tao: result.fee_tao, + fee_alpha: result.fee_alpha, + }); + + Ok(()) + } + + /// Modify a liquidity position. + /// + /// Parameters: + /// - origin: The origin of the transaction + /// - netuid: Subnet ID + /// - position_id: ID of the position to remove + /// - liquidity_delta: Liquidity to add (if positive) or remove (if negative) + /// + /// Emits `Event::LiquidityRemoved` on success + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::modify_position())] + pub fn modify_position( + origin: OriginFor, + hotkey: T::AccountId, + netuid: NetUid, + position_id: PositionId, + liquidity_delta: i64, + ) -> DispatchResult { + let coldkey = ensure_signed(origin)?; + + // Ensure that the subnet exists. + ensure!( + T::SubnetInfo::exists(netuid.into()), + Error::::SubNetworkDoesNotExist + ); + + // Add or remove liquidity + let result = + Self::do_modify_position(netuid, &coldkey, &hotkey, position_id, liquidity_delta)?; + + if liquidity_delta > 0 { + // Remove TAO and Alpha balances or fail transaction if they can't be removed exactly + let tao_provided = T::BalanceOps::decrease_balance(&coldkey, result.tao)?; + ensure!(tao_provided == result.tao, Error::::InsufficientBalance); + + let alpha_provided = + T::BalanceOps::decrease_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; + ensure!( + alpha_provided == result.alpha, + Error::::InsufficientBalance + ); + + // Emit an event + Self::deposit_event(Event::LiquidityModified { + coldkey: coldkey.clone(), + hotkey: hotkey.clone(), + netuid, + position_id, + liquidity: liquidity_delta, + tao: result.tao as i64, + alpha: result.alpha as i64, + fee_tao: result.fee_tao, + fee_alpha: result.fee_alpha, + }); + } else { + // Credit the returned tao and alpha to the account + T::BalanceOps::increase_balance(&coldkey, result.tao); + T::BalanceOps::increase_stake(&coldkey, &hotkey, netuid.into(), result.alpha)?; + + // Emit an event + if result.removed { + Self::deposit_event(Event::LiquidityRemoved { + coldkey: coldkey.clone(), + hotkey: hotkey.clone(), + netuid, + position_id, + tao: result.tao, + alpha: result.alpha, + fee_tao: result.fee_tao, + fee_alpha: result.fee_alpha, + }); + } else { + Self::deposit_event(Event::LiquidityModified { + coldkey: coldkey.clone(), + hotkey: hotkey.clone(), + netuid, + position_id, + liquidity: liquidity_delta, + tao: (result.tao as i64).neg(), + alpha: (result.alpha as i64).neg(), + fee_tao: result.fee_tao, + fee_alpha: result.fee_alpha, + }); + } + } + + // Credit accrued fees to user account (no matter if liquidity is added or removed) + if result.fee_tao > 0 { + T::BalanceOps::increase_balance(&coldkey, result.fee_tao); + } + if result.fee_alpha > 0 { + T::BalanceOps::increase_stake( + &coldkey, + &hotkey.clone(), + netuid.into(), + result.fee_alpha, + )?; + } + + Ok(()) + } + } +} diff --git a/pallets/swap/src/pallet/tests.rs b/pallets/swap/src/pallet/tests.rs new file mode 100644 index 0000000000..07d1c63b89 --- /dev/null +++ b/pallets/swap/src/pallet/tests.rs @@ -0,0 +1,1733 @@ +#![allow(clippy::unwrap_used)] +#![allow(clippy::indexing_slicing)] +#![allow(clippy::arithmetic_side_effects)] + +use approx::assert_abs_diff_eq; +use frame_support::{assert_err, assert_noop, assert_ok}; +use sp_arithmetic::helpers_128bit; +use sp_runtime::DispatchError; +use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; + +use super::*; +use crate::{OrderType, SqrtPrice, mock::*}; + +// this function is used to convert price (NON-SQRT price!) to TickIndex. it's only utility for +// testing, all the implementation logic is based on sqrt prices +fn price_to_tick(price: f64) -> TickIndex { + let price_sqrt: SqrtPrice = SqrtPrice::from_num(price.sqrt()); + // Handle potential errors in the conversion + match TickIndex::try_from_sqrt_price(price_sqrt) { + Ok(mut tick) => { + // Ensure the tick is within bounds + if tick > TickIndex::MAX { + tick = TickIndex::MAX; + } else if tick < TickIndex::MIN { + tick = TickIndex::MIN; + } + tick + } + // Default to a reasonable value when conversion fails + Err(_) => { + if price > 1.0 { + TickIndex::MAX + } else { + TickIndex::MIN + } + } + } +} + +fn get_ticked_prices_around_current_price() -> (f64, f64) { + // Get current price, ticks around it, and prices on the tick edges for test cases + let netuid = NetUid::from(1); + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + let current_tick = CurrentTick::::get(netuid); + + // Low and high prices that match to a lower and higher tick that doesn't contain the current price + let current_price_low_sqrt = current_tick.as_sqrt_price_bounded(); + let current_price_high_sqrt = current_tick.next().unwrap().as_sqrt_price_bounded(); + let current_price_low = U96F32::from_num(current_price_low_sqrt * current_price_low_sqrt); + let current_price_high = U96F32::from_num(current_price_high_sqrt * current_price_high_sqrt); + + ( + current_price_low.to_num::(), + current_price_high.to_num::() + 0.000000001, + ) +} + +// this function is used to convert tick index NON-SQRT (!) price. it's only utility for +// testing, all the implementation logic is based on sqrt prices +fn tick_to_price(tick: TickIndex) -> f64 { + // Handle errors gracefully + match tick.try_to_sqrt_price() { + Ok(price_sqrt) => (price_sqrt * price_sqrt).to_num::(), + Err(_) => { + // Return a sensible default based on whether the tick is above or below the valid range + if tick > TickIndex::MAX { + tick_to_price(TickIndex::MAX) // Use the max valid tick price + } else { + tick_to_price(TickIndex::MIN) // Use the min valid tick price + } + } + } +} + +mod dispatchables { + use super::*; + + #[test] + fn test_set_fee_rate() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let fee_rate = 500; // 0.76% fee + + assert_noop!( + Swap::set_fee_rate(RuntimeOrigin::signed(666), netuid, fee_rate), + DispatchError::BadOrigin + ); + + assert_ok!(Swap::set_fee_rate(RuntimeOrigin::root(), netuid, fee_rate)); + + // Check that fee rate was set correctly + assert_eq!(FeeRate::::get(netuid), fee_rate); + + let fee_rate = fee_rate * 2; + assert_ok!(Swap::set_fee_rate( + RuntimeOrigin::signed(1), + netuid, + fee_rate + )); + assert_eq!(FeeRate::::get(netuid), fee_rate); + + // Verify fee rate validation - should fail if too high + let too_high_fee = MaxFeeRate::get() + 1; + assert_noop!( + Swap::set_fee_rate(RuntimeOrigin::root(), netuid, too_high_fee), + Error::::FeeRateTooHigh + ); + }); + } + + #[test] + fn test_toggle_user_liquidity() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(101); + + assert!(!EnabledUserLiquidity::::get(netuid)); + + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::root(), + netuid.into(), + true + )); + + assert!(EnabledUserLiquidity::::get(netuid)); + + assert_noop!( + Swap::toggle_user_liquidity(RuntimeOrigin::signed(666), netuid.into(), true), + DispatchError::BadOrigin + ); + + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::signed(1), + netuid.into(), + true + )); + + assert_noop!( + Swap::toggle_user_liquidity( + RuntimeOrigin::root(), + NON_EXISTENT_NETUID.into(), + true + ), + Error::::SubNetworkDoesNotExist + ); + }); + } +} + +#[test] +fn test_swap_initialization() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + // Get reserves from the mock provider + let tao = MockLiquidityProvider::tao_reserve(netuid.into()); + let alpha = MockLiquidityProvider::alpha_reserve(netuid.into()); + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + assert!(SwapV3Initialized::::get(netuid)); + + // Verify current price is set + let sqrt_price = AlphaSqrtPrice::::get(netuid); + let expected_sqrt_price = U64F64::from_num(0.5_f64); + assert_abs_diff_eq!( + sqrt_price.to_num::(), + expected_sqrt_price.to_num::(), + epsilon = 0.000000001 + ); + + // Verify that current tick is set + let current_tick = CurrentTick::::get(netuid); + let expected_current_tick = TickIndex::from_sqrt_price_bounded(expected_sqrt_price); + assert_eq!(current_tick, expected_current_tick); + + // Calculate expected liquidity + let expected_liquidity = + helpers_128bit::sqrt((tao as u128).saturating_mul(alpha as u128)) as u64; + + // Get the protocol account + let protocol_account_id = Pallet::::protocol_account_id(); + + // Verify position created for protocol account + let positions = Positions::::iter_prefix_values((netuid, protocol_account_id)) + .collect::>(); + assert_eq!(positions.len(), 1); + + let position = &positions[0]; + assert_eq!(position.liquidity, expected_liquidity); + assert_eq!(position.tick_low, TickIndex::MIN); + assert_eq!(position.tick_high, TickIndex::MAX); + assert_eq!(position.fees_tao, 0); + assert_eq!(position.fees_alpha, 0); + + // Verify ticks were created + let tick_low = Ticks::::get(netuid, TickIndex::MIN).unwrap(); + let tick_high = Ticks::::get(netuid, TickIndex::MAX).unwrap(); + + // Check liquidity values + assert_eq!(tick_low.liquidity_net, expected_liquidity as i128); + assert_eq!(tick_low.liquidity_gross, expected_liquidity); + assert_eq!(tick_high.liquidity_net, -(expected_liquidity as i128)); + assert_eq!(tick_high.liquidity_gross, expected_liquidity); + + // Verify current liquidity is set + assert_eq!(CurrentLiquidity::::get(netuid), expected_liquidity); + }); +} + +// Test adding liquidity on top of the existing protocol liquidity +#[test] +fn test_add_liquidity_basic() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + assert_eq!(max_tick, TickIndex::MAX); + + assert_ok!(Pallet::::maybe_initialize_v3(NetUid::from(1))); + let current_price = Pallet::::current_price(NetUid::from(1)).to_num::(); + let (current_price_low, current_price_high) = get_ticked_prices_around_current_price(); + + // As a user add liquidity with all possible corner cases + // - Initial price is 0.25 + // - liquidity is expressed in RAO units + // Test case is (price_low, price_high, liquidity, tao, alpha) + [ + // Repeat the protocol liquidity at maximum range: Expect all the same values + ( + min_price, + max_price, + 2_000_000_000_u64, + 1_000_000_000_u64, + 4_000_000_000_u64, + ), + // Repeat the protocol liquidity at current to max range: Expect the same alpha + ( + current_price_high, + max_price, + 2_000_000_000_u64, + 0, + 4_000_000_000, + ), + // Repeat the protocol liquidity at min to current range: Expect all the same tao + ( + min_price, + current_price_low, + 2_000_000_000_u64, + 1_000_000_000, + 0, + ), + // Half to double price - just some sane wothdraw amounts + (0.125, 0.5, 2_000_000_000_u64, 293_000_000, 1_171_000_000), + // Both below price - tao is non-zero, alpha is zero + (0.12, 0.13, 2_000_000_000_u64, 28_270_000, 0), + // Both above price - tao is zero, alpha is non-zero + (0.3, 0.4, 2_000_000_000_u64, 0, 489_200_000), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2, v.3, v.4)) + .for_each( + |(netuid, price_low, price_high, liquidity, expected_tao, expected_alpha)| { + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Calculate ticks (assuming tick math is tested separately) + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + + // Get tick infos and liquidity before adding (to account for protocol liquidity) + let tick_low_info_before = Ticks::::get(netuid, tick_low).unwrap_or_default(); + let tick_high_info_before = + Ticks::::get(netuid, tick_high).unwrap_or_default(); + let liquidity_before = CurrentLiquidity::::get(netuid); + + // Add liquidity + let (position_id, tao, alpha) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + assert_abs_diff_eq!(tao, expected_tao, epsilon = tao / 1000); + assert_abs_diff_eq!(alpha, expected_alpha, epsilon = alpha / 1000); + + // Check that low and high ticks appear in the state and are properly updated + let tick_low_info = Ticks::::get(netuid, tick_low).unwrap(); + let tick_high_info = Ticks::::get(netuid, tick_high).unwrap(); + let expected_liquidity_net_low = liquidity as i128; + let expected_liquidity_gross_low = liquidity; + let expected_liquidity_net_high = -(liquidity as i128); + let expected_liquidity_gross_high = liquidity; + + assert_eq!( + tick_low_info.liquidity_net - tick_low_info_before.liquidity_net, + expected_liquidity_net_low, + ); + assert_eq!( + tick_low_info.liquidity_gross - tick_low_info_before.liquidity_gross, + expected_liquidity_gross_low, + ); + assert_eq!( + tick_high_info.liquidity_net - tick_high_info_before.liquidity_net, + expected_liquidity_net_high, + ); + assert_eq!( + tick_high_info.liquidity_gross - tick_high_info_before.liquidity_gross, + expected_liquidity_gross_high, + ); + + // Liquidity position at correct ticks + assert_eq!( + Pallet::::count_positions(netuid, &OK_COLDKEY_ACCOUNT_ID), + 1 + ); + + let position = + Positions::::get((netuid, OK_COLDKEY_ACCOUNT_ID, position_id)).unwrap(); + assert_eq!(position.liquidity, liquidity); + assert_eq!(position.tick_low, tick_low); + assert_eq!(position.tick_high, tick_high); + assert_eq!(position.fees_alpha, 0); + assert_eq!(position.fees_tao, 0); + + // Current liquidity is updated only when price range includes the current price + let expected_liquidity = + if (price_high > current_price) && (price_low <= current_price) { + liquidity_before + liquidity + } else { + liquidity_before + }; + + assert_eq!(CurrentLiquidity::::get(netuid), expected_liquidity) + }, + ); + }); +} + +#[test] +fn test_add_liquidity_out_of_bounds() { + new_test_ext().execute_with(|| { + [ + // For our tests, we'll construct TickIndex values that are intentionally + // outside the valid range for testing purposes only + ( + TickIndex::new_unchecked(TickIndex::MIN.get() - 1), + TickIndex::MAX, + 1_000_000_000_u64, + ), + ( + TickIndex::MIN, + TickIndex::new_unchecked(TickIndex::MAX.get() + 1), + 1_000_000_000_u64, + ), + ( + TickIndex::new_unchecked(TickIndex::MIN.get() - 1), + TickIndex::new_unchecked(TickIndex::MAX.get() + 1), + 1_000_000_000_u64, + ), + ( + TickIndex::new_unchecked(TickIndex::MIN.get() - 100), + TickIndex::new_unchecked(TickIndex::MAX.get() + 100), + 1_000_000_000_u64, + ), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2)) + .for_each(|(netuid, tick_low, tick_high, liquidity)| { + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Add liquidity + assert_err!( + Swap::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity + ), + Error::::InvalidTickRange, + ); + }); + }); +} + +#[test] +fn test_add_liquidity_over_balance() { + new_test_ext().execute_with(|| { + let coldkey_account_id = 3; + let hotkey_account_id = 1002; + + [ + // Lower than price (not enough tao) + (0.1, 0.2, 100_000_000_000_u64), + // Higher than price (not enough alpha) + (0.3, 0.4, 100_000_000_000_u64), + // Around the price (not enough both) + (0.1, 0.4, 100_000_000_000_u64), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2)) + .for_each(|(netuid, price_low, price_high, liquidity)| { + // Calculate ticks + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Add liquidity + assert_err!( + Pallet::::do_add_liquidity( + netuid, + &coldkey_account_id, + &hotkey_account_id, + tick_low, + tick_high, + liquidity + ), + Error::::InsufficientBalance, + ); + }); + }); +} + +// cargo test --package pallet-subtensor-swap --lib -- pallet::impls::tests::test_remove_liquidity_basic --exact --show-output +#[test] +fn test_remove_liquidity_basic() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + assert_eq!(max_tick, TickIndex::MAX); + + let (current_price_low, current_price_high) = get_ticked_prices_around_current_price(); + + // As a user add liquidity with all possible corner cases + // - Initial price is 0.25 + // - liquidity is expressed in RAO units + // Test case is (price_low, price_high, liquidity, tao, alpha) + [ + // Repeat the protocol liquidity at maximum range: Expect all the same values + ( + min_price, + max_price, + 2_000_000_000_u64, + 1_000_000_000_u64, + 4_000_000_000_u64, + ), + // Repeat the protocol liquidity at current to max range: Expect the same alpha + ( + current_price_high, + max_price, + 2_000_000_000_u64, + 0, + 4_000_000_000, + ), + // Repeat the protocol liquidity at min to current range: Expect all the same tao + ( + min_price, + current_price_low, + 2_000_000_000_u64, + 1_000_000_000, + 0, + ), + // Half to double price - just some sane wothdraw amounts + (0.125, 0.5, 2_000_000_000_u64, 293_000_000, 1_171_000_000), + // Both below price - tao is non-zero, alpha is zero + (0.12, 0.13, 2_000_000_000_u64, 28_270_000, 0), + // Both above price - tao is zero, alpha is non-zero + (0.3, 0.4, 2_000_000_000_u64, 0, 489_200_000), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2, v.3, v.4)) + .for_each(|(netuid, price_low, price_high, liquidity, tao, alpha)| { + // Calculate ticks (assuming tick math is tested separately) + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + let liquidity_before = CurrentLiquidity::::get(netuid); + + // Add liquidity + let (position_id, _, _) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + // Remove liquidity + let remove_result = + Pallet::::do_remove_liquidity(netuid, &OK_COLDKEY_ACCOUNT_ID, position_id) + .unwrap(); + assert_abs_diff_eq!(remove_result.tao, tao, epsilon = tao / 1000); + assert_abs_diff_eq!(remove_result.alpha, alpha, epsilon = alpha / 1000); + assert_eq!(remove_result.fee_tao, 0); + assert_eq!(remove_result.fee_alpha, 0); + + // Liquidity position is removed + assert_eq!( + Pallet::::count_positions(netuid, &OK_COLDKEY_ACCOUNT_ID), + 0 + ); + assert!(Positions::::get((netuid, OK_COLDKEY_ACCOUNT_ID, position_id)).is_none()); + + // Current liquidity is updated (back where it was) + assert_eq!(CurrentLiquidity::::get(netuid), liquidity_before); + }); + }); +} + +#[test] +fn test_remove_liquidity_nonexisting_position() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + assert_eq!(max_tick.get(), TickIndex::MAX.get()); + + let liquidity = 2_000_000_000_u64; + let netuid = NetUid::from(1); + + // Calculate ticks (assuming tick math is tested separately) + let tick_low = price_to_tick(min_price); + let tick_high = price_to_tick(max_price); + + // Setup swap + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Add liquidity + assert_ok!(Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + )); + + assert!(Pallet::::count_positions(netuid, &OK_COLDKEY_ACCOUNT_ID) > 0); + + // Remove liquidity + assert_err!( + Pallet::::do_remove_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + PositionId::new::() + ), + Error::::LiquidityNotFound, + ); + }); +} + +// cargo test --package pallet-subtensor-swap --lib -- pallet::tests::test_modify_position_basic --exact --show-output +#[test] +fn test_modify_position_basic() { + new_test_ext().execute_with(|| { + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + let limit_price = 1000.0_f64; + assert_eq!(max_tick, TickIndex::MAX); + let (current_price_low, _current_price_high) = get_ticked_prices_around_current_price(); + + // As a user add liquidity with all possible corner cases + // - Initial price is 0.25 + // - liquidity is expressed in RAO units + // Test case is (price_low, price_high, liquidity, tao, alpha) + [ + // Repeat the protocol liquidity at current to max range: Expect the same alpha + ( + current_price_low, + max_price, + 2_000_000_000_u64, + 4_000_000_000, + ), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2, v.3)) + .for_each(|(netuid, price_low, price_high, liquidity, alpha)| { + // Calculate ticks (assuming tick math is tested separately) + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Add liquidity + let (position_id, _, _) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + // Swap to create fees on the position + let sqrt_limit_price = SqrtPrice::from_num((limit_price).sqrt()); + Pallet::::do_swap( + netuid, + OrderType::Buy, + liquidity / 10, + sqrt_limit_price, + false, + ) + .unwrap(); + + // Modify liquidity (also causes claiming of fees) + let liquidity_before = CurrentLiquidity::::get(netuid); + let modify_result = Pallet::::do_modify_position( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + position_id, + -((liquidity / 10) as i64), + ) + .unwrap(); + assert_abs_diff_eq!(modify_result.alpha, alpha / 10, epsilon = alpha / 1000); + assert!(modify_result.fee_tao > 0); + assert_eq!(modify_result.fee_alpha, 0); + + // Liquidity position is reduced + assert_eq!( + Pallet::::count_positions(netuid, &OK_COLDKEY_ACCOUNT_ID), + 1 + ); + + // Current liquidity is reduced with modify_position + assert!(CurrentLiquidity::::get(netuid) < liquidity_before); + + // Position liquidity is reduced + let position = + Positions::::get((netuid, OK_COLDKEY_ACCOUNT_ID, position_id)).unwrap(); + assert_eq!(position.liquidity, liquidity * 9 / 10); + assert_eq!(position.tick_low, tick_low); + assert_eq!(position.tick_high, tick_high); + + // Modify liquidity again (ensure fees aren't double-collected) + let modify_result = Pallet::::do_modify_position( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + position_id, + -((liquidity / 100) as i64), + ) + .unwrap(); + + assert_abs_diff_eq!(modify_result.alpha, alpha / 100, epsilon = alpha / 1000); + assert_eq!(modify_result.fee_tao, 0); + assert_eq!(modify_result.fee_alpha, 0); + }); + }); +} + +// cargo test --package pallet-subtensor-swap --lib -- pallet::impls::tests::test_swap_basic --exact --show-output +#[test] +fn test_swap_basic() { + new_test_ext().execute_with(|| { + // Current price is 0.25 + // Test case is (order_type, liquidity, limit_price, output_amount) + [ + (OrderType::Buy, 1_000u64, 1000.0_f64, 3990_u64), + (OrderType::Sell, 1_000u64, 0.0001_f64, 250_u64), + (OrderType::Buy, 500_000_000, 1000.0, 2_000_000_000), + ] + .into_iter() + .enumerate() + .map(|(n, v)| (NetUid::from(n as u16 + 1), v.0, v.1, v.2, v.3)) + .for_each( + |(netuid, order_type, liquidity, limit_price, output_amount)| { + // Consumed liquidity ticks + let tick_low = TickIndex::MIN; + let tick_high = TickIndex::MAX; + + // Setup swap + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Get tick infos before the swap + let tick_low_info_before = Ticks::::get(netuid, tick_low).unwrap_or_default(); + let tick_high_info_before = + Ticks::::get(netuid, tick_high).unwrap_or_default(); + let liquidity_before = CurrentLiquidity::::get(netuid); + + // Get current price + let current_price = Pallet::::current_price(netuid); + + // Swap + let sqrt_limit_price = SqrtPrice::from_num((limit_price).sqrt()); + let swap_result = + Pallet::::do_swap(netuid, order_type, liquidity, sqrt_limit_price, false) + .unwrap(); + assert_abs_diff_eq!( + swap_result.amount_paid_out, + output_amount, + epsilon = output_amount / 100 + ); + + let (tao_delta_expected, alpha_delta_expected) = match order_type { + OrderType::Buy => (liquidity as i64, -(output_amount as i64)), + OrderType::Sell => (-(output_amount as i64), liquidity as i64), + }; + + assert_abs_diff_eq!( + swap_result.alpha_reserve_delta, + alpha_delta_expected, + epsilon = alpha_delta_expected.abs() / 10 + ); + assert_abs_diff_eq!( + swap_result.tao_reserve_delta, + tao_delta_expected, + epsilon = tao_delta_expected.abs() / 10 + ); + + // Check that low and high ticks' fees were updated properly, and liquidity values were not updated + let tick_low_info = Ticks::::get(netuid, tick_low).unwrap(); + let tick_high_info = Ticks::::get(netuid, tick_high).unwrap(); + let expected_liquidity_net_low = tick_low_info_before.liquidity_net; + let expected_liquidity_gross_low = tick_low_info_before.liquidity_gross; + let expected_liquidity_net_high = tick_high_info_before.liquidity_net; + let expected_liquidity_gross_high = tick_high_info_before.liquidity_gross; + assert_eq!(tick_low_info.liquidity_net, expected_liquidity_net_low,); + assert_eq!(tick_low_info.liquidity_gross, expected_liquidity_gross_low,); + assert_eq!(tick_high_info.liquidity_net, expected_liquidity_net_high,); + assert_eq!( + tick_high_info.liquidity_gross, + expected_liquidity_gross_high, + ); + + // Expected fee amount + let fee_rate = FeeRate::::get(netuid) as f64 / u16::MAX as f64; + let expected_fee = (liquidity as f64 * fee_rate) as u64; + + // Global fees should be updated + let actual_global_fee = ((match order_type { + OrderType::Buy => FeeGlobalTao::::get(netuid), + OrderType::Sell => FeeGlobalAlpha::::get(netuid), + }) + .to_num::() + * (liquidity_before as f64)) as u64; + + assert!((swap_result.fee_paid as i64 - expected_fee as i64).abs() <= 1); + assert!((actual_global_fee as i64 - expected_fee as i64).abs() <= 1); + + // Tick fees should be updated + + // Liquidity position should not be updated + let protocol_id = Pallet::::protocol_account_id(); + let positions = Positions::::iter_prefix_values((netuid, protocol_id)) + .collect::>(); + let position = positions.first().unwrap(); + + assert_eq!( + position.liquidity, + helpers_128bit::sqrt( + MockLiquidityProvider::tao_reserve(netuid.into()) as u128 + * MockLiquidityProvider::alpha_reserve(netuid.into()) as u128 + ) as u64 + ); + assert_eq!(position.tick_low, tick_low); + assert_eq!(position.tick_high, tick_high); + assert_eq!(position.fees_alpha, 0); + assert_eq!(position.fees_tao, 0); + + // Current liquidity is not updated + assert_eq!(CurrentLiquidity::::get(netuid), liquidity_before); + + // Assert that price movement is in correct direction + let sqrt_current_price_after = Pallet::::current_price_sqrt(netuid); + let current_price_after = Pallet::::current_price(netuid); + match order_type { + OrderType::Buy => assert!(current_price_after >= current_price), + OrderType::Sell => assert!(current_price_after <= current_price), + } + + // Assert that current tick is updated + let current_tick = CurrentTick::::get(netuid); + let expected_current_tick = + TickIndex::from_sqrt_price_bounded(sqrt_current_price_after); + assert_eq!(current_tick, expected_current_tick); + }, + ); + }); +} + +// In this test the swap starts and ends within one (large liquidity) position +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor-swap --lib -- pallet::tests::test_swap_single_position --exact --show-output +#[test] +fn test_swap_single_position() { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + let netuid = NetUid::from(1); + assert_eq!(max_tick, TickIndex::MAX); + + let mut current_price_low = 0_f64; + let mut current_price_high = 0_f64; + let mut current_price = 0_f64; + new_test_ext().execute_with(|| { + let (low, high) = get_ticked_prices_around_current_price(); + current_price_low = low; + current_price_high = high; + current_price = Pallet::::current_price(netuid).to_num::(); + }); + + // Current price is 0.25 + // The test case is based on the current price and position prices are defined as a price + // offset from the current price + // Outer part of test case is Position: (price_low_offset, price_high_offset, liquidity) + [ + // Very localized position at the current price + (-0.1, 0.1, 500_000_000_000_u64), + // Repeat the protocol liquidity at maximum range + ( + min_price - current_price, + max_price - current_price, + 2_000_000_000_u64, + ), + // Repeat the protocol liquidity at current to max range + ( + current_price_high - current_price, + max_price - current_price, + 2_000_000_000_u64, + ), + // Repeat the protocol liquidity at min to current range + ( + min_price - current_price, + current_price_low - current_price, + 2_000_000_000_u64, + ), + // Half to double price + (-0.125, 0.25, 2_000_000_000_u64), + // A few other price ranges and liquidity volumes + (-0.1, 0.1, 2_000_000_000_u64), + (-0.1, 0.1, 10_000_000_000_u64), + (-0.1, 0.1, 100_000_000_000_u64), + (-0.01, 0.01, 100_000_000_000_u64), + (-0.001, 0.001, 100_000_000_000_u64), + ] + .into_iter() + .for_each( + |(price_low_offset, price_high_offset, position_liquidity)| { + // Inner part of test case is Order: (order_type, order_liquidity, limit_price) + // order_liquidity is represented as a fraction of position_liquidity + [ + (OrderType::Buy, 0.0001, 1000.0_f64), + (OrderType::Sell, 0.0001, 0.0001_f64), + (OrderType::Buy, 0.001, 1000.0_f64), + (OrderType::Sell, 0.001, 0.0001_f64), + (OrderType::Buy, 0.01, 1000.0_f64), + (OrderType::Sell, 0.01, 0.0001_f64), + (OrderType::Buy, 0.1, 1000.0_f64), + (OrderType::Sell, 0.1, 0.0001), + (OrderType::Buy, 0.2, 1000.0_f64), + (OrderType::Sell, 0.2, 0.0001), + (OrderType::Buy, 0.5, 1000.0), + (OrderType::Sell, 0.5, 0.0001), + ] + .into_iter() + .for_each(|(order_type, order_liquidity_fraction, limit_price)| { + new_test_ext().execute_with(|| { + ////////////////////////////////////////////// + // Initialize pool and add the user position + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + let tao_reserve = MockLiquidityProvider::tao_reserve(netuid.into()); + let alpha_reserve = MockLiquidityProvider::alpha_reserve(netuid.into()); + let protocol_liquidity = (tao_reserve as f64 * alpha_reserve as f64).sqrt(); + + // Add liquidity + let current_price = Pallet::::current_price(netuid).to_num::(); + let sqrt_current_price = + Pallet::::current_price_sqrt(netuid).to_num::(); + + let price_low = price_low_offset + current_price; + let price_high = price_high_offset + current_price; + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + let (_position_id, _tao, _alpha) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + position_liquidity, + ) + .unwrap(); + + // Liquidity position at correct ticks + assert_eq!( + Pallet::::count_positions(netuid, &OK_COLDKEY_ACCOUNT_ID), + 1 + ); + + // Get tick infos before the swap + let tick_low_info_before = + Ticks::::get(netuid, tick_low).unwrap_or_default(); + let tick_high_info_before = + Ticks::::get(netuid, tick_high).unwrap_or_default(); + let liquidity_before = CurrentLiquidity::::get(netuid); + assert_abs_diff_eq!( + liquidity_before as f64, + protocol_liquidity + position_liquidity as f64, + epsilon = liquidity_before as f64 / 1000. + ); + + ////////////////////////////////////////////// + // Swap + + // Calculate the expected output amount for the cornercase of one step + let order_liquidity = order_liquidity_fraction * position_liquidity as f64; + + let output_amount = match order_type { + OrderType::Buy => { + let denom = sqrt_current_price + * (sqrt_current_price * liquidity_before as f64 + order_liquidity); + let per_order_liq = liquidity_before as f64 / denom; + per_order_liq * order_liquidity + } + OrderType::Sell => { + let denom = + liquidity_before as f64 / sqrt_current_price + order_liquidity; + let per_order_liq = + sqrt_current_price * liquidity_before as f64 / denom; + per_order_liq * order_liquidity + } + }; + + // Do the swap + let sqrt_limit_price = SqrtPrice::from_num((limit_price).sqrt()); + let swap_result = Pallet::::do_swap( + netuid, + order_type, + order_liquidity as u64, + sqrt_limit_price, + false, + ) + .unwrap(); + assert_abs_diff_eq!( + swap_result.amount_paid_out as f64, + output_amount, + epsilon = output_amount / 10. + ); + + if order_liquidity_fraction <= 0.001 { + let (tao_delta_expected, alpha_delta_expected) = match order_type { + OrderType::Buy => (order_liquidity as i64, -(output_amount as i64)), + OrderType::Sell => (-(output_amount as i64), order_liquidity as i64), + }; + assert_abs_diff_eq!( + swap_result.alpha_reserve_delta, + alpha_delta_expected, + epsilon = alpha_delta_expected.abs() / 10 + ); + assert_abs_diff_eq!( + swap_result.tao_reserve_delta, + tao_delta_expected, + epsilon = tao_delta_expected.abs() / 10 + ); + } + + // Assert that price movement is in correct direction + let current_price_after = Pallet::::current_price(netuid); + match order_type { + OrderType::Buy => assert!(current_price_after > current_price), + OrderType::Sell => assert!(current_price_after < current_price), + } + + // Assert that for small amounts price stays within the user position + if (order_liquidity_fraction <= 0.001) + && (price_low_offset > 0.0001) + && (price_high_offset > 0.0001) + { + assert!(current_price_after <= price_high); + assert!(current_price_after >= price_low); + } + + // Check that low and high ticks' fees were updated properly + let tick_low_info = Ticks::::get(netuid, tick_low).unwrap(); + let tick_high_info = Ticks::::get(netuid, tick_high).unwrap(); + let expected_liquidity_net_low = tick_low_info_before.liquidity_net; + let expected_liquidity_gross_low = tick_low_info_before.liquidity_gross; + let expected_liquidity_net_high = tick_high_info_before.liquidity_net; + let expected_liquidity_gross_high = tick_high_info_before.liquidity_gross; + assert_eq!(tick_low_info.liquidity_net, expected_liquidity_net_low,); + assert_eq!(tick_low_info.liquidity_gross, expected_liquidity_gross_low,); + assert_eq!(tick_high_info.liquidity_net, expected_liquidity_net_high,); + assert_eq!( + tick_high_info.liquidity_gross, + expected_liquidity_gross_high, + ); + + // Expected fee amount + let fee_rate = FeeRate::::get(netuid) as f64 / u16::MAX as f64; + let expected_fee = + (order_liquidity - order_liquidity / (1.0 + fee_rate)) as u64; + + // Global fees should be updated + let actual_global_fee = ((match order_type { + OrderType::Buy => FeeGlobalTao::::get(netuid), + OrderType::Sell => FeeGlobalAlpha::::get(netuid), + }) + .to_num::() + * (liquidity_before as f64)) + as u64; + + assert_abs_diff_eq!( + swap_result.fee_paid, + expected_fee, + epsilon = expected_fee / 10 + ); + assert_abs_diff_eq!( + actual_global_fee, + expected_fee, + epsilon = expected_fee / 10 + ); + + // Tick fees should be updated + + // Liquidity position should not be updated + let positions = + Positions::::iter_prefix_values((netuid, OK_COLDKEY_ACCOUNT_ID)) + .collect::>(); + let position = positions.first().unwrap(); + + assert_eq!(position.liquidity, position_liquidity,); + assert_eq!(position.tick_low, tick_low); + assert_eq!(position.tick_high, tick_high); + assert_eq!(position.fees_alpha, 0); + assert_eq!(position.fees_tao, 0); + }); + }); + }, + ); +} + +// This test is a sanity check for swap and multiple positions +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor-swap --lib -- pallet::impls::tests::test_swap_multiple_positions --exact --show-output --nocapture +#[test] +fn test_swap_multiple_positions() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let max_tick = price_to_tick(max_price); + let netuid = NetUid::from(1); + assert_eq!(max_tick, TickIndex::MAX); + + ////////////////////////////////////////////// + // Initialize pool and add the user position + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Add liquidity + let current_price = Pallet::::current_price(netuid).to_num::(); + + // Current price is 0.25 + // All positions below are placed at once + [ + // Very localized position at the current price + (-0.1, 0.1, 500_000_000_000_u64), + // Repeat the protocol liquidity at maximum range + ( + min_price - current_price, + max_price - current_price, + 2_000_000_000_u64, + ), + // Repeat the protocol liquidity at current to max range + (0.0, max_price - current_price, 2_000_000_000_u64), + // Repeat the protocol liquidity at min to current range + (min_price - current_price, 0.0, 2_000_000_000_u64), + // Half to double price + (-0.125, 0.25, 2_000_000_000_u64), + // A few other price ranges and liquidity volumes + (-0.1, 0.1, 2_000_000_000_u64), + (-0.1, 0.1, 10_000_000_000_u64), + (-0.1, 0.1, 100_000_000_000_u64), + (-0.01, 0.01, 100_000_000_000_u64), + (-0.001, 0.001, 100_000_000_000_u64), + // A few (overlapping) positions up the range + (0.01, 0.02, 100_000_000_000_u64), + (0.02, 0.03, 100_000_000_000_u64), + (0.03, 0.04, 100_000_000_000_u64), + (0.03, 0.05, 100_000_000_000_u64), + // A few (overlapping) positions down the range + (-0.02, -0.01, 100_000_000_000_u64), + (-0.03, -0.02, 100_000_000_000_u64), + (-0.04, -0.03, 100_000_000_000_u64), + (-0.05, -0.03, 100_000_000_000_u64), + ] + .into_iter() + .for_each( + |(price_low_offset, price_high_offset, position_liquidity)| { + let price_low = price_low_offset + current_price; + let price_high = price_high_offset + current_price; + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + let (_position_id, _tao, _alpha) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + position_liquidity, + ) + .unwrap(); + }, + ); + + // All these orders are executed without swap reset + [ + (OrderType::Buy, 100_000_u64, 1000.0_f64), + (OrderType::Sell, 100_000, 0.0001_f64), + (OrderType::Buy, 1_000_000, 1000.0_f64), + (OrderType::Sell, 1_000_000, 0.0001_f64), + (OrderType::Buy, 10_000_000, 1000.0_f64), + (OrderType::Sell, 10_000_000, 0.0001_f64), + (OrderType::Buy, 100_000_000, 1000.0), + (OrderType::Sell, 100_000_000, 0.0001), + (OrderType::Buy, 200_000_000, 1000.0_f64), + (OrderType::Sell, 200_000_000, 0.0001), + (OrderType::Buy, 500_000_000, 1000.0), + (OrderType::Sell, 500_000_000, 0.0001), + (OrderType::Buy, 1_000_000_000, 1000.0), + (OrderType::Sell, 1_000_000_000, 0.0001), + (OrderType::Buy, 10_000_000_000, 1000.0), + (OrderType::Sell, 10_000_000_000, 0.0001), + ] + .into_iter() + .for_each(|(order_type, order_liquidity, limit_price)| { + ////////////////////////////////////////////// + // Swap + let sqrt_current_price = Pallet::::current_price_sqrt(netuid); + let current_price = (sqrt_current_price * sqrt_current_price).to_num::(); + let liquidity_before = CurrentLiquidity::::get(netuid); + + let output_amount = match order_type { + OrderType::Buy => { + let denom = sqrt_current_price.to_num::() + * (sqrt_current_price.to_num::() * liquidity_before as f64 + + order_liquidity as f64); + let per_order_liq = liquidity_before as f64 / denom; + per_order_liq * order_liquidity as f64 + } + OrderType::Sell => { + let denom = liquidity_before as f64 / sqrt_current_price.to_num::() + + order_liquidity as f64; + let per_order_liq = + sqrt_current_price.to_num::() * liquidity_before as f64 / denom; + per_order_liq * order_liquidity as f64 + } + }; + + // Do the swap + let sqrt_limit_price = SqrtPrice::from_num((limit_price).sqrt()); + let swap_result = Pallet::::do_swap( + netuid, + order_type, + order_liquidity, + sqrt_limit_price, + false, + ) + .unwrap(); + assert_abs_diff_eq!( + swap_result.amount_paid_out as f64, + output_amount, + epsilon = output_amount / 10. + ); + + let tao_reserve = MockLiquidityProvider::tao_reserve(netuid.into()); + let alpha_reserve = MockLiquidityProvider::alpha_reserve(netuid.into()); + let output_amount = output_amount as u64; + + assert!(output_amount > 0); + + if alpha_reserve > order_liquidity && tao_reserve > order_liquidity { + let (tao_delta_expected, alpha_delta_expected) = match order_type { + OrderType::Buy => (order_liquidity as i64, -(output_amount as i64)), + OrderType::Sell => (-(output_amount as i64), order_liquidity as i64), + }; + assert_abs_diff_eq!( + swap_result.alpha_reserve_delta, + alpha_delta_expected, + epsilon = alpha_delta_expected.abs() / 100 + ); + assert_abs_diff_eq!( + swap_result.tao_reserve_delta, + tao_delta_expected, + epsilon = tao_delta_expected.abs() / 100 + ); + } + + // Assert that price movement is in correct direction + let sqrt_current_price_after = Pallet::::current_price_sqrt(netuid); + let current_price_after = + (sqrt_current_price_after * sqrt_current_price_after).to_num::(); + match order_type { + OrderType::Buy => assert!(current_price_after > current_price), + OrderType::Sell => assert!(current_price_after < current_price), + } + }); + + // Current price shouldn't be much different from the original + let sqrt_current_price_after = Pallet::::current_price_sqrt(netuid); + let current_price_after = + (sqrt_current_price_after * sqrt_current_price_after).to_num::(); + assert_abs_diff_eq!( + current_price, + current_price_after, + epsilon = current_price / 10. + ) + }); +} + +// cargo test --package pallet-subtensor-swap --lib -- pallet::impls::tests::test_swap_precision_edge_case --exact --show-output +#[test] +fn test_swap_precision_edge_case() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(123); // 123 is netuid with low edge case liquidity + let order_type = OrderType::Sell; + let liquidity = 1_000_000_000_000_000_000; + let tick_low = TickIndex::MIN; + + let sqrt_limit_price: SqrtPrice = tick_low.try_to_sqrt_price().unwrap(); + + // Setup swap + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Swap + let swap_result = + Pallet::::do_swap(netuid, order_type, liquidity, sqrt_limit_price, true).unwrap(); + + assert!(swap_result.amount_paid_out > 0); + }); +} + +// cargo test --package pallet-subtensor-swap --lib -- pallet::impls::tests::test_price_tick_price_roundtrip --exact --show-output +#[test] +fn test_price_tick_price_roundtrip() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + // Setup swap + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + let current_price = SqrtPrice::from_num(0.500_000_512_192_122_7); + let tick = TickIndex::try_from_sqrt_price(current_price).unwrap(); + + let round_trip_price = TickIndex::try_to_sqrt_price(&tick).unwrap(); + assert!(round_trip_price <= current_price); + + let roundtrip_tick = TickIndex::try_from_sqrt_price(round_trip_price).unwrap(); + assert!(tick == roundtrip_tick); + }); +} + +#[test] +fn test_convert_deltas() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + for (sqrt_price, delta_in, expected_buy, expected_sell) in [ + (SqrtPrice::from_num(1.5), 1, 0, 2), + (SqrtPrice::from_num(1.5), 10000, 4444, 22500), + (SqrtPrice::from_num(1.5), 1000000, 444444, 2250000), + ( + SqrtPrice::from_num(1.5), + u64::MAX, + 2000000000000, + 3000000000000, + ), + ( + TickIndex::MIN.as_sqrt_price_bounded(), + 1, + 18406523739291577836, + 465, + ), + (TickIndex::MIN.as_sqrt_price_bounded(), 10000, u64::MAX, 465), + ( + TickIndex::MIN.as_sqrt_price_bounded(), + 1000000, + u64::MAX, + 465, + ), + ( + TickIndex::MIN.as_sqrt_price_bounded(), + u64::MAX, + u64::MAX, + 464, + ), + ( + TickIndex::MAX.as_sqrt_price_bounded(), + 1, + 0, + 18406523745214495085, + ), + (TickIndex::MAX.as_sqrt_price_bounded(), 10000, 0, u64::MAX), + (TickIndex::MAX.as_sqrt_price_bounded(), 1000000, 0, u64::MAX), + ( + TickIndex::MAX.as_sqrt_price_bounded(), + u64::MAX, + 2000000000000, + u64::MAX, + ), + ] { + { + AlphaSqrtPrice::::insert(netuid, sqrt_price); + + assert_abs_diff_eq!( + Pallet::::convert_deltas(netuid, OrderType::Sell, delta_in), + expected_sell, + epsilon = 2 + ); + assert_abs_diff_eq!( + Pallet::::convert_deltas(netuid, OrderType::Buy, delta_in), + expected_buy, + epsilon = 2 + ); + } + } + }); +} + +#[test] +fn test_user_liquidity_disabled() { + new_test_ext().execute_with(|| { + // Use a netuid above 100 since our mock enables liquidity for 0-100 + let netuid = NetUid::from(101); + let tick_low = TickIndex::new_unchecked(-1000); + let tick_high = TickIndex::new_unchecked(1000); + let position_id = PositionId::from(1); + let liquidity = 1_000_000_000; + let liquidity_delta = 500_000_000; + + assert!(!EnabledUserLiquidity::::get(netuid)); + + assert_noop!( + Swap::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity + ), + Error::::UserLiquidityDisabled + ); + + assert_noop!( + Swap::do_remove_liquidity(netuid, &OK_COLDKEY_ACCOUNT_ID, position_id), + Error::::LiquidityNotFound + ); + + assert_noop!( + Swap::modify_position( + RuntimeOrigin::signed(OK_COLDKEY_ACCOUNT_ID), + OK_HOTKEY_ACCOUNT_ID, + netuid, + position_id, + liquidity_delta + ), + Error::::UserLiquidityDisabled + ); + + assert_ok!(Swap::toggle_user_liquidity( + RuntimeOrigin::root(), + netuid, + true + )); + + let position_id = Swap::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap() + .0; + + assert_ok!(Swap::do_modify_position( + netuid.into(), + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + position_id, + liquidity_delta, + )); + + assert_ok!(Swap::do_remove_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + position_id, + )); + }); +} + +/// Test correctness of swap fees: +/// - Fees are distribued to (concentrated) liquidity providers +/// +#[test] +fn test_swap_fee_correctness() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let netuid = NetUid::from(1); + + // Provide very spread liquidity at the range from min to max that matches protocol liquidity + let liquidity = 2_000_000_000_000_u64; // 1x of protocol liquidity + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Calculate ticks + let tick_low = price_to_tick(min_price); + let tick_high = price_to_tick(max_price); + + // Add user liquidity + let (position_id, _tao, _alpha) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + // Swap buy and swap sell + Pallet::::do_swap( + netuid, + OrderType::Buy, + liquidity / 10, + u64::MAX.into(), + false, + ) + .unwrap(); + Pallet::::do_swap(netuid, OrderType::Sell, liquidity / 10, 0_u64.into(), false) + .unwrap(); + + // Get user position + let mut position = + Positions::::get((netuid, OK_COLDKEY_ACCOUNT_ID, position_id)).unwrap(); + assert_eq!(position.liquidity, liquidity); + assert_eq!(position.tick_low, tick_low); + assert_eq!(position.tick_high, tick_high); + + // Check that 50% of fees were credited to the position + let fee_rate = FeeRate::::get(NetUid::from(netuid)) as f64 / u16::MAX as f64; + let (actual_fee_tao, actual_fee_alpha) = position.collect_fees(); + let expected_fee = (fee_rate * (liquidity / 10) as f64 * 0.5) as u64; + + assert_abs_diff_eq!(actual_fee_tao, expected_fee, epsilon = 1,); + assert_abs_diff_eq!(actual_fee_alpha, expected_fee, epsilon = 1,); + }); +} + +#[test] +fn test_current_liquidity_updates() { + let netuid = NetUid::from(1); + let liquidity = 1_000_000_000; + + // Get current price + let (current_price, current_price_low, current_price_high) = + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + let sqrt_current_price = AlphaSqrtPrice::::get(netuid); + let current_price = (sqrt_current_price * sqrt_current_price).to_num::(); + let (current_price_low, current_price_high) = get_ticked_prices_around_current_price(); + (current_price, current_price_low, current_price_high) + }); + + // Test case: (price_low, price_high, expect_to_update) + [ + // Current price is out of position range (lower), no current lq update + (current_price * 2., current_price * 3., false), + // Current price is out of position range (higher), no current lq update + (current_price / 3., current_price / 2., false), + // Current price is just below position range, no current lq update + (current_price_high, current_price * 3., false), + // Position lower edge is just below the current price, current lq updates + (current_price_low, current_price * 3., true), + // Current price is exactly at lower edge of position range, current lq updates + (current_price, current_price * 3., true), + // Current price is exactly at higher edge of position range, no current lq update + (current_price / 2., current_price, false), + ] + .into_iter() + .for_each(|(price_low, price_high, expect_to_update)| { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Calculate ticks (assuming tick math is tested separately) + let tick_low = price_to_tick(price_low); + let tick_high = price_to_tick(price_high); + let liquidity_before = CurrentLiquidity::::get(netuid); + + // Add liquidity + assert_ok!(Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + )); + + // Current liquidity is updated only when price range includes the current price + let expected_liquidity = if (price_high > current_price) && (price_low <= current_price) + { + assert!(expect_to_update); + liquidity_before + liquidity + } else { + assert!(!expect_to_update); + liquidity_before + }; + + assert_eq!(CurrentLiquidity::::get(netuid), expected_liquidity) + }); + }); +} + +#[test] +fn test_rollback_works() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + assert_eq!( + Pallet::::do_swap(netuid, OrderType::Buy, 1_000_000, u64::MAX.into(), true) + .unwrap(), + Pallet::::do_swap(netuid, OrderType::Buy, 1_000_000, u64::MAX.into(), false) + .unwrap() + ); + }) +} + +/// Test correctness of swap fees: +/// - New LP is not eligible to previously accrued fees +/// +/// cargo test --package pallet-subtensor-swap --lib -- pallet::tests::test_new_lp_doesnt_get_old_fees --exact --show-output +#[test] +fn test_new_lp_doesnt_get_old_fees() { + new_test_ext().execute_with(|| { + let min_price = tick_to_price(TickIndex::MIN); + let max_price = tick_to_price(TickIndex::MAX); + let netuid = NetUid::from(1); + + // Provide very spread liquidity at the range from min to max that matches protocol liquidity + let liquidity = 2_000_000_000_000_u64; // 1x of protocol liquidity + + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + // Calculate ticks + let tick_low = price_to_tick(min_price); + let tick_high = price_to_tick(max_price); + + // Add user liquidity + Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID, + &OK_HOTKEY_ACCOUNT_ID, + tick_low, + tick_high, + liquidity, + ) + .unwrap(); + + // Swap buy and swap sell + Pallet::::do_swap( + netuid, + OrderType::Buy, + liquidity / 10, + u64::MAX.into(), + false, + ) + .unwrap(); + Pallet::::do_swap(netuid, OrderType::Sell, liquidity / 10, 0_u64.into(), false) + .unwrap(); + + // Add liquidity from a different user to a new tick + let (position_id_2, _tao, _alpha) = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID_2, + &OK_HOTKEY_ACCOUNT_ID_2, + tick_low.next().unwrap(), + tick_high.prev().unwrap(), + liquidity, + ) + .unwrap(); + + // Get user position + let mut position = + Positions::::get((netuid, OK_COLDKEY_ACCOUNT_ID_2, position_id_2)).unwrap(); + assert_eq!(position.liquidity, liquidity); + assert_eq!(position.tick_low, tick_low.next().unwrap()); + assert_eq!(position.tick_high, tick_high.prev().unwrap()); + + // Check that collected fees are 0 + let (actual_fee_tao, actual_fee_alpha) = position.collect_fees(); + assert_abs_diff_eq!(actual_fee_tao, 0, epsilon = 1); + assert_abs_diff_eq!(actual_fee_alpha, 0, epsilon = 1); + }); +} + +fn bbox(t: U64F64, a: U64F64, b: U64F64) -> U64F64 { + if t < a { + a + } else if t > b { + b + } else { + t + } +} + +fn print_current_price(netuid: NetUid) { + let current_sqrt_price = Pallet::::current_price_sqrt(netuid).to_num::(); + let current_price = current_sqrt_price * current_sqrt_price; + log::trace!("Current price: {:.6}", current_price); +} + +/// RUST_LOG=pallet_subtensor_swap=trace cargo test --package pallet-subtensor-swap --lib -- pallet::tests::test_wrapping_fees --exact --show-output --nocapture +#[test] +fn test_wrapping_fees() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(WRAPPING_FEES_NETUID); + let position_1_low_price = 0.20; + let position_1_high_price = 0.255; + let position_2_low_price = 0.255; + let position_2_high_price = 0.257; + assert_ok!(Pallet::::maybe_initialize_v3(netuid)); + + Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID_RICH, + &OK_COLDKEY_ACCOUNT_ID_RICH, + price_to_tick(position_1_low_price), + price_to_tick(position_1_high_price), + 1_000_000_000_u64, + ) + .unwrap(); + + print_current_price(netuid); + + let swap_amt = 800_000_000_u64; + let order_type = OrderType::Sell; + let sqrt_limit_price = SqrtPrice::from_num(0.000001); + Pallet::::do_swap(netuid, order_type, swap_amt, sqrt_limit_price, false).unwrap(); + + let swap_amt = 1_850_000_000_u64; + let order_type = OrderType::Buy; + let sqrt_limit_price = SqrtPrice::from_num(1_000_000.0); + + print_current_price(netuid); + + Pallet::::do_swap(netuid, order_type, swap_amt, sqrt_limit_price, false).unwrap(); + + print_current_price(netuid); + + let add_liquidity_result = Pallet::::do_add_liquidity( + netuid, + &OK_COLDKEY_ACCOUNT_ID_RICH, + &OK_COLDKEY_ACCOUNT_ID_RICH, + price_to_tick(position_2_low_price), + price_to_tick(position_2_high_price), + 1_000_000_000_u64, + ) + .unwrap(); + + let swap_amt = 1_800_000_000_u64; + let order_type = OrderType::Sell; + let sqrt_limit_price = SqrtPrice::from_num(0.000001); + + let initial_sqrt_price = Pallet::::current_price_sqrt(netuid); + Pallet::::do_swap(netuid, order_type, swap_amt, sqrt_limit_price, false).unwrap(); + let final_sqrt_price = Pallet::::current_price_sqrt(netuid); + + print_current_price(netuid); + + let mut position = + Positions::::get((netuid, &OK_COLDKEY_ACCOUNT_ID_RICH, add_liquidity_result.0)) + .unwrap(); + + let initial_box_price = bbox( + initial_sqrt_price, + position.tick_low.try_to_sqrt_price().unwrap(), + position.tick_high.try_to_sqrt_price().unwrap(), + ); + + let final_box_price = bbox( + final_sqrt_price, + position.tick_low.try_to_sqrt_price().unwrap(), + position.tick_high.try_to_sqrt_price().unwrap(), + ); + + let fee_rate = FeeRate::::get(netuid) as f64 / u16::MAX as f64; + + log::trace!("fee_rate: {:.6}", fee_rate); + log::trace!("position.liquidity: {}", position.liquidity); + log::trace!( + "initial_box_price: {:.6}", + initial_box_price.to_num::() + ); + log::trace!("final_box_price: {:.6}", final_box_price.to_num::()); + + let expected_fee_tao = ((fee_rate / (1.0 - fee_rate)) + * (position.liquidity as f64) + * (final_box_price.to_num::() - initial_box_price.to_num::())) + as u64; + + let expected_fee_alpha = ((fee_rate / (1.0 - fee_rate)) + * (position.liquidity as f64) + * ((1.0 / final_box_price.to_num::()) - (1.0 / initial_box_price.to_num::()))) + as u64; + + log::trace!("Expected ALPHA fee: {:.6}", expected_fee_alpha as f64); + + let (fee_tao, fee_alpha) = position.collect_fees(); + + log::trace!("Collected fees: TAO: {}, ALPHA: {}", fee_tao, fee_alpha); + + assert_abs_diff_eq!(fee_tao, expected_fee_tao, epsilon = 1); + assert_abs_diff_eq!(fee_alpha, expected_fee_alpha, epsilon = 1); + }); +} diff --git a/pallets/swap/src/position.rs b/pallets/swap/src/position.rs new file mode 100644 index 0000000000..542aa389ad --- /dev/null +++ b/pallets/swap/src/position.rs @@ -0,0 +1,188 @@ +use core::marker::PhantomData; + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::pallet_prelude::*; +use safe_math::*; +use substrate_fixed::types::{I64F64, U64F64}; +use subtensor_macros::freeze_struct; +use subtensor_runtime_common::NetUid; + +use crate::SqrtPrice; +use crate::pallet::{Config, Error, FeeGlobalAlpha, FeeGlobalTao, LastPositionId}; +use crate::tick::TickIndex; + +/// Position designates one liquidity position. +/// +/// Alpha price is expressed in rao units per one 10^9 unit. For example, +/// price 1_000_000 is equal to 0.001 TAO per Alpha. +#[freeze_struct("27a1bf8c59480f0")] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen, Default)] +#[scale_info(skip_type_params(T))] +pub struct Position { + /// Unique ID of the position + pub id: PositionId, + /// Network identifier + pub netuid: NetUid, + /// Tick index for lower boundary of price + pub tick_low: TickIndex, + /// Tick index for higher boundary of price + pub tick_high: TickIndex, + /// Position liquidity + pub liquidity: u64, + /// Fees accrued by the position in quote currency (TAO) relative to global fees + pub fees_tao: I64F64, + /// Fees accrued by the position in base currency (Alpha) relative to global fees + pub fees_alpha: I64F64, + /// Phantom marker for generic Config type + pub _phantom: PhantomData, +} + +impl Position { + pub fn new( + id: PositionId, + netuid: NetUid, + tick_low: TickIndex, + tick_high: TickIndex, + liquidity: u64, + ) -> Self { + let mut position = Position { + id, + netuid, + tick_low, + tick_high, + liquidity, + fees_tao: I64F64::saturating_from_num(0), + fees_alpha: I64F64::saturating_from_num(0), + _phantom: PhantomData, + }; + + position.fees_tao = position.fees_in_range(true); + position.fees_alpha = position.fees_in_range(false); + + position + } + + /// Converts position to token amounts + /// + /// returns tuple of (TAO, Alpha) + /// + /// Pseudocode: + /// if self.sqrt_price_curr < sqrt_pa: + /// tao = 0 + /// alpha = L * (1 / sqrt_pa - 1 / sqrt_pb) + /// elif self.sqrt_price_curr > sqrt_pb: + /// tao = L * (sqrt_pb - sqrt_pa) + /// alpha = 0 + /// else: + /// tao = L * (self.sqrt_price_curr - sqrt_pa) + /// alpha = L * (1 / self.sqrt_price_curr - 1 / sqrt_pb) + /// + pub fn to_token_amounts(&self, sqrt_price_curr: SqrtPrice) -> Result<(u64, u64), Error> { + let one = U64F64::saturating_from_num(1); + + let sqrt_price_low = self + .tick_low + .try_to_sqrt_price() + .map_err(|_| Error::::InvalidTickRange)?; + let sqrt_price_high = self + .tick_high + .try_to_sqrt_price() + .map_err(|_| Error::::InvalidTickRange)?; + let liquidity_fixed = U64F64::saturating_from_num(self.liquidity); + + Ok(if sqrt_price_curr < sqrt_price_low { + ( + 0, + liquidity_fixed + .saturating_mul( + one.safe_div(sqrt_price_low) + .saturating_sub(one.safe_div(sqrt_price_high)), + ) + .saturating_to_num::(), + ) + } else if sqrt_price_curr > sqrt_price_high { + ( + liquidity_fixed + .saturating_mul(sqrt_price_high.saturating_sub(sqrt_price_low)) + .saturating_to_num::(), + 0, + ) + } else { + ( + liquidity_fixed + .saturating_mul(sqrt_price_curr.saturating_sub(sqrt_price_low)) + .saturating_to_num::(), + liquidity_fixed + .saturating_mul( + one.safe_div(sqrt_price_curr) + .saturating_sub(one.safe_div(sqrt_price_high)), + ) + .saturating_to_num::(), + ) + }) + } + + /// Collect fees for a position + /// Updates the position + pub fn collect_fees(&mut self) -> (u64, u64) { + let fee_tao_agg = self.fees_in_range(true); + let fee_alpha_agg = self.fees_in_range(false); + + let mut fee_tao = fee_tao_agg.saturating_sub(self.fees_tao); + let mut fee_alpha = fee_alpha_agg.saturating_sub(self.fees_alpha); + + self.fees_tao = fee_tao_agg; + self.fees_alpha = fee_alpha_agg; + + let liquidity_frac = I64F64::saturating_from_num(self.liquidity); + + fee_tao = liquidity_frac.saturating_mul(fee_tao); + fee_alpha = liquidity_frac.saturating_mul(fee_alpha); + + ( + fee_tao.saturating_to_num::(), + fee_alpha.saturating_to_num::(), + ) + } + + /// Get fees in a position's range + /// + /// If quote flag is true, Tao is returned, otherwise alpha. + fn fees_in_range(&self, quote: bool) -> I64F64 { + if quote { + I64F64::saturating_from_num(FeeGlobalTao::::get(self.netuid)) + } else { + I64F64::saturating_from_num(FeeGlobalAlpha::::get(self.netuid)) + } + .saturating_sub(self.tick_low.fees_below::(self.netuid, quote)) + .saturating_sub(self.tick_high.fees_above::(self.netuid, quote)) + } +} + +#[freeze_struct("1f02550d787d80da")] +#[derive( + Clone, Copy, Decode, Default, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo, +)] +pub struct PositionId(u128); + +impl PositionId { + /// Create a new position ID + pub fn new() -> Self { + let new = LastPositionId::::get().saturating_add(1); + LastPositionId::::put(new); + + Self(new) + } +} + +impl From for PositionId { + fn from(value: u128) -> Self { + Self(value) + } +} + +impl From for u128 { + fn from(value: PositionId) -> Self { + value.0 + } +} diff --git a/pallets/swap/src/tick.rs b/pallets/swap/src/tick.rs new file mode 100644 index 0000000000..20a19007d7 --- /dev/null +++ b/pallets/swap/src/tick.rs @@ -0,0 +1,2197 @@ +//! The math is adapted from github.com/0xKitsune/uniswap-v3-math +use core::cmp::Ordering; +use core::convert::TryFrom; +use core::error::Error; +use core::fmt; +use core::hash::Hash; +use core::ops::{Add, AddAssign, BitOr, Deref, Neg, Shl, Shr, Sub, SubAssign}; + +use alloy_primitives::{I256, U256}; +use codec::{Decode, Encode, Error as CodecError, Input, MaxEncodedLen}; +use frame_support::pallet_prelude::*; +use safe_math::*; +use sp_std::vec; +use sp_std::vec::Vec; +use substrate_fixed::types::{I64F64, U64F64}; +use subtensor_macros::freeze_struct; +use subtensor_runtime_common::NetUid; + +use crate::SqrtPrice; +use crate::pallet::{ + Config, CurrentTick, FeeGlobalAlpha, FeeGlobalTao, TickIndexBitmapWords, Ticks, +}; + +const U256_1: U256 = U256::from_limbs([1, 0, 0, 0]); +const U256_2: U256 = U256::from_limbs([2, 0, 0, 0]); +const U256_3: U256 = U256::from_limbs([3, 0, 0, 0]); +const U256_4: U256 = U256::from_limbs([4, 0, 0, 0]); +const U256_5: U256 = U256::from_limbs([5, 0, 0, 0]); +const U256_6: U256 = U256::from_limbs([6, 0, 0, 0]); +const U256_7: U256 = U256::from_limbs([7, 0, 0, 0]); +const U256_8: U256 = U256::from_limbs([8, 0, 0, 0]); +const U256_15: U256 = U256::from_limbs([15, 0, 0, 0]); +const U256_16: U256 = U256::from_limbs([16, 0, 0, 0]); +const U256_32: U256 = U256::from_limbs([32, 0, 0, 0]); +const U256_64: U256 = U256::from_limbs([64, 0, 0, 0]); +const U256_127: U256 = U256::from_limbs([127, 0, 0, 0]); +const U256_128: U256 = U256::from_limbs([128, 0, 0, 0]); +const U256_255: U256 = U256::from_limbs([255, 0, 0, 0]); + +const U256_256: U256 = U256::from_limbs([256, 0, 0, 0]); +const U256_512: U256 = U256::from_limbs([512, 0, 0, 0]); +const U256_1024: U256 = U256::from_limbs([1024, 0, 0, 0]); +const U256_2048: U256 = U256::from_limbs([2048, 0, 0, 0]); +const U256_4096: U256 = U256::from_limbs([4096, 0, 0, 0]); +const U256_8192: U256 = U256::from_limbs([8192, 0, 0, 0]); +const U256_16384: U256 = U256::from_limbs([16384, 0, 0, 0]); +const U256_32768: U256 = U256::from_limbs([32768, 0, 0, 0]); +const U256_65536: U256 = U256::from_limbs([65536, 0, 0, 0]); +const U256_131072: U256 = U256::from_limbs([131072, 0, 0, 0]); +const U256_262144: U256 = U256::from_limbs([262144, 0, 0, 0]); +const U256_524288: U256 = U256::from_limbs([524288, 0, 0, 0]); + +const U256_MAX_TICK: U256 = U256::from_limbs([887272, 0, 0, 0]); + +const MIN_TICK: i32 = -887272; +const MAX_TICK: i32 = -MIN_TICK; + +const MIN_SQRT_RATIO: U256 = U256::from_limbs([4295128739, 0, 0, 0]); +const MAX_SQRT_RATIO: U256 = + U256::from_limbs([6743328256752651558, 17280870778742802505, 4294805859, 0]); + +const SQRT_10001: I256 = I256::from_raw(U256::from_limbs([11745905768312294533, 13863, 0, 0])); +const TICK_LOW: I256 = I256::from_raw(U256::from_limbs([ + 6552757943157144234, + 184476617836266586, + 0, + 0, +])); +const TICK_HIGH: I256 = I256::from_raw(U256::from_limbs([ + 4998474450511881007, + 15793544031827761793, + 0, + 0, +])); + +/// Tick is the price range determined by tick index (not part of this struct, but is the key at +/// which the Tick is stored in state hash maps). Tick struct stores liquidity and fee information. +/// +/// - Net liquidity +/// - Gross liquidity +/// - Fees (above global) in both currencies +#[freeze_struct("ff1bce826e64c4aa")] +#[derive(Debug, Default, Clone, Encode, Decode, TypeInfo, MaxEncodedLen, PartialEq, Eq)] +pub struct Tick { + pub liquidity_net: i128, + pub liquidity_gross: u64, + pub fees_out_tao: I64F64, + pub fees_out_alpha: I64F64, +} + +impl Tick { + pub fn liquidity_net_as_u64(&self) -> u64 { + self.liquidity_net.abs().min(u64::MAX as i128) as u64 + } +} + +/// Struct representing a tick index +#[freeze_struct("31577b3ad1f55092")] +#[derive( + Debug, + Default, + Clone, + Copy, + Encode, + TypeInfo, + MaxEncodedLen, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, +)] +pub struct TickIndex(i32); + +impl Decode for TickIndex { + fn decode(input: &mut I) -> Result { + let raw = i32::decode(input)?; + TickIndex::new(raw).map_err(|_| "TickIndex out of bounds".into()) + } +} + +impl Add for TickIndex { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn add(self, rhs: Self) -> Self::Output { + // Note: This assumes the result is within bounds. + // For a safer implementation, consider using checked_add. + Self::new_unchecked(self.get() + rhs.get()) + } +} + +impl Sub for TickIndex { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn sub(self, rhs: Self) -> Self::Output { + // Note: This assumes the result is within bounds. + // For a safer implementation, consider using checked_sub. + Self::new_unchecked(self.get() - rhs.get()) + } +} + +impl AddAssign for TickIndex { + #[allow(clippy::arithmetic_side_effects)] + fn add_assign(&mut self, rhs: Self) { + *self = Self::new_unchecked(self.get() + rhs.get()); + } +} + +impl SubAssign for TickIndex { + #[allow(clippy::arithmetic_side_effects)] + fn sub_assign(&mut self, rhs: Self) { + *self = Self::new_unchecked(self.get() - rhs.get()); + } +} + +impl TryFrom for TickIndex { + type Error = TickMathError; + + fn try_from(value: i32) -> Result { + Self::new(value) + } +} + +impl Deref for TickIndex { + type Target = i32; + + fn deref(&self) -> &Self::Target { + // Using get() would create an infinite recursion, so this is one place where we need direct + // field access. This is safe because Self::Target is i32, which is exactly what we're + // storing + &self.0 + } +} + +/// Extension trait to make working with TryFrom more ergonomic +pub trait TryIntoTickIndex { + /// Convert an i32 into a TickIndex, with bounds checking + fn into_tick_index(self) -> Result; +} + +impl TryIntoTickIndex for i32 { + fn into_tick_index(self) -> Result { + TickIndex::try_from(self) + } +} + +impl TickIndex { + /// Minimum value of the tick index + /// The tick_math library uses different bitness, so we have to divide by 2. + /// It's unsafe to change this value to something else. + pub const MIN: Self = Self(MIN_TICK.saturating_div(2)); + + /// Maximum value of the tick index + /// The tick_math library uses different bitness, so we have to divide by 2. + /// It's unsafe to change this value to something else. + pub const MAX: Self = Self(MAX_TICK.saturating_div(2)); + + /// All tick indexes are offset by this value for storage needs + /// so that tick indexes are positive, which simplifies bit logic + const OFFSET: Self = Self(MAX_TICK); + + /// The MIN sqrt price, which is caclculated at Self::MIN + pub fn min_sqrt_price() -> SqrtPrice { + SqrtPrice::saturating_from_num(0.0000000002328350195) + } + + /// The MAX sqrt price, which is calculated at Self::MAX + #[allow(clippy::excessive_precision)] + pub fn max_sqrt_price() -> SqrtPrice { + SqrtPrice::saturating_from_num(4294886577.20989222513899790805) + } + + /// Get fees above a tick + pub fn fees_above(&self, netuid: NetUid, quote: bool) -> I64F64 { + let current_tick = Self::current_bounded::(netuid); + + let tick = Ticks::::get(netuid, *self).unwrap_or_default(); + if *self <= current_tick { + if quote { + I64F64::saturating_from_num(FeeGlobalTao::::get(netuid)) + .saturating_sub(tick.fees_out_tao) + } else { + I64F64::saturating_from_num(FeeGlobalAlpha::::get(netuid)) + .saturating_sub(tick.fees_out_alpha) + } + } else if quote { + tick.fees_out_tao + } else { + tick.fees_out_alpha + } + } + + /// Get fees below a tick + pub fn fees_below(&self, netuid: NetUid, quote: bool) -> I64F64 { + let current_tick = Self::current_bounded::(netuid); + + let tick = Ticks::::get(netuid, *self).unwrap_or_default(); + if *self <= current_tick { + if quote { + tick.fees_out_tao + } else { + tick.fees_out_alpha + } + } else if quote { + I64F64::saturating_from_num(FeeGlobalTao::::get(netuid)) + .saturating_sub(tick.fees_out_tao) + } else { + I64F64::saturating_from_num(FeeGlobalAlpha::::get(netuid)) + .saturating_sub(tick.fees_out_alpha) + } + } + + /// Get the current tick index for a subnet, ensuring it's within valid bounds + pub fn current_bounded(netuid: NetUid) -> Self { + let current_tick = CurrentTick::::get(netuid); + if current_tick > Self::MAX { + Self::MAX + } else if current_tick < Self::MIN { + Self::MIN + } else { + current_tick + } + } + + /// Converts a sqrt price to a tick index, ensuring it's within valid bounds + /// + /// If the price is outside the valid range, this function will return the appropriate boundary + /// tick index (MIN or MAX) instead of an error. + /// + /// # Arguments + /// * `sqrt_price` - The square root price to convert to a tick index + /// + /// # Returns + /// * `TickIndex` - A tick index that is guaranteed to be within valid bounds + pub fn from_sqrt_price_bounded(sqrt_price: SqrtPrice) -> Self { + match Self::try_from_sqrt_price(sqrt_price) { + Ok(index) => index, + Err(_) => { + let max_price = Self::MAX.as_sqrt_price_bounded(); + + if sqrt_price > max_price { + Self::MAX + } else { + Self::MIN + } + } + } + } + + /// Converts a tick index to a sqrt price, ensuring it's within valid bounds + /// + /// Unlike try_to_sqrt_price which returns an error for boundary indices, this function + /// guarantees a valid sqrt price by using fallback values if conversion fails. + /// + /// # Returns + /// * `SqrtPrice` - A sqrt price that is guaranteed to be a valid value + pub fn as_sqrt_price_bounded(&self) -> SqrtPrice { + self.try_to_sqrt_price().unwrap_or_else(|_| { + if *self >= Self::MAX { + Self::max_sqrt_price() + } else { + Self::min_sqrt_price() + } + }) + } + + /// Creates a new TickIndex instance with bounds checking + pub fn new(value: i32) -> Result { + if !(Self::MIN.0..=Self::MAX.0).contains(&value) { + Err(TickMathError::TickOutOfBounds) + } else { + Ok(Self(value)) + } + } + + /// Creates a new TickIndex without bounds checking + /// Use this function with caution, only when you're certain the value is valid + pub fn new_unchecked(value: i32) -> Self { + Self(value) + } + + /// Get the inner value + pub fn get(&self) -> i32 { + self.0 + } + + /// Creates a TickIndex from an offset representation (u32) + /// + /// # Arguments + /// * `offset_index` - An offset index (u32 value) representing a tick index + /// + /// # Returns + /// * `Result` - The corresponding TickIndex if within valid bounds + pub fn from_offset_index(offset_index: u32) -> Result { + // while it's safe, we use saturating math to mute the linter and just in case + let signed_index = ((offset_index as i64).saturating_sub(Self::OFFSET.get() as i64)) as i32; + Self::new(signed_index) + } + + /// Get the next tick index (incrementing by 1) + pub fn next(&self) -> Result { + Self::new(self.0.saturating_add(1)) + } + + /// Get the previous tick index (decrementing by 1) + pub fn prev(&self) -> Result { + Self::new(self.0.saturating_sub(1)) + } + + /// Add a value to this tick index with bounds checking + pub fn checked_add(&self, value: i32) -> Result { + Self::new(self.0.saturating_add(value)) + } + + /// Subtract a value from this tick index with bounds checking + pub fn checked_sub(&self, value: i32) -> Result { + Self::new(self.0.saturating_sub(value)) + } + + /// Add a value to this tick index, saturating at the bounds instead of overflowing + pub fn saturating_add(&self, value: i32) -> Self { + match self.checked_add(value) { + Ok(result) => result, + Err(_) => { + if value > 0 { + Self::MAX + } else { + Self::MIN + } + } + } + } + + /// Subtract a value from this tick index, saturating at the bounds instead of overflowing + pub fn saturating_sub(&self, value: i32) -> Self { + match self.checked_sub(value) { + Ok(result) => result, + Err(_) => { + if value > 0 { + Self::MIN + } else { + Self::MAX + } + } + } + } + + /// Divide the tick index by a value with bounds checking + #[allow(clippy::arithmetic_side_effects)] + pub fn checked_div(&self, value: i32) -> Result { + if value == 0 { + return Err(TickMathError::DivisionByZero); + } + Self::new(self.0.saturating_div(value)) + } + + /// Divide the tick index by a value, saturating at the bounds + pub fn saturating_div(&self, value: i32) -> Self { + if value == 0 { + return Self::MAX; // Return MAX for division by zero + } + match self.checked_div(value) { + Ok(result) => result, + Err(_) => { + if (self.0 < 0 && value > 0) || (self.0 > 0 && value < 0) { + Self::MIN + } else { + Self::MAX + } + } + } + } + + /// Multiply the tick index by a value with bounds checking + pub fn checked_mul(&self, value: i32) -> Result { + // Check for potential overflow + match self.0.checked_mul(value) { + Some(result) => Self::new(result), + None => Err(TickMathError::Overflow), + } + } + + /// Multiply the tick index by a value, saturating at the bounds + pub fn saturating_mul(&self, value: i32) -> Self { + match self.checked_mul(value) { + Ok(result) => result, + Err(_) => { + if (self.0 < 0 && value > 0) || (self.0 > 0 && value < 0) { + Self::MIN + } else { + Self::MAX + } + } + } + } + + /// Converts tick index into SQRT of lower price of this tick In order to find the higher price + /// of this tick, call tick_index_to_sqrt_price(tick_idx + 1) + pub fn try_to_sqrt_price(&self) -> Result { + // because of u256->u128 conversion we have twice less values for min/max ticks + if !(Self::MIN..=Self::MAX).contains(self) { + return Err(TickMathError::TickOutOfBounds); + } + get_sqrt_ratio_at_tick(self.0).and_then(u256_q64_96_to_u64f64) + } + + /// Converts SQRT price to tick index + /// Because the tick is the range of prices [sqrt_lower_price, sqrt_higher_price), the resulting + /// tick index matches the price by the following inequality: + /// sqrt_lower_price <= sqrt_price < sqrt_higher_price + pub fn try_from_sqrt_price(sqrt_price: SqrtPrice) -> Result { + // price in the native Q64.96 integer format + let price_x96 = u64f64_to_u256_q64_96(sqrt_price); + + // first‑pass estimate from the log calculation + let mut tick = get_tick_at_sqrt_ratio(price_x96)?; + + // post‑verification, *both* directions + let price_at_tick = get_sqrt_ratio_at_tick(tick)?; + if price_at_tick > price_x96 { + tick = tick.saturating_sub(1); // estimate was too high + } else { + // it may still be one too low + let price_at_tick_plus = get_sqrt_ratio_at_tick(tick.saturating_add(1))?; + if price_at_tick_plus <= price_x96 { + tick = tick.saturating_add(1); // step up when required + } + } + + tick.into_tick_index() + } +} + +pub struct ActiveTickIndexManager(PhantomData); + +impl ActiveTickIndexManager { + pub fn insert(netuid: NetUid, index: TickIndex) { + // Check the range + if (index < TickIndex::MIN) || (index > TickIndex::MAX) { + return; + } + + // Convert to bitmap representation + let bitmap = TickIndexBitmap::from(index); + + // Update layer words + let mut word0_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Top, + bitmap.word_at(LayerLevel::Top), + )); + let mut word1_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Middle, + bitmap.word_at(LayerLevel::Middle), + )); + let mut word2_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Bottom, + bitmap.word_at(LayerLevel::Bottom), + )); + + // Set bits in each layer + word0_value |= bitmap.bit_mask(LayerLevel::Top); + word1_value |= bitmap.bit_mask(LayerLevel::Middle); + word2_value |= bitmap.bit_mask(LayerLevel::Bottom); + + // Update the storage + TickIndexBitmapWords::::set( + (netuid, LayerLevel::Top, bitmap.word_at(LayerLevel::Top)), + word0_value, + ); + TickIndexBitmapWords::::set( + ( + netuid, + LayerLevel::Middle, + bitmap.word_at(LayerLevel::Middle), + ), + word1_value, + ); + TickIndexBitmapWords::::set( + ( + netuid, + LayerLevel::Bottom, + bitmap.word_at(LayerLevel::Bottom), + ), + word2_value, + ); + } + + pub fn remove(netuid: NetUid, index: TickIndex) { + // Check the range + if (index < TickIndex::MIN) || (index > TickIndex::MAX) { + return; + } + + // Convert to bitmap representation + let bitmap = TickIndexBitmap::from(index); + + // Update layer words + let mut word0_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Top, + bitmap.word_at(LayerLevel::Top), + )); + let mut word1_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Middle, + bitmap.word_at(LayerLevel::Middle), + )); + let mut word2_value = TickIndexBitmapWords::::get(( + netuid, + LayerLevel::Bottom, + bitmap.word_at(LayerLevel::Bottom), + )); + + // Turn the bit off (& !bit) and save as needed + word2_value &= !bitmap.bit_mask(LayerLevel::Bottom); + TickIndexBitmapWords::::set( + ( + netuid, + LayerLevel::Bottom, + bitmap.word_at(LayerLevel::Bottom), + ), + word2_value, + ); + + if word2_value == 0 { + word1_value &= !bitmap.bit_mask(LayerLevel::Middle); + TickIndexBitmapWords::::set( + ( + netuid, + LayerLevel::Middle, + bitmap.word_at(LayerLevel::Middle), + ), + word1_value, + ); + } + + if word1_value == 0 { + word0_value &= !bitmap.bit_mask(LayerLevel::Top); + TickIndexBitmapWords::::set( + (netuid, LayerLevel::Top, bitmap.word_at(LayerLevel::Top)), + word0_value, + ); + } + } + + pub fn find_closest_lower(netuid: NetUid, index: TickIndex) -> Option { + Self::find_closest(netuid, index, true) + } + + pub fn find_closest_higher(netuid: NetUid, index: TickIndex) -> Option { + Self::find_closest(netuid, index, false) + } + + fn find_closest(netuid: NetUid, index: TickIndex, lower: bool) -> Option { + // Check the range + if (index < TickIndex::MIN) || (index > TickIndex::MAX) { + return None; + } + + // Convert to bitmap representation + let bitmap = TickIndexBitmap::from(index); + let mut found = false; + let mut result: u32 = 0; + + // Layer positions from bitmap + let layer0_word = bitmap.word_at(LayerLevel::Top); + let layer0_bit = bitmap.bit_at(LayerLevel::Top); + let layer1_word = bitmap.word_at(LayerLevel::Middle); + let layer1_bit = bitmap.bit_at(LayerLevel::Middle); + let layer2_word = bitmap.word_at(LayerLevel::Bottom); + let layer2_bit = bitmap.bit_at(LayerLevel::Bottom); + + // Find the closest active bits in layer 0, then 1, then 2 + + /////////////// + // Level 0 + let word0 = TickIndexBitmapWords::::get((netuid, LayerLevel::Top, layer0_word)); + let closest_bits_l0 = + TickIndexBitmap::find_closest_active_bit_candidates(word0, layer0_bit, lower); + + for closest_bit_l0 in closest_bits_l0.iter() { + /////////////// + // Level 1 + let word1_index = TickIndexBitmap::layer_to_index(BitmapLayer::new(0, *closest_bit_l0)); + + // Layer 1 words are different, shift the bit to the word edge + let start_from_l1_bit = match word1_index.cmp(&layer1_word) { + Ordering::Less => 127, + Ordering::Greater => 0, + _ => layer1_bit, + }; + let word1_value = + TickIndexBitmapWords::::get((netuid, LayerLevel::Middle, word1_index)); + let closest_bits_l1 = TickIndexBitmap::find_closest_active_bit_candidates( + word1_value, + start_from_l1_bit, + lower, + ); + + for closest_bit_l1 in closest_bits_l1.iter() { + /////////////// + // Level 2 + let word2_index = + TickIndexBitmap::layer_to_index(BitmapLayer::new(word1_index, *closest_bit_l1)); + + // Layer 2 words are different, shift the bit to the word edge + let start_from_l2_bit = match word2_index.cmp(&layer2_word) { + Ordering::Less => 127, + Ordering::Greater => 0, + _ => layer2_bit, + }; + + let word2_value = + TickIndexBitmapWords::::get((netuid, LayerLevel::Bottom, word2_index)); + + let closest_bits_l2 = TickIndexBitmap::find_closest_active_bit_candidates( + word2_value, + start_from_l2_bit, + lower, + ); + + if !closest_bits_l2.is_empty() { + // The active tick is found, restore its full index and return + let offset_found_index = TickIndexBitmap::layer_to_index(BitmapLayer::new( + word2_index, + // it's safe to unwrap, because the len is > 0, but to prevent errors in + // refactoring, we use default fallback here for extra safety + closest_bits_l2.first().copied().unwrap_or_default(), + )); + + if lower { + if (offset_found_index > result) || (!found) { + result = offset_found_index; + found = true; + } + } else if (offset_found_index < result) || (!found) { + result = offset_found_index; + found = true; + } + } + } + } + + if !found { + return None; + } + + // Convert the result offset_index back to a tick index + TickIndex::from_offset_index(result).ok() + } + + pub fn tick_is_active(netuid: NetUid, tick: TickIndex) -> bool { + Self::find_closest_lower(netuid, tick).unwrap_or(TickIndex::MAX) == tick + } +} + +/// Represents the three layers in the Uniswap V3 bitmap structure +#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub enum LayerLevel { + /// Top layer (highest level of the hierarchy) + Top = 0, + /// Middle layer + Middle = 1, + /// Bottom layer (contains the actual ticks) + Bottom = 2, +} + +#[freeze_struct("4015a04919eb5e2e")] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub(crate) struct BitmapLayer { + word: u32, + bit: u32, +} + +impl BitmapLayer { + pub fn new(word: u32, bit: u32) -> Self { + Self { word, bit } + } +} + +/// A bitmap representation of a tick index position across the three-layer structure +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct TickIndexBitmap { + /// The position in layer 0 (top layer) + layer0: BitmapLayer, + /// The position in layer 1 (middle layer) + layer1: BitmapLayer, + /// The position in layer 2 (bottom layer) + layer2: BitmapLayer, +} + +impl TickIndexBitmap { + /// Helper function to convert a bitmap index to a (word, bit) tuple in a bitmap layer using + /// safe methods + /// + /// Note: This function operates on bitmap navigation indices, NOT tick indices. + /// It converts a flat index within the bitmap structure to a (word, bit) position. + fn index_to_layer(index: u32) -> BitmapLayer { + let word = index.safe_div(128); + let bit = index.checked_rem(128).unwrap_or_default(); + BitmapLayer { word, bit } + } + + /// Converts a position (word, bit) within a layer to a word index in the next layer down + /// Note: This returns a bitmap navigation index, NOT a tick index + pub(crate) fn layer_to_index(layer: BitmapLayer) -> u32 { + layer.word.saturating_mul(128).saturating_add(layer.bit) + } + + /// Get the mask for a bit in the specified layer + pub(crate) fn bit_mask(&self, layer: LayerLevel) -> u128 { + match layer { + LayerLevel::Top => 1u128 << self.layer0.bit, + LayerLevel::Middle => 1u128 << self.layer1.bit, + LayerLevel::Bottom => 1u128 << self.layer2.bit, + } + } + + /// Get the word for the specified layer + pub(crate) fn word_at(&self, layer: LayerLevel) -> u32 { + match layer { + LayerLevel::Top => self.layer0.word, + LayerLevel::Middle => self.layer1.word, + LayerLevel::Bottom => self.layer2.word, + } + } + + /// Get the bit for the specified layer + pub(crate) fn bit_at(&self, layer: LayerLevel) -> u32 { + match layer { + LayerLevel::Top => self.layer0.bit, + LayerLevel::Middle => self.layer1.bit, + LayerLevel::Bottom => self.layer2.bit, + } + } + + /// Finds the closest active bit in a bitmap word, and if the active bit exactly matches the + /// requested bit, then it finds the next one as well + /// + /// # Arguments + /// * `word` - The bitmap word to search within + /// * `bit` - The bit position to start searching from + /// * `lower` - If true, search for lower bits (decreasing bit position), if false, search for + /// higher bits (increasing bit position) + /// + /// # Returns + /// * Exact match: Vec with [next_bit, bit] + /// * Non-exact match: Vec with [closest_bit] + /// * No match: Empty Vec + pub(crate) fn find_closest_active_bit_candidates( + word: u128, + bit: u32, + lower: bool, + ) -> Vec { + let mut result = vec![]; + let mut mask: u128 = 1_u128.wrapping_shl(bit); + let mut active_bit: u32 = bit; + + while mask > 0 { + if mask & word != 0 { + result.push(active_bit); + if active_bit != bit { + break; + } + } + + mask = if lower { + active_bit = active_bit.saturating_sub(1); + mask.wrapping_shr(1) + } else { + active_bit = active_bit.saturating_add(1); + mask.wrapping_shl(1) + }; + } + + result + } +} + +impl From for TickIndexBitmap { + fn from(tick_index: TickIndex) -> Self { + // Convert to offset index (internal operation only) + let offset_index = (tick_index.get().saturating_add(TickIndex::OFFSET.get())) as u32; + + // Calculate layer positions + let layer2 = Self::index_to_layer(offset_index); + let layer1 = Self::index_to_layer(layer2.word); + let layer0 = Self::index_to_layer(layer1.word); + + Self { + layer0, + layer1, + layer2, + } + } +} + +#[allow(clippy::arithmetic_side_effects)] +fn get_sqrt_ratio_at_tick(tick: i32) -> Result { + let abs_tick = if tick < 0 { + U256::from(tick.neg()) + } else { + U256::from(tick) + }; + + if abs_tick > U256_MAX_TICK { + return Err(TickMathError::TickOutOfBounds); + } + + let mut ratio = if abs_tick & (U256_1) != U256::ZERO { + U256::from_limbs([12262481743371124737, 18445821805675392311, 0, 0]) + } else { + U256::from_limbs([0, 0, 1, 0]) + }; + + if !(abs_tick & U256_2).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 6459403834229662010, + 18444899583751176498, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_4).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 17226890335427755468, + 18443055278223354162, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_8).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 2032852871939366096, + 18439367220385604838, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_16).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 14545316742740207172, + 18431993317065449817, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_32).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 5129152022828963008, + 18417254355718160513, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_64).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 4894419605888772193, + 18387811781193591352, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_128).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 1280255884321894483, + 18329067761203520168, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_256).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 15924666964335305636, + 18212142134806087854, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_512).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 8010504389359918676, + 17980523815641551639, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_1024).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 10668036004952895731, + 17526086738831147013, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_2048).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 4878133418470705625, + 16651378430235024244, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_4096).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 9537173718739605541, + 15030750278693429944, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_8192).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 9972618978014552549, + 12247334978882834399, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_16384).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 10428997489610666743, + 8131365268884726200, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_32768).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 9305304367709015974, + 3584323654723342297, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_65536).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 14301143598189091785, + 696457651847595233, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_131072).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 7393154844743099908, + 26294789957452057, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_262144).is_zero() { + ratio = (ratio.saturating_mul(U256::from_limbs([ + 2209338891292245656, + 37481735321082, + 0, + 0, + ]))) >> 128 + } + if !(abs_tick & U256_524288).is_zero() { + ratio = + (ratio.saturating_mul(U256::from_limbs([10518117631919034274, 76158723, 0, 0]))) >> 128 + } + + if tick > 0 { + ratio = U256::MAX / ratio; + } + + let shifted: U256 = ratio >> 32; + let ceil = if ratio & U256::from((1u128 << 32) - 1) != U256::ZERO { + shifted.saturating_add(U256_1) + } else { + shifted + }; + Ok(ceil) +} + +#[allow(clippy::arithmetic_side_effects)] +fn get_tick_at_sqrt_ratio(sqrt_price_x_96: U256) -> Result { + if !(sqrt_price_x_96 >= MIN_SQRT_RATIO && sqrt_price_x_96 < MAX_SQRT_RATIO) { + return Err(TickMathError::SqrtPriceOutOfBounds); + } + + let ratio: U256 = sqrt_price_x_96.shl(32); + let mut r = ratio; + let mut msb = U256::ZERO; + + let mut f = if r > U256::from_limbs([18446744073709551615, 18446744073709551615, 0, 0]) { + U256_1.shl(U256_7) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256::from_limbs([18446744073709551615, 0, 0, 0]) { + U256_1.shl(U256_6) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256::from_limbs([4294967295, 0, 0, 0]) { + U256_1.shl(U256_5) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256::from_limbs([65535, 0, 0, 0]) { + U256_1.shl(U256_4) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256_255 { + U256_1.shl(U256_3) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256_15 { + U256_1.shl(U256_2) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256_3 { + U256_1.shl(U256_1) + } else { + U256::ZERO + }; + msb = msb.bitor(f); + r = r.shr(f); + + f = if r > U256_1 { U256_1 } else { U256::ZERO }; + + msb = msb.bitor(f); + + r = if msb >= U256_128 { + ratio.shr(msb.saturating_sub(U256_127)) + } else { + ratio.shl(U256_127.saturating_sub(msb)) + }; + + let mut log_2: I256 = + (I256::from_raw(msb).saturating_sub(I256::from_limbs([128, 0, 0, 0]))).shl(64); + + for i in (51..=63).rev() { + r = r.overflowing_mul(r).0.shr(U256_127); + let f: U256 = r.shr(128); + log_2 = log_2.bitor(I256::from_raw(f.shl(i))); + + r = r.shr(f); + } + + r = r.overflowing_mul(r).0.shr(U256_127); + let f: U256 = r.shr(128); + log_2 = log_2.bitor(I256::from_raw(f.shl(50))); + + let log_sqrt10001 = log_2.wrapping_mul(SQRT_10001); + + let tick_low = (log_sqrt10001.saturating_sub(TICK_LOW) >> 128_u8).low_i32(); + + let tick_high = (log_sqrt10001.saturating_add(TICK_HIGH) >> 128_u8).low_i32(); + + let tick = if tick_low == tick_high { + tick_low + } else if get_sqrt_ratio_at_tick(tick_high)? <= sqrt_price_x_96 { + tick_high + } else { + tick_low + }; + + Ok(tick) +} + +// Convert U64F64 to U256 in Q64.96 format (Uniswap's sqrt price format) +fn u64f64_to_u256_q64_96(value: U64F64) -> U256 { + u64f64_to_u256(value, 96) +} + +/// Convert U64F64 to U256 +/// +/// # Arguments +/// * `value` - The U64F64 value to convert +/// * `target_fractional_bits` - Number of fractional bits in the target U256 format +/// +/// # Returns +/// * `U256` - Converted value +#[allow(clippy::arithmetic_side_effects)] +fn u64f64_to_u256(value: U64F64, target_fractional_bits: u32) -> U256 { + let raw = U256::from(value.to_bits()); + + match target_fractional_bits.cmp(&64) { + Ordering::Less => raw >> (64 - target_fractional_bits), + Ordering::Greater => raw.saturating_shl((target_fractional_bits - 64) as usize), + Ordering::Equal => raw, + } +} + +/// Convert U256 in Q64.96 format (Uniswap's sqrt price format) to U64F64 +fn u256_q64_96_to_u64f64(value: U256) -> Result { + q_to_u64f64(value, 96) +} + +#[allow(clippy::arithmetic_side_effects)] +fn q_to_u64f64(x: U256, frac_bits: u32) -> Result { + let diff = frac_bits.saturating_sub(64) as usize; + + // 1. shift right diff bits + let shifted = if diff != 0 { x >> diff } else { x }; + + // 2. **round up** if we threw away any 1‑bits + let mask = if diff != 0 { + (U256_1.saturating_shl(diff)).saturating_sub(U256_1) + } else { + U256::ZERO + }; + let rounded = if diff != 0 && (x & mask) != U256::ZERO { + shifted.saturating_add(U256_1) + } else { + shifted + }; + + // 3. check that it fits in 128 bits and transmute + if (rounded >> 128) != U256::ZERO { + return Err(TickMathError::Overflow); + } + Ok(U64F64::from_bits(rounded.to::())) +} + +#[derive(Debug, PartialEq, Eq)] +pub enum TickMathError { + TickOutOfBounds, + SqrtPriceOutOfBounds, + ConversionError, + Overflow, + DivisionByZero, +} + +impl fmt::Display for TickMathError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::TickOutOfBounds => f.write_str("The given tick is outside of the minimum/maximum values."), + Self::SqrtPriceOutOfBounds =>f.write_str("Second inequality must be < because the price can never reach the price at the max tick"), + Self::ConversionError => f.write_str("Error converting from one number type into another"), + Self::Overflow => f.write_str("Number overflow in arithmetic operation"), + Self::DivisionByZero => f.write_str("Division by zero is not allowed") + } + } +} + +impl Error for TickMathError {} + +#[allow(clippy::unwrap_used)] +#[cfg(test)] +mod tests { + use safe_math::FixedExt; + use std::{ops::Sub, str::FromStr}; + + use super::*; + use crate::mock::*; + + #[test] + fn test_get_sqrt_ratio_at_tick_bounds() { + // the function should return an error if the tick is out of bounds + if let Err(err) = get_sqrt_ratio_at_tick(MIN_TICK - 1) { + assert!(matches!(err, TickMathError::TickOutOfBounds)); + } else { + panic!("get_qrt_ratio_at_tick did not respect lower tick bound") + } + if let Err(err) = get_sqrt_ratio_at_tick(MAX_TICK + 1) { + assert!(matches!(err, TickMathError::TickOutOfBounds)); + } else { + panic!("get_qrt_ratio_at_tick did not respect upper tick bound") + } + } + + #[test] + fn test_get_sqrt_ratio_at_tick_values() { + // test individual values for correct results + assert_eq!( + get_sqrt_ratio_at_tick(MIN_TICK).unwrap(), + U256::from(4295128739u64), + "sqrt ratio at min incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(MIN_TICK + 1).unwrap(), + U256::from(4295343490u64), + "sqrt ratio at min + 1 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(MAX_TICK - 1).unwrap(), + U256::from_str("1461373636630004318706518188784493106690254656249").unwrap(), + "sqrt ratio at max - 1 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(MAX_TICK).unwrap(), + U256::from_str("1461446703485210103287273052203988822378723970342").unwrap(), + "sqrt ratio at max incorrect" + ); + // checking hard coded values against solidity results + assert_eq!( + get_sqrt_ratio_at_tick(50).unwrap(), + U256::from(79426470787362580746886972461u128), + "sqrt ratio at 50 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(100).unwrap(), + U256::from(79625275426524748796330556128u128), + "sqrt ratio at 100 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(250).unwrap(), + U256::from(80224679980005306637834519095u128), + "sqrt ratio at 250 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(500).unwrap(), + U256::from(81233731461783161732293370115u128), + "sqrt ratio at 500 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(1000).unwrap(), + U256::from(83290069058676223003182343270u128), + "sqrt ratio at 1000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(2500).unwrap(), + U256::from(89776708723587163891445672585u128), + "sqrt ratio at 2500 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(3000).unwrap(), + U256::from(92049301871182272007977902845u128), + "sqrt ratio at 3000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(4000).unwrap(), + U256::from(96768528593268422080558758223u128), + "sqrt ratio at 4000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(5000).unwrap(), + U256::from(101729702841318637793976746270u128), + "sqrt ratio at 5000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(50000).unwrap(), + U256::from(965075977353221155028623082916u128), + "sqrt ratio at 50000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(150000).unwrap(), + U256::from(143194173941309278083010301478497u128), + "sqrt ratio at 150000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(250000).unwrap(), + U256::from(21246587762933397357449903968194344u128), + "sqrt ratio at 250000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(500000).unwrap(), + U256::from_str("5697689776495288729098254600827762987878").unwrap(), + "sqrt ratio at 500000 incorrect" + ); + assert_eq!( + get_sqrt_ratio_at_tick(738203).unwrap(), + U256::from_str("847134979253254120489401328389043031315994541").unwrap(), + "sqrt ratio at 738203 incorrect" + ); + } + + #[test] + fn test_get_tick_at_sqrt_ratio() { + //throws for too low + let result = get_tick_at_sqrt_ratio(MIN_SQRT_RATIO.sub(U256_1)); + assert_eq!( + result.unwrap_err().to_string(), + "Second inequality must be < because the price can never reach the price at the max tick" + ); + + //throws for too high + let result = get_tick_at_sqrt_ratio(MAX_SQRT_RATIO); + assert_eq!( + result.unwrap_err().to_string(), + "Second inequality must be < because the price can never reach the price at the max tick" + ); + + //ratio of min tick + let result = get_tick_at_sqrt_ratio(MIN_SQRT_RATIO).unwrap(); + assert_eq!(result, MIN_TICK); + + //ratio of min tick + 1 + let result = get_tick_at_sqrt_ratio(U256::from_str("4295343490").unwrap()).unwrap(); + assert_eq!(result, MIN_TICK + 1); + } + + #[test] + fn test_roundtrip() { + for tick_index in [ + MIN_TICK + 1, // we can't use extremes because of rounding during roundtrip conversion + -1000, + -100, + -10, + -4, + -2, + 0, + 2, + 4, + 10, + 100, + 1000, + MAX_TICK - 1, + ] + .iter() + { + let sqrt_price = get_sqrt_ratio_at_tick(*tick_index).unwrap(); + let round_trip_tick_index = get_tick_at_sqrt_ratio(sqrt_price).unwrap(); + assert_eq!(round_trip_tick_index, *tick_index); + } + } + + #[test] + fn test_u256_to_u64f64_q64_96() { + // Test tick 0 (sqrt price = 1.0 * 2^96) + let tick0_sqrt_price = U256::from(1u128 << 96); + let fixed_price = u256_q64_96_to_u64f64(tick0_sqrt_price).unwrap(); + + // Should be 1.0 in U64F64 + assert_eq!(fixed_price, U64F64::from_num(1.0)); + + // Round trip back to U256 Q64.96 + let back_to_u256 = u64f64_to_u256_q64_96(fixed_price); + assert_eq!(back_to_u256, tick0_sqrt_price); + } + + #[test] + fn test_tick_index_to_sqrt_price() { + let tick_spacing = SqrtPrice::from_num(1.0001); + + // check tick bounds + assert_eq!( + TickIndex(MIN_TICK).try_to_sqrt_price(), + Err(TickMathError::TickOutOfBounds) + ); + + assert_eq!( + TickIndex(MAX_TICK).try_to_sqrt_price(), + Err(TickMathError::TickOutOfBounds), + ); + + assert!( + TickIndex::MAX.try_to_sqrt_price().unwrap().abs_diff( + TickIndex::new_unchecked(TickIndex::MAX.get() + 1).as_sqrt_price_bounded() + ) < SqrtPrice::from_num(1e-6) + ); + + assert!( + TickIndex::MIN.try_to_sqrt_price().unwrap().abs_diff( + TickIndex::new_unchecked(TickIndex::MIN.get() - 1).as_sqrt_price_bounded() + ) < SqrtPrice::from_num(1e-6) + ); + + // At tick index 0, the sqrt price should be 1.0 + let sqrt_price = TickIndex(0).try_to_sqrt_price().unwrap(); + assert_eq!(sqrt_price, SqrtPrice::from_num(1.0)); + + let sqrt_price = TickIndex(2).try_to_sqrt_price().unwrap(); + assert!(sqrt_price.abs_diff(tick_spacing) < SqrtPrice::from_num(1e-10)); + + let sqrt_price = TickIndex(4).try_to_sqrt_price().unwrap(); + // Calculate the expected value: (1 + TICK_SPACING/1e9 + 1.0)^2 + let expected = tick_spacing * tick_spacing; + assert!(sqrt_price.abs_diff(expected) < SqrtPrice::from_num(1e-10)); + + // Test with tick index 10 + let sqrt_price = TickIndex(10).try_to_sqrt_price().unwrap(); + // Calculate the expected value: (1 + TICK_SPACING/1e9 + 1.0)^5 + let expected = tick_spacing.checked_pow(5).unwrap(); + assert!( + sqrt_price.abs_diff(expected) < SqrtPrice::from_num(1e-10), + "diff: {}", + sqrt_price.abs_diff(expected), + ); + } + + #[test] + fn test_sqrt_price_to_tick_index() { + let tick_spacing = SqrtPrice::from_num(1.0001); + let tick_index = TickIndex::try_from_sqrt_price(SqrtPrice::from_num(1.0)).unwrap(); + assert_eq!(tick_index, TickIndex::new_unchecked(0)); + + // Test with sqrt price equal to tick_spacing_tao (should be tick index 2) + let epsilon = SqrtPrice::from_num(0.0000000000000001); + assert!( + TickIndex::new_unchecked(2) + .as_sqrt_price_bounded() + .abs_diff(tick_spacing) + < epsilon + ); + + // Test with sqrt price equal to tick_spacing_tao^2 (should be tick index 4) + let sqrt_price = tick_spacing * tick_spacing; + assert!( + TickIndex::new_unchecked(4) + .as_sqrt_price_bounded() + .abs_diff(sqrt_price) + < epsilon + ); + + // Test with sqrt price equal to tick_spacing_tao^5 (should be tick index 10) + let sqrt_price = tick_spacing.checked_pow(5).unwrap(); + assert!( + TickIndex::new_unchecked(10) + .as_sqrt_price_bounded() + .abs_diff(sqrt_price) + < epsilon + ); + } + + #[test] + fn test_roundtrip_tick_index_sqrt_price() { + for i32_value in [ + TickIndex::MIN.get(), + -1000, + -100, + -10, + -4, + -2, + 0, + 2, + 4, + 10, + 100, + 1000, + TickIndex::MAX.get(), + ] + .into_iter() + { + let tick_index = TickIndex::new_unchecked(i32_value); + let sqrt_price = tick_index.try_to_sqrt_price().unwrap(); + let round_trip_tick_index = TickIndex::try_from_sqrt_price(sqrt_price).unwrap(); + assert_eq!(round_trip_tick_index, tick_index); + } + } + + #[test] + fn test_from_offset_index() { + // Test various tick indices + for i32_value in [ + TickIndex::MIN.get(), + -1000, + -100, + -10, + 0, + 10, + 100, + 1000, + TickIndex::MAX.get(), + ] { + let original_tick = TickIndex::new_unchecked(i32_value); + + // Calculate the offset index (adding OFFSET) + let offset_index = (i32_value + TickIndex::OFFSET.get()) as u32; + + // Convert back from offset index to tick index + let roundtrip_tick = TickIndex::from_offset_index(offset_index).unwrap(); + + // Check that we get the same tick index back + assert_eq!(original_tick, roundtrip_tick); + } + + // Test out of bounds values + let too_large = (TickIndex::MAX.get() + TickIndex::OFFSET.get() + 1) as u32; + assert!(TickIndex::from_offset_index(too_large).is_err()); + } + + #[test] + fn test_tick_price_sanity_check() { + let min_price = TickIndex::MIN.try_to_sqrt_price().unwrap(); + let max_price = TickIndex::MAX.try_to_sqrt_price().unwrap(); + + assert!(min_price > 0.); + assert!(max_price > 0.); + assert!(max_price > min_price); + assert!(min_price < 0.000001); + assert!(max_price > 10.); + + // Roundtrip conversions + let min_price_sqrt = TickIndex::MIN.try_to_sqrt_price().unwrap(); + let min_tick = TickIndex::try_from_sqrt_price(min_price_sqrt).unwrap(); + assert_eq!(min_tick, TickIndex::MIN); + + let max_price_sqrt: SqrtPrice = TickIndex::MAX.try_to_sqrt_price().unwrap(); + let max_tick = TickIndex::try_from_sqrt_price(max_price_sqrt).unwrap(); + assert_eq!(max_tick, TickIndex::MAX); + } + + #[test] + fn test_to_sqrt_price_bounded() { + assert_eq!( + TickIndex::MAX.as_sqrt_price_bounded(), + TickIndex::MAX.try_to_sqrt_price().unwrap() + ); + + assert_eq!( + TickIndex::MIN.as_sqrt_price_bounded(), + TickIndex::MIN.try_to_sqrt_price().unwrap() + ); + } + + mod active_tick_index_manager { + + use super::*; + + #[test] + fn test_tick_search_basic() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + ActiveTickIndexManager::::insert(netuid, TickIndex::MIN); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MIN) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MAX) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.saturating_div(2) + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.prev().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.next().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, TickIndex::MIN) + .unwrap(), + TickIndex::MIN + ); + assert!( + ActiveTickIndexManager::::find_closest_higher(netuid, TickIndex::MAX) + .is_none() + ); + assert!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MAX.saturating_div(2) + ) + .is_none() + ); + assert!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MAX.prev().unwrap() + ) + .is_none() + ); + assert!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MIN.next().unwrap() + ) + .is_none() + ); + + ActiveTickIndexManager::::insert(netuid, TickIndex::MAX); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MIN) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MAX) + .unwrap(), + TickIndex::MAX + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.saturating_div(2) + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.prev().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.next().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + }); + } + + #[test] + fn test_tick_search_sparse_queries() { + new_test_ext().execute_with(|| { + let active_index = TickIndex::MIN.saturating_add(10); + let netuid = NetUid::from(1); + + ActiveTickIndexManager::::insert(netuid, active_index); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, active_index) + .unwrap(), + active_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.saturating_add(11) + ) + .unwrap(), + active_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.saturating_add(12) + ) + .unwrap(), + active_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MIN), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.saturating_add(9) + ), + None + ); + + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, active_index) + .unwrap(), + active_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MIN.saturating_add(11) + ), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MIN.saturating_add(12) + ), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, TickIndex::MIN) + .unwrap(), + active_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MIN.saturating_add(9) + ) + .unwrap(), + active_index + ); + }); + } + + #[test] + fn test_tick_search_many_lows() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + (0..1000).for_each(|i| { + ActiveTickIndexManager::::insert( + netuid, + TickIndex::MIN.saturating_add(i), + ); + }); + + for i in 0..1000 { + let test_index = TickIndex::MIN.saturating_add(i); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, test_index) + .unwrap(), + test_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, test_index) + .unwrap(), + test_index + ); + } + }); + } + + #[test] + fn test_tick_search_many_sparse() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let count = 1000; + + for i in 0..=count { + ActiveTickIndexManager::::insert( + netuid, + TickIndex::new_unchecked(i * 10), + ); + } + + for i in 1..count { + let tick = TickIndex::new_unchecked(i * 10); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, tick).unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, tick).unwrap(), + tick + ); + for j in 1..=9 { + let before_tick = TickIndex::new_unchecked(i * 10 - j); + let after_tick = TickIndex::new_unchecked(i * 10 + j); + let prev_tick = TickIndex::new_unchecked((i - 1) * 10); + let next_tick = TickIndex::new_unchecked((i + 1) * 10); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, before_tick) + .unwrap(), + prev_tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, after_tick) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + before_tick + ) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, after_tick) + .unwrap(), + next_tick + ); + } + } + }); + } + + #[test] + fn test_tick_search_many_lows_sparse_reversed() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let count = 1000; + + for i in (0..=count).rev() { + ActiveTickIndexManager::::insert( + netuid, + TickIndex::new_unchecked(i * 10), + ); + } + + for i in 1..count { + let tick = TickIndex::new_unchecked(i * 10); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, tick).unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, tick).unwrap(), + tick + ); + for j in 1..=9 { + let before_tick = TickIndex::new_unchecked(i * 10 - j); + let after_tick = TickIndex::new_unchecked(i * 10 + j); + let prev_tick = TickIndex::new_unchecked((i - 1) * 10); + let next_tick = TickIndex::new_unchecked((i + 1) * 10); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, before_tick) + .unwrap(), + prev_tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, after_tick) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + before_tick + ) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, after_tick) + .unwrap(), + next_tick + ); + } + } + }); + } + + #[test] + fn test_tick_search_repeated_insertions() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let count = 1000; + + for _ in 0..10 { + for i in 0..=count { + let tick = TickIndex::new_unchecked(i * 10); + ActiveTickIndexManager::::insert(netuid, tick); + } + + for i in 1..count { + let tick = TickIndex::new_unchecked(i * 10); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, tick) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, tick) + .unwrap(), + tick + ); + for j in 1..=9 { + let before_tick = TickIndex::new_unchecked(i * 10 - j); + let after_tick = TickIndex::new_unchecked(i * 10 + j); + let prev_tick = TickIndex::new_unchecked((i - 1) * 10); + let next_tick = TickIndex::new_unchecked((i + 1) * 10); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + before_tick + ) + .unwrap(), + prev_tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, after_tick + ) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + before_tick + ) + .unwrap(), + tick + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, after_tick + ) + .unwrap(), + next_tick + ); + } + } + } + }); + } + + #[test] + fn test_tick_search_full_range() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let step = 1019; + // Get the full valid tick range by subtracting MIN from MAX + let count = (TickIndex::MAX.get() - TickIndex::MIN.get()) / step; + + for i in 0..=count { + let index = TickIndex::MIN.saturating_add(i * step); + ActiveTickIndexManager::::insert(netuid, index); + } + for i in 1..count { + let index = TickIndex::MIN.saturating_add(i * step); + + let prev_index = TickIndex::new_unchecked(index.get() - step); + let next_minus_one = TickIndex::new_unchecked(index.get() + step - 1); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, prev_index) + .unwrap(), + prev_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, index).unwrap(), + index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, next_minus_one) + .unwrap(), + index + ); + + let mid_next = TickIndex::new_unchecked(index.get() + step / 2); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, mid_next) + .unwrap(), + index + ); + + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, index).unwrap(), + index + ); + + let next_index = TickIndex::new_unchecked(index.get() + step); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, next_index) + .unwrap(), + next_index + ); + + let mid_next = TickIndex::new_unchecked(index.get() + step / 2); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, mid_next) + .unwrap(), + next_index + ); + + let next_minus_1 = TickIndex::new_unchecked(index.get() + step - 1); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, next_minus_1) + .unwrap(), + next_index + ); + for j in 1..=9 { + let before_index = TickIndex::new_unchecked(index.get() - j); + let after_index = TickIndex::new_unchecked(index.get() + j); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + before_index + ) + .unwrap(), + prev_index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, after_index) + .unwrap(), + index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + before_index + ) + .unwrap(), + index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + after_index + ) + .unwrap(), + next_index + ); + } + } + }); + } + + #[test] + fn test_tick_remove_basic() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + + ActiveTickIndexManager::::insert(netuid, TickIndex::MIN); + ActiveTickIndexManager::::insert(netuid, TickIndex::MAX); + ActiveTickIndexManager::::remove(netuid, TickIndex::MAX); + + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MIN) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, TickIndex::MAX) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.saturating_div(2) + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MAX.prev().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_lower( + netuid, + TickIndex::MIN.next().unwrap() + ) + .unwrap(), + TickIndex::MIN + ); + + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, TickIndex::MIN) + .unwrap(), + TickIndex::MIN + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, TickIndex::MAX), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MAX.saturating_div(2) + ), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MAX.prev().unwrap() + ), + None + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher( + netuid, + TickIndex::MIN.next().unwrap() + ), + None + ); + }); + } + + #[test] + fn test_tick_remove_full_range() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1); + let step = 1019; + // Get the full valid tick range by subtracting MIN from MAX + let count = (TickIndex::MAX.get() - TickIndex::MIN.get()) / step; + let remove_frequency = 5; // Remove every 5th tick + + // Insert ticks + for i in 0..=count { + let index = TickIndex::MIN.saturating_add(i * step); + ActiveTickIndexManager::::insert(netuid, index); + } + + // Remove some ticks + for i in 1..count { + if i % remove_frequency == 0 { + let index = TickIndex::MIN.saturating_add(i * step); + ActiveTickIndexManager::::remove(netuid, index); + } + } + + // Verify + for i in 1..count { + let index = TickIndex::MIN.saturating_add(i * step); + + if i % remove_frequency == 0 { + let lower = + ActiveTickIndexManager::::find_closest_lower(netuid, index); + let higher = + ActiveTickIndexManager::::find_closest_higher(netuid, index); + assert!(lower != Some(index)); + assert!(higher != Some(index)); + } else { + assert_eq!( + ActiveTickIndexManager::::find_closest_lower(netuid, index) + .unwrap(), + index + ); + assert_eq!( + ActiveTickIndexManager::::find_closest_higher(netuid, index) + .unwrap(), + index + ); + } + } + }); + } + } +} diff --git a/pallets/swap/src/weights.rs b/pallets/swap/src/weights.rs new file mode 100644 index 0000000000..2bbbb8dbdf --- /dev/null +++ b/pallets/swap/src/weights.rs @@ -0,0 +1,94 @@ +//! Weights for pallet_subtensor_swap +//! +//! This is a default weight implementation with conservative estimates +//! until actual benchmarks are run. + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{Weight, constants::RocksDbWeight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_subtensor_swap. +pub trait WeightInfo { + fn set_fee_rate() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; + fn modify_position() -> Weight; + fn toggle_user_liquidity() -> Weight; +} + +/// Default weights for pallet_subtensor_swap. +pub struct DefaultWeight(PhantomData); +impl WeightInfo for DefaultWeight { + fn set_fee_rate() -> Weight { + // Conservative weight estimate: one read and one write + Weight::from_parts(10_000_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + + fn add_liquidity() -> Weight { + // Conservative weight estimate for add_liquidity + Weight::from_parts(50_000_000, 0) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn remove_liquidity() -> Weight { + // Conservative weight estimate for remove_liquidity + Weight::from_parts(50_000_000, 0) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn modify_position() -> Weight { + // Conservative weight estimate for modify_position + Weight::from_parts(50_000_000, 0) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + + fn toggle_user_liquidity() -> Weight { + // Conservative weight estimate: one read and one write + Weight::from_parts(10_000_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn set_fee_rate() -> Weight { + Weight::from_parts(10_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) + } + + fn add_liquidity() -> Weight { + Weight::from_parts(50_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + + fn remove_liquidity() -> Weight { + Weight::from_parts(50_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(4)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + + fn modify_position() -> Weight { + Weight::from_parts(50_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(4)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + + fn toggle_user_liquidity() -> Weight { + Weight::from_parts(10_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) + } +} diff --git a/pallets/utility/src/lib.rs b/pallets/utility/src/lib.rs index 2677f744b6..35f11cbc53 100644 --- a/pallets/utility/src/lib.rs +++ b/pallets/utility/src/lib.rs @@ -260,7 +260,7 @@ pub mod pallet { T::WeightInfo::as_derivative() // AccountData for inner call origin accountdata. .saturating_add(T::DbWeight::get().reads_writes(1, 1)) - .saturating_add(dispatch_info.weight), + .saturating_add(dispatch_info.call_weight), dispatch_info.class, ) })] @@ -368,7 +368,7 @@ pub mod pallet { let dispatch_info = call.get_dispatch_info(); ( T::WeightInfo::dispatch_as() - .saturating_add(dispatch_info.weight), + .saturating_add(dispatch_info.call_weight), dispatch_info.class, ) })] @@ -484,7 +484,7 @@ pub mod pallet { |(total_weight, dispatch_class), di| { ( if di.pays_fee == Pays::Yes { - total_weight.saturating_add(di.weight) + total_weight.saturating_add(di.call_weight) } else { total_weight }, diff --git a/pallets/utility/src/tests.rs b/pallets/utility/src/tests.rs index 34ed8d323e..f0389187a9 100644 --- a/pallets/utility/src/tests.rs +++ b/pallets/utility/src/tests.rs @@ -327,7 +327,7 @@ fn as_derivative_handles_weight_refund() { let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(1)); assert_ok!(result); - assert_eq!(extract_actual_weight(&result, &info), info.weight); + assert_eq!(extract_actual_weight(&result, &info), info.call_weight); // Refund weight when ok let inner_call = call_foobar(false, start_weight, Some(end_weight)); @@ -339,7 +339,10 @@ fn as_derivative_handles_weight_refund() { let result = call.dispatch(RuntimeOrigin::signed(1)); assert_ok!(result); // Diff is refunded - assert_eq!(extract_actual_weight(&result, &info), info.weight - diff); + assert_eq!( + extract_actual_weight(&result, &info), + info.call_weight - diff + ); // Full weight when err let inner_call = call_foobar(true, start_weight, None); @@ -354,7 +357,7 @@ fn as_derivative_handles_weight_refund() { DispatchErrorWithPostInfo { post_info: PostDispatchInfo { // No weight is refunded - actual_weight: Some(info.weight), + actual_weight: Some(info.call_weight), pays_fee: Pays::Yes, }, error: DispatchError::Other("The cake is a lie."), @@ -374,7 +377,7 @@ fn as_derivative_handles_weight_refund() { DispatchErrorWithPostInfo { post_info: PostDispatchInfo { // Diff is refunded - actual_weight: Some(info.weight - diff), + actual_weight: Some(info.call_weight - diff), pays_fee: Pays::Yes, }, error: DispatchError::Other("The cake is a lie."), @@ -489,14 +492,14 @@ fn batch_weight_calculation_doesnt_overflow() { let big_call = RuntimeCall::RootTesting(RootTestingCall::fill_block { ratio: Perbill::from_percent(50), }); - assert_eq!(big_call.get_dispatch_info().weight, Weight::MAX / 2); + assert_eq!(big_call.get_dispatch_info().call_weight, Weight::MAX / 2); // 3 * 50% saturates to 100% let batch_call = RuntimeCall::Utility(crate::Call::batch { calls: vec![big_call.clone(), big_call.clone(), big_call.clone()], }); - assert_eq!(batch_call.get_dispatch_info().weight, Weight::MAX); + assert_eq!(batch_call.get_dispatch_info().call_weight, Weight::MAX); }); } @@ -515,7 +518,7 @@ fn batch_handles_weight_refund() { let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(1)); assert_ok!(result); - assert_eq!(extract_actual_weight(&result, &info), info.weight); + assert_eq!(extract_actual_weight(&result, &info), info.call_weight); // Refund weight when ok let inner_call = call_foobar(false, start_weight, Some(end_weight)); @@ -527,7 +530,7 @@ fn batch_handles_weight_refund() { // Diff is refunded assert_eq!( extract_actual_weight(&result, &info), - info.weight - diff * batch_len + info.call_weight - diff * batch_len ); // Full weight when err @@ -546,7 +549,7 @@ fn batch_handles_weight_refund() { .into(), ); // No weight is refunded - assert_eq!(extract_actual_weight(&result, &info), info.weight); + assert_eq!(extract_actual_weight(&result, &info), info.call_weight); // Refund weight when err let good_call = call_foobar(false, start_weight, Some(end_weight)); @@ -566,7 +569,7 @@ fn batch_handles_weight_refund() { ); assert_eq!( extract_actual_weight(&result, &info), - info.weight - diff * batch_len + info.call_weight - diff * batch_len ); // Partial batch completion @@ -626,7 +629,7 @@ fn batch_all_revert() { DispatchErrorWithPostInfo { post_info: PostDispatchInfo { actual_weight: Some( - ::WeightInfo::batch_all(2) + info.weight * 2 + ::WeightInfo::batch_all(2) + info.call_weight * 2 ), pays_fee: Pays::Yes }, @@ -653,7 +656,7 @@ fn batch_all_handles_weight_refund() { let info = call.get_dispatch_info(); let result = call.dispatch(RuntimeOrigin::signed(1)); assert_ok!(result); - assert_eq!(extract_actual_weight(&result, &info), info.weight); + assert_eq!(extract_actual_weight(&result, &info), info.call_weight); // Refund weight when ok let inner_call = call_foobar(false, start_weight, Some(end_weight)); @@ -665,7 +668,7 @@ fn batch_all_handles_weight_refund() { // Diff is refunded assert_eq!( extract_actual_weight(&result, &info), - info.weight - diff * batch_len + info.call_weight - diff * batch_len ); // Full weight when err @@ -677,7 +680,7 @@ fn batch_all_handles_weight_refund() { let result = call.dispatch(RuntimeOrigin::signed(1)); assert_err_ignore_postinfo!(result, "The cake is a lie."); // No weight is refunded - assert_eq!(extract_actual_weight(&result, &info), info.weight); + assert_eq!(extract_actual_weight(&result, &info), info.call_weight); // Refund weight when err let good_call = call_foobar(false, start_weight, Some(end_weight)); @@ -690,7 +693,7 @@ fn batch_all_handles_weight_refund() { assert_err_ignore_postinfo!(result, "The cake is a lie."); assert_eq!( extract_actual_weight(&result, &info), - info.weight - diff * batch_len + info.call_weight - diff * batch_len ); // Partial batch completion @@ -729,7 +732,9 @@ fn batch_all_does_not_nest() { Utility::batch_all(RuntimeOrigin::signed(1), vec![batch_all.clone()]), DispatchErrorWithPostInfo { post_info: PostDispatchInfo { - actual_weight: Some(::WeightInfo::batch_all(1) + info.weight), + actual_weight: Some( + ::WeightInfo::batch_all(1) + info.call_weight + ), pays_fee: Pays::Yes }, error: frame_system::Error::::CallFiltered.into(), @@ -868,7 +873,7 @@ fn batch_all_doesnt_work_with_inherents() { batch_all.dispatch(RuntimeOrigin::signed(1)), DispatchErrorWithPostInfo { post_info: PostDispatchInfo { - actual_weight: Some(info.weight), + actual_weight: Some(info.call_weight), pays_fee: Pays::Yes }, error: frame_system::Error::::CallFiltered.into(), @@ -886,7 +891,7 @@ fn batch_works_with_council_origin() { )], }); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Council::propose( @@ -926,7 +931,7 @@ fn force_batch_works_with_council_origin() { )], }); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); - let proposal_weight = proposal.get_dispatch_info().weight; + let proposal_weight = proposal.get_dispatch_info().call_weight; let hash = BlakeTwo256::hash_of(&proposal); assert_ok!(Council::propose( @@ -977,7 +982,7 @@ fn with_weight_works() { )); // Weight before is max. assert_eq!( - upgrade_code_call.get_dispatch_info().weight, + upgrade_code_call.get_dispatch_info().call_weight, ::SystemWeightInfo::set_code() ); assert_eq!( @@ -991,7 +996,7 @@ fn with_weight_works() { }; // Weight after is set by Root. assert_eq!( - with_weight_call.get_dispatch_info().weight, + with_weight_call.get_dispatch_info().call_weight, Weight::from_parts(123, 456) ); assert_eq!( diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml index ec46e6aee2..16c73ac76d 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -18,18 +18,22 @@ frame-system = { workspace = true } log = { workspace = true } pallet-balances = { workspace = true } pallet-evm = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } pallet-evm-precompile-modexp = { workspace = true } pallet-evm-precompile-sha3fips = { workspace = true } pallet-evm-precompile-simple = { workspace = true } pallet-proxy = { workspace = true } precompile-utils = { workspace = true } sp-core = { workspace = true } +sp-io = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } subtensor-runtime-common = { workspace = true } - +substrate-fixed = { workspace = true } pallet-subtensor = { workspace = true } +pallet-subtensor-swap = { workspace = true } pallet-admin-utils = { workspace = true } +subtensor-swap-interface = { workspace = true } [lints] workspace = true @@ -44,15 +48,20 @@ std = [ "log/std", "pallet-admin-utils/std", "pallet-balances/std", + "pallet-evm-precompile-dispatch/std", "pallet-evm-precompile-modexp/std", "pallet-evm-precompile-sha3fips/std", "pallet-evm-precompile-simple/std", "pallet-evm/std", "pallet-proxy/std", "pallet-subtensor/std", + "pallet-subtensor-swap/std", "precompile-utils/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", + "substrate-fixed/std", "subtensor-runtime-common/std", + "subtensor-swap-interface/std", ] diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs new file mode 100644 index 0000000000..3a4a36fb79 --- /dev/null +++ b/precompiles/src/alpha.rs @@ -0,0 +1,152 @@ +use core::marker::PhantomData; + +use fp_evm::{ExitError, PrecompileFailure}; +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; +use sp_core::U256; +use substrate_fixed::types::U96F32; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::{OrderType, SwapHandler}; + +use crate::PrecompileExt; + +pub struct AlphaPrecompile(PhantomData); + +impl PrecompileExt for AlphaPrecompile +where + R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config, + R::AccountId: From<[u8; 32]>, +{ + const INDEX: u64 = 2056; +} + +#[precompile_utils::precompile] +impl AlphaPrecompile +where + R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config, +{ + #[precompile::public("getAlphaPrice(uint16)")] + #[precompile::view] + fn get_alpha_price(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + let price = + as SwapHandler>::current_alpha_price( + netuid.into(), + ); + Ok(U256::from(price.saturating_to_num::())) + } + + #[precompile::public("getMovingAlphaPrice(uint16)")] + #[precompile::view] + fn get_moving_alpha_price(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + let price: U96F32 = pallet_subtensor::Pallet::::get_moving_alpha_price(netuid.into()); + Ok(U256::from(price.saturating_to_num::())) + } + + #[precompile::public("getTaoInPool(uint16)")] + #[precompile::view] + fn get_tao_in_pool(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetTAO::::get(NetUid::from(netuid))) + } + + #[precompile::public("getAlphaInPool(uint16)")] + #[precompile::view] + fn get_alpha_in_pool(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetAlphaIn::::get(NetUid::from( + netuid, + ))) + } + + #[precompile::public("getAlphaOutPool(uint16)")] + #[precompile::view] + fn get_alpha_out_pool(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetAlphaOut::::get(NetUid::from( + netuid, + ))) + } + + #[precompile::public("getAlphaIssuance(uint16)")] + #[precompile::view] + fn get_alpha_issuance(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_alpha_issuance( + netuid.into(), + )) + } + + #[precompile::public("getTaoWeight()")] + #[precompile::view] + fn get_tao_weight(_handle: &mut impl PrecompileHandle) -> EvmResult { + let weight = pallet_subtensor::Pallet::::get_tao_weight(); + Ok(U256::from(weight.saturating_to_num::())) + } + + #[precompile::public("simSwapTaoForAlpha(uint16,uint64)")] + #[precompile::view] + fn sim_swap_tao_for_alpha( + _handle: &mut impl PrecompileHandle, + netuid: u16, + tao: u64, + ) -> EvmResult { + let swap_result = + as SwapHandler>::sim_swap( + netuid.into(), + OrderType::Buy, + tao, + ) + .map_err(|e| PrecompileFailure::Error { + exit_status: ExitError::Other(Into::<&'static str>::into(e).into()), + })?; + Ok(U256::from(swap_result.amount_paid_out)) + } + + #[precompile::public("simSwapAlphaForTao(uint16,uint64)")] + #[precompile::view] + fn sim_swap_alpha_for_tao( + _handle: &mut impl PrecompileHandle, + netuid: u16, + alpha: u64, + ) -> EvmResult { + let swap_result = + as SwapHandler>::sim_swap( + netuid.into(), + OrderType::Sell, + alpha, + ) + .map_err(|e| PrecompileFailure::Error { + exit_status: ExitError::Other(Into::<&'static str>::into(e).into()), + })?; + Ok(U256::from(swap_result.amount_paid_out)) + } + + #[precompile::public("getSubnetMechanism(uint16)")] + #[precompile::view] + fn get_subnet_mechanism(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetMechanism::::get(NetUid::from( + netuid, + ))) + } + + #[precompile::public("getRootNetuid()")] + #[precompile::view] + fn get_root_netuid(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(NetUid::ROOT.into()) + } + + #[precompile::public("getEMAPriceHalvingBlocks(uint16)")] + #[precompile::view] + fn get_ema_price_halving_blocks( + _handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::EMAPriceHalvingBlocks::::get( + NetUid::from(netuid), + )) + } + + #[precompile::public("getSubnetVolume(uint16)")] + #[precompile::view] + fn get_subnet_volume(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(U256::from(pallet_subtensor::SubnetVolume::::get( + NetUid::from(netuid), + ))) + } +} diff --git a/precompiles/src/ed25519.rs b/precompiles/src/ed25519.rs index ae23a70e78..5e186f344f 100644 --- a/precompiles/src/ed25519.rs +++ b/precompiles/src/ed25519.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use ed25519_dalek::{Signature, Verifier, VerifyingKey}; use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; -use crate::PrecompileExt; +use crate::{PrecompileExt, parse_slice}; pub(crate) struct Ed25519Verify(PhantomData); @@ -52,21 +52,3 @@ where Ok((ExitSucceed::Returned, buf.to_vec())) } } - -/// Takes a slice from bytes with PrecompileFailure as Error -fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { - let maybe_slice = data.get(from..to); - if let Some(slice) = maybe_slice { - Ok(slice) - } else { - log::error!( - "fail to get slice from data, {:?}, from {}, to {}", - &data, - from, - to - ); - Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } -} diff --git a/precompiles/src/extensions.rs b/precompiles/src/extensions.rs index 1c90922c57..ffa8da5778 100644 --- a/precompiles/src/extensions.rs +++ b/precompiles/src/extensions.rs @@ -56,7 +56,7 @@ pub(crate) trait PrecompileHandleExt: PrecompileHandle { if let Some(gas) = target_gas { let valid_weight = ::GasWeightMapping::gas_to_weight(gas, false).ref_time(); - if info.weight.ref_time() > valid_weight { + if info.call_weight.ref_time() > valid_weight { return Err(PrecompileFailure::Error { exit_status: ExitError::OutOfGas, }); @@ -64,27 +64,27 @@ pub(crate) trait PrecompileHandleExt: PrecompileHandle { } self.record_external_cost( - Some(info.weight.ref_time()), - Some(info.weight.proof_size()), + Some(info.call_weight.ref_time()), + Some(info.call_weight.proof_size()), None, )?; match call.dispatch(R::RuntimeOrigin::from(origin)) { Ok(post_info) => { if post_info.pays_fee(&info) == Pays::Yes { - let actual_weight = post_info.actual_weight.unwrap_or(info.weight); + let actual_weight = post_info.actual_weight.unwrap_or(info.call_weight); let cost = ::GasWeightMapping::weight_to_gas(actual_weight); self.record_cost(cost)?; self.refund_external_cost( Some( - info.weight + info.call_weight .ref_time() .saturating_sub(actual_weight.ref_time()), ), Some( - info.weight + info.call_weight .proof_size() .saturating_sub(actual_weight.proof_size()), ), diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 4c6824e07b..19020a0d1b 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -4,11 +4,16 @@ extern crate alloc; use core::marker::PhantomData; -use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::{ + dispatch::{GetDispatchInfo, PostDispatchInfo}, + pallet_prelude::Decode, +}; use pallet_evm::{ AddressMapping, IsPrecompileResult, Precompile, PrecompileHandle, PrecompileResult, PrecompileSet, }; +use pallet_evm_precompile_dispatch::Dispatch; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; @@ -19,24 +24,29 @@ use subtensor_runtime_common::ProxyType; use pallet_admin_utils::PrecompileEnum; +use crate::alpha::*; use crate::balance_transfer::*; use crate::ed25519::*; use crate::extensions::*; use crate::metagraph::*; use crate::neuron::*; +use crate::sr25519::*; use crate::staking::*; +use crate::storage_query::*; use crate::subnet::*; use crate::uid_lookup::*; +mod alpha; mod balance_transfer; mod ed25519; mod extensions; mod metagraph; mod neuron; +mod sr25519; mod staking; +mod storage_query; mod subnet; mod uid_lookup; - pub struct Precompiles(PhantomData); impl Default for Precompiles @@ -46,6 +56,7 @@ where + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + + pallet_subtensor_swap::Config + pallet_proxy::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> @@ -70,6 +81,7 @@ where + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + + pallet_subtensor_swap::Config + pallet_proxy::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> @@ -86,23 +98,27 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 15] { + pub fn used_addresses() -> [H160; 19] { [ hash(1), hash(2), hash(3), hash(4), hash(5), + hash(6), hash(1024), hash(1025), hash(Ed25519Verify::::INDEX), + hash(Sr25519Verify::::INDEX), hash(BalanceTransferPrecompile::::INDEX), hash(StakingPrecompile::::INDEX), hash(SubnetPrecompile::::INDEX), hash(MetagraphPrecompile::::INDEX), hash(NeuronPrecompile::::INDEX), hash(StakingPrecompileV2::::INDEX), + hash(StorageQueryPrecompile::::INDEX), hash(UidLookupPrecompile::::INDEX), + hash(AlphaPrecompile::::INDEX), ] } } @@ -113,6 +129,7 @@ where + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + + pallet_subtensor_swap::Config + pallet_proxy::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> @@ -120,7 +137,10 @@ where + From> + From> + GetDispatchInfo - + Dispatchable, + + Dispatchable + + Decode, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: + From>>, ::AddressMapping: AddressMapping, ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, @@ -133,12 +153,16 @@ where a if a == hash(3) => Some(Ripemd160::execute(handle)), a if a == hash(4) => Some(Identity::execute(handle)), a if a == hash(5) => Some(Modexp::execute(handle)), + a if a == hash(6) => Some(Dispatch::::execute(handle)), // Non-Frontier specific nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(Ed25519Verify::::INDEX) => { Some(Ed25519Verify::::execute(handle)) } + a if a == hash(Sr25519Verify::::INDEX) => { + Some(Sr25519Verify::::execute(handle)) + } // Subtensor specific precompiles : a if a == hash(BalanceTransferPrecompile::::INDEX) => { BalanceTransferPrecompile::::try_execute::( @@ -164,6 +188,12 @@ where a if a == hash(UidLookupPrecompile::::INDEX) => { UidLookupPrecompile::::try_execute::(handle, PrecompileEnum::UidLookup) } + a if a == hash(StorageQueryPrecompile::::INDEX) => { + Some(StorageQueryPrecompile::::execute(handle)) + } + a if a == hash(AlphaPrecompile::::INDEX) => { + AlphaPrecompile::::try_execute::(handle, PrecompileEnum::Alpha) + } _ => None, } } @@ -179,3 +209,25 @@ where fn hash(a: u64) -> H160 { H160::from_low_u64_be(a) } + +/* + * + * This is used to parse a slice from bytes with PrecompileFailure as Error + * + */ +fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { + let maybe_slice = data.get(from..to); + if let Some(slice) = maybe_slice { + Ok(slice) + } else { + log::error!( + "fail to get slice from data, {:?}, from {}, to {}", + &data, + from, + to + ); + Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }) + } +} diff --git a/precompiles/src/metagraph.rs b/precompiles/src/metagraph.rs index 758ce8f8eb..05f7a5bf79 100644 --- a/precompiles/src/metagraph.rs +++ b/precompiles/src/metagraph.rs @@ -5,6 +5,7 @@ use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle}; use pallet_subtensor::AxonInfo as SubtensorModuleAxonInfo; use precompile_utils::{EvmResult, solidity::Codec}; use sp_core::{ByteArray, H256}; +use subtensor_runtime_common::NetUid; use crate::PrecompileExt; @@ -27,13 +28,15 @@ where #[precompile::public("getUidCount(uint16)")] #[precompile::view] fn get_uid_count(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::SubnetworkN::::get(netuid)) + Ok(pallet_subtensor::SubnetworkN::::get(NetUid::from( + netuid, + ))) } #[precompile::public("getStake(uint16,uint16)")] #[precompile::view] fn get_stake(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid.into(), uid) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::InvalidRange, })?; @@ -46,14 +49,18 @@ where #[precompile::public("getRank(uint16,uint16)")] #[precompile::view] fn get_rank(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_rank_for_uid(netuid, uid)) + Ok(pallet_subtensor::Pallet::::get_rank_for_uid( + netuid.into(), + uid, + )) } #[precompile::public("getTrust(uint16,uint16)")] #[precompile::view] fn get_trust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_trust_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -61,7 +68,8 @@ where #[precompile::view] fn get_consensus(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_consensus_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -69,7 +77,8 @@ where #[precompile::view] fn get_incentive(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_incentive_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -77,7 +86,8 @@ where #[precompile::view] fn get_dividends(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_dividends_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -85,7 +95,8 @@ where #[precompile::view] fn get_emission(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_emission_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -93,7 +104,8 @@ where #[precompile::view] fn get_vtrust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_validator_trust_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -105,7 +117,8 @@ where uid: u16, ) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_validator_permit_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -113,7 +126,8 @@ where #[precompile::view] fn get_last_update(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_last_update_for_uid( - netuid, uid, + netuid.into(), + uid, )) } @@ -121,25 +135,26 @@ where #[precompile::view] fn get_is_active(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { Ok(pallet_subtensor::Pallet::::get_active_for_uid( - netuid, uid, + netuid.into(), + uid, )) } #[precompile::public("getAxon(uint16,uint16)")] #[precompile::view] fn get_axon(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid.into(), uid) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::Other("hotkey not found".into()), })?; - Ok(pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey).into()) + Ok(pallet_subtensor::Pallet::::get_axon_info(netuid.into(), &hotkey).into()) } #[precompile::public("getHotkey(uint16,uint16)")] #[precompile::view] fn get_hotkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid.into(), uid) .map(|acc| H256::from_slice(acc.as_slice())) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::InvalidRange, @@ -149,7 +164,7 @@ where #[precompile::public("getColdkey(uint16,uint16)")] #[precompile::view] fn get_coldkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid.into(), uid) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::InvalidRange, })?; diff --git a/precompiles/src/neuron.rs b/precompiles/src/neuron.rs index cedb3a56db..3e49387bb3 100644 --- a/precompiles/src/neuron.rs +++ b/precompiles/src/neuron.rs @@ -44,7 +44,7 @@ where version_key: u64, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::set_weights { - netuid, + netuid: netuid.into(), dests, weights, version_key, @@ -64,7 +64,7 @@ where commit_hash: H256, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::commit_weights { - netuid, + netuid: netuid.into(), commit_hash, }; @@ -85,7 +85,7 @@ where version_key: u64, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::reveal_weights { - netuid, + netuid: netuid.into(), uids, values, salt, @@ -107,7 +107,10 @@ where ) -> EvmResult<()> { let coldkey = handle.caller_account_id::(); let hotkey = R::AccountId::from(hotkey.0); - let call = pallet_subtensor::Call::::burned_register { netuid, hotkey }; + let call = pallet_subtensor::Call::::burned_register { + netuid: netuid.into(), + hotkey, + }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(coldkey)) } @@ -127,7 +130,7 @@ where placeholder2: u8, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::serve_axon { - netuid, + netuid: netuid.into(), version, ip, port, @@ -161,7 +164,7 @@ where certificate: UnboundedBytes, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::serve_axon_tls { - netuid, + netuid: netuid.into(), version, ip, port, @@ -190,7 +193,7 @@ where ip_type: u8, ) -> EvmResult<()> { let call = pallet_subtensor::Call::::serve_prometheus { - netuid, + netuid: netuid.into(), version, ip, port, diff --git a/precompiles/src/solidity/alpha.abi b/precompiles/src/solidity/alpha.abi new file mode 100644 index 0000000000..feb2b518af --- /dev/null +++ b/precompiles/src/solidity/alpha.abi @@ -0,0 +1,247 @@ +[ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMovingAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getTaoInPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaInPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaOutPool", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAlphaIssuance", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTaoWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "tao", + "type": "uint64" + } + ], + "name": "simSwapTaoForAlpha", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" + } + ], + "name": "simSwapAlphaForTao", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetMechanism", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRootNetuid", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getEMAPriceHalvingBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetVolume", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/alpha.sol b/precompiles/src/solidity/alpha.sol new file mode 100644 index 0000000000..7bb529f684 --- /dev/null +++ b/precompiles/src/solidity/alpha.sol @@ -0,0 +1,70 @@ +pragma solidity ^0.8.0; + +address constant IALPHA_ADDRESS = 0x0000000000000000000000000000000000000808; + +interface IAlpha { + /// @dev Returns the current alpha price for a subnet. + /// @param netuid The subnet identifier. + /// @return The alpha price in RAO per alpha. + function getAlphaPrice(uint16 netuid) external view returns (uint256); + + /// @dev Returns the moving (EMA) alpha price for a subnet. + /// @param netuid The subnet identifier. + /// @return The moving alpha price in RAO per alpha. + function getMovingAlphaPrice(uint16 netuid) external view returns (uint256); + + /// @dev Returns the amount of TAO in the pool for a subnet. + /// @param netuid The subnet identifier. + /// @return The TAO amount in the pool. + function getTaoInPool(uint16 netuid) external view returns (uint64); + + /// @dev Returns the amount of alpha in the pool for a subnet. + /// @param netuid The subnet identifier. + /// @return The alpha amount in the pool. + function getAlphaInPool(uint16 netuid) external view returns (uint64); + + /// @dev Returns the amount of alpha outside the pool for a subnet. + /// @param netuid The subnet identifier. + /// @return The alpha amount outside the pool. + function getAlphaOutPool(uint16 netuid) external view returns (uint64); + + /// @dev Returns the total alpha issuance for a subnet. + /// @param netuid The subnet identifier. + /// @return The total alpha issuance. + function getAlphaIssuance(uint16 netuid) external view returns (uint64); + + /// @dev Returns the global TAO weight. + /// @return The TAO weight value. + function getTaoWeight() external view returns (uint256); + + /// @dev Simulates swapping TAO for alpha. + /// @param netuid The subnet identifier. + /// @param tao The amount of TAO to swap. + /// @return The amount of alpha that would be received. + function simSwapTaoForAlpha(uint16 netuid, uint64 tao) external view returns (uint256); + + /// @dev Simulates swapping alpha for TAO. + /// @param netuid The subnet identifier. + /// @param alpha The amount of alpha to swap. + /// @return The amount of TAO that would be received. + function simSwapAlphaForTao(uint16 netuid, uint64 alpha) external view returns (uint256); + + /// @dev Returns the mechanism type for a subnet (0 for Stable, 1 for Dynamic). + /// @param netuid The subnet identifier. + /// @return The subnet mechanism type. + function getSubnetMechanism(uint16 netuid) external view returns (uint16); + + /// @dev Returns the root subnet unique identifier. + /// @return The root subnet ID. + function getRootNetuid() external view returns (uint16); + + /// @dev Returns the EMA price halving blocks parameter for a subnet. + /// @param netuid The subnet identifier. + /// @return The number of blocks for EMA price halving. + function getEMAPriceHalvingBlocks(uint16 netuid) external view returns (uint64); + + /// @dev Returns the transaction volume for a subnet. + /// @param netuid The subnet identifier. + /// @return The subnet volume. + function getSubnetVolume(uint16 netuid) external view returns (uint256); +} diff --git a/precompiles/src/solidity/sr25519Verify.abi b/precompiles/src/solidity/sr25519Verify.abi new file mode 100644 index 0000000000..05d75ae6cc --- /dev/null +++ b/precompiles/src/solidity/sr25519Verify.abi @@ -0,0 +1,14 @@ +[ + { + "inputs": [ + { "internalType": "bytes32", "name": "message", "type": "bytes32" }, + { "internalType": "bytes32", "name": "publicKey", "type": "bytes32" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "verify", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "pure", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/sr25519Verify.sol b/precompiles/src/solidity/sr25519Verify.sol new file mode 100644 index 0000000000..1c6cbff45a --- /dev/null +++ b/precompiles/src/solidity/sr25519Verify.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.0; + +address constant ISR25519VERIFY_ADDRESS = 0x0000000000000000000000000000000000000403; + +interface ISR25519Verify { + /** + * @dev Verifies SR25519 signature using provided message and public key. + * + * @param message The 32-byte signature payload message. + * @param publicKey 32-byte public key matching to private key used to sign the message. + * @param r The SR25519 signature commitment (first 32 bytes). + * @param s The SR25519 signature response (second 32 bytes). + * @return bool Returns true if the signature is valid for the given message and public key, false otherwise. + */ + function verify(bytes32 message, bytes32 publicKey, bytes32 r, bytes32 s) external pure returns (bool); +} diff --git a/precompiles/src/solidity/subnet.abi b/precompiles/src/solidity/subnet.abi index a2849a0cbe..805c0057d9 100644 --- a/precompiles/src/solidity/subnet.abi +++ b/precompiles/src/solidity/subnet.abi @@ -80,6 +80,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getBondsResetEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -392,12 +411,12 @@ "type": "uint16" } ], - "name": "getServingRateLimit", + "name": "getAlphaSigmoidSteepness", "outputs": [ { - "internalType": "uint64", + "internalType": "uint16", "name": "", - "type": "uint64" + "type": "uint16" } ], "stateMutability": "view", @@ -502,6 +521,59 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "subnetName", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetContact", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "registerNetwork", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -579,6 +651,24 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "bondsResetEnabled", + "type": "bool" + } + ], + "name": "setBondsResetEnabled", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -867,6 +957,24 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "steepness", + "type": "uint16" + } + ], + "name": "setAlphaSigmoidSteepness", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { diff --git a/precompiles/src/solidity/subnet.sol b/precompiles/src/solidity/subnet.sol index 2fa9d3f550..7517db3019 100644 --- a/precompiles/src/solidity/subnet.sol +++ b/precompiles/src/solidity/subnet.sol @@ -16,6 +16,18 @@ interface ISubnet { string memory description, string memory additional ) external payable; + /// Registers a new network with specified subnet name, GitHub repository, contact information, and logo URL. + function registerNetwork( + bytes32 hotkey, + string memory subnetName, + string memory githubRepo, + string memory subnetContact, + string memory subnetUrl, + string memory discord, + string memory description, + string memory logoUrl, + string memory additional + ) external payable; function getServingRateLimit(uint16 netuid) external view returns (uint64); @@ -90,6 +102,15 @@ interface ISubnet { function setRho(uint16 netuid, uint16 rho) external payable; + function getAlphaSigmoidSteepness( + uint16 netuid + ) external view returns (unt16); + + function setAlphaSigmoidSteepness( + uint16 netuid, + int16 steepness + ) external payable; + function getActivityCutoff(uint16 netuid) external view returns (uint16); function setActivityCutoff( @@ -159,6 +180,14 @@ interface ISubnet { bool yuma3Enabled ) external payable; + function getBondsResetEnabled(uint16 netuid) external view returns (bool); + + function setBondsResetEnabled( + uint16 netuid, + bool bondsResetEnabled + ) external payable; + + function getAlphaValues( uint16 netuid ) external view returns (uint16, uint16); diff --git a/precompiles/src/sr25519.rs b/precompiles/src/sr25519.rs new file mode 100644 index 0000000000..c81443dc19 --- /dev/null +++ b/precompiles/src/sr25519.rs @@ -0,0 +1,56 @@ +extern crate alloc; + +use alloc::vec::Vec; +use core::marker::PhantomData; +use sp_core::sr25519; +use sp_runtime::traits::Verify; + +use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; + +use crate::{PrecompileExt, parse_slice}; + +pub(crate) struct Sr25519Verify(PhantomData); + +impl PrecompileExt for Sr25519Verify +where + A: From<[u8; 32]>, +{ + const INDEX: u64 = 1027; +} + +impl LinearCostPrecompile for Sr25519Verify +where + A: From<[u8; 32]>, +{ + const BASE: u64 = 15; + const WORD: u64 = 3; + + fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec), PrecompileFailure> { + if input.len() < 132 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::Other("input must contain 128 bytes".into()), + }); + }; + + let mut buf = [0u8; 32]; + + let msg = parse_slice(input, 4, 36)?; + let pk = sr25519::Public::try_from(parse_slice(input, 36, 68)?).map_err(|_| { + PrecompileFailure::Error { + exit_status: ExitError::Other("Public key recover failed".into()), + } + })?; + let sig = sr25519::Signature::try_from(parse_slice(input, 68, 132)?).map_err(|_| { + PrecompileFailure::Error { + exit_status: ExitError::Other("Signature recover failed".into()), + } + })?; + + let valid = sig.verify(msg, &pk); + if valid { + buf[31] = 1u8; + } + + Ok((ExitSucceed::Returned, buf.to_vec())) + } +} diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 21f50bc917..f26506b14c 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -37,7 +37,7 @@ use precompile_utils::EvmResult; use sp_core::{H256, U256}; use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; use sp_std::vec; -use subtensor_runtime_common::ProxyType; +use subtensor_runtime_common::{NetUid, ProxyType}; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -94,7 +94,7 @@ where let netuid = try_u16_from_u256(netuid)?; let call = pallet_subtensor::Call::::add_stake { hotkey, - netuid, + netuid: netuid.into(), amount_staked, }; @@ -114,7 +114,7 @@ where let amount_unstaked = amount_alpha.unique_saturated_into(); let call = pallet_subtensor::Call::::remove_stake { hotkey, - netuid, + netuid: netuid.into(), amount_unstaked, }; @@ -139,8 +139,8 @@ where let call = pallet_subtensor::Call::::move_stake { origin_hotkey, destination_hotkey, - origin_netuid, - destination_netuid, + origin_netuid: origin_netuid.into(), + destination_netuid: destination_netuid.into(), alpha_amount, }; @@ -165,8 +165,8 @@ where let call = pallet_subtensor::Call::::transfer_stake { destination_coldkey, hotkey, - origin_netuid, - destination_netuid, + origin_netuid: origin_netuid.into(), + destination_netuid: destination_netuid.into(), alpha_amount, }; @@ -209,7 +209,9 @@ where let coldkey = R::AccountId::from(coldkey.0); let netuid = try_u16_from_u256(netuid)?; let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, + &hotkey, + &coldkey, + netuid.into(), ); Ok(stake.into()) @@ -224,7 +226,7 @@ where ) -> EvmResult> { let hotkey = R::AccountId::from(hotkey.0); let mut coldkeys: Vec = vec![]; - let netuid = try_u16_from_u256(netuid)?; + let netuid = NetUid::from(try_u16_from_u256(netuid)?); for ((coldkey, netuid_in_alpha), _) in pallet_subtensor::Alpha::::iter_prefix((hotkey,)) { if netuid == netuid_in_alpha { @@ -245,7 +247,8 @@ where ) -> EvmResult { let hotkey = R::AccountId::from(hotkey.0); let netuid = try_u16_from_u256(netuid)?; - let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_on_subnet(&hotkey, netuid); + let stake = + pallet_subtensor::Pallet::::get_stake_for_hotkey_on_subnet(&hotkey, netuid.into()); Ok(stake.into()) } @@ -294,7 +297,7 @@ where let netuid = try_u16_from_u256(netuid)?; let call = pallet_subtensor::Call::::add_stake_limit { hotkey, - netuid, + netuid: netuid.into(), amount_staked, limit_price, allow_partial, @@ -319,7 +322,7 @@ where let limit_price = limit_price_rao.unique_saturated_into(); let call = pallet_subtensor::Call::::remove_stake_limit { hotkey, - netuid, + netuid: netuid.into(), amount_unstaked, limit_price, allow_partial, @@ -385,7 +388,7 @@ where let netuid = try_u16_from_u256(netuid)?; let call = pallet_subtensor::Call::::add_stake { hotkey, - netuid, + netuid: netuid.into(), amount_staked: amount_sub.unique_saturated_into(), }; @@ -409,7 +412,7 @@ where .ok_or(ExitError::OutOfFund)?; let call = pallet_subtensor::Call::::remove_stake { hotkey, - netuid, + netuid: netuid.into(), amount_unstaked, }; @@ -466,7 +469,9 @@ where let coldkey = R::AccountId::from(coldkey.0); let netuid = try_u16_from_u256(netuid)?; let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, + &hotkey, + &coldkey, + netuid.into(), ); let stake: SubstrateBalance = stake.into(); let stake = ::BalanceConverter::into_evm_balance(stake) diff --git a/precompiles/src/storage_query.rs b/precompiles/src/storage_query.rs new file mode 100644 index 0000000000..b9455ae708 --- /dev/null +++ b/precompiles/src/storage_query.rs @@ -0,0 +1,56 @@ +use core::marker::PhantomData; + +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use pallet_evm::{ExitSucceed, Precompile, PrecompileHandle, PrecompileOutput}; +use sp_runtime::traits::{Dispatchable, StaticLookup}; +use sp_std::vec::Vec; + +use crate::PrecompileExt; + +pub(crate) struct StorageQueryPrecompile(PhantomData); + +impl PrecompileExt for StorageQueryPrecompile +where + R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: + GetDispatchInfo + Dispatchable, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + <::Lookup as StaticLookup>::Source: From, +{ + const INDEX: u64 = 2055; +} + +impl Precompile for StorageQueryPrecompile +where + R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, + R::AccountId: From<[u8; 32]>, + ::RuntimeCall: + GetDispatchInfo + Dispatchable, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + <::Lookup as StaticLookup>::Source: From, +{ + fn execute(handle: &mut impl PrecompileHandle) -> fp_evm::PrecompileResult { + let input = handle.input(); + let data = sp_io::storage::get(input); + + match data { + Some(value) => { + let result = value.to_vec(); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result, + }) + } + None => Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: Vec::new(), + }), + } + } +} diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index 7d4dd175e3..3a598db61c 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -7,6 +7,8 @@ use pallet_evm::{AddressMapping, PrecompileHandle}; use precompile_utils::{EvmResult, prelude::BoundedString}; use sp_core::H256; use sp_runtime::traits::Dispatchable; +use sp_std::vec; +use subtensor_runtime_common::NetUid; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -74,13 +76,54 @@ where additional: BoundedString>, ) -> EvmResult<()> { let hotkey = R::AccountId::from(hotkey.0); - let identity = pallet_subtensor::SubnetIdentityOfV2 { + let identity = pallet_subtensor::SubnetIdentityOfV3 { subnet_name: subnet_name.into(), github_repo: github_repo.into(), subnet_contact: subnet_contact.into(), subnet_url: subnet_url.into(), discord: discord.into(), description: description.into(), + logo_url: vec![], + additional: additional.into(), + }; + + let call = pallet_subtensor::Call::::register_network_with_identity { + hotkey, + identity: Some(identity), + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public( + "registerNetwork(bytes32,string,string,string,string,string,string,string,string)" + )] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn register_network_with_identity_v2( + handle: &mut impl PrecompileHandle, + hotkey: H256, + subnet_name: BoundedString>, + github_repo: BoundedString>, + subnet_contact: BoundedString>, + subnet_url: BoundedString>, + discord: BoundedString>, + description: BoundedString>, + additional: BoundedString>, + logo_url: BoundedString>, + ) -> EvmResult<()> { + let hotkey = R::AccountId::from(hotkey.0); + let identity = pallet_subtensor::SubnetIdentityOfV3 { + subnet_name: subnet_name.into(), + github_repo: github_repo.into(), + subnet_contact: subnet_contact.into(), + subnet_url: subnet_url.into(), + discord: discord.into(), + description: description.into(), + logo_url: logo_url.into(), additional: additional.into(), }; @@ -98,7 +141,9 @@ where #[precompile::public("getServingRateLimit(uint16)")] #[precompile::view] fn get_serving_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ServingRateLimit::::get(netuid)) + Ok(pallet_subtensor::ServingRateLimit::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setServingRateLimit(uint16,uint64)")] @@ -109,7 +154,7 @@ where serving_rate_limit: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_serving_rate_limit { - netuid, + netuid: netuid.into(), serving_rate_limit, }; @@ -122,7 +167,9 @@ where #[precompile::public("getMinDifficulty(uint16)")] #[precompile::view] fn get_min_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinDifficulty::::get(netuid)) + Ok(pallet_subtensor::MinDifficulty::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setMinDifficulty(uint16,uint64)")] @@ -133,7 +180,7 @@ where min_difficulty: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_min_difficulty { - netuid, + netuid: netuid.into(), min_difficulty, }; @@ -146,7 +193,9 @@ where #[precompile::public("getMaxDifficulty(uint16)")] #[precompile::view] fn get_max_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxDifficulty::::get(netuid)) + Ok(pallet_subtensor::MaxDifficulty::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setMaxDifficulty(uint16,uint64)")] @@ -157,7 +206,7 @@ where max_difficulty: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_max_difficulty { - netuid, + netuid: netuid.into(), max_difficulty, }; @@ -170,7 +219,9 @@ where #[precompile::public("getWeightsVersionKey(uint16)")] #[precompile::view] fn get_weights_version_key(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::WeightsVersionKey::::get(netuid)) + Ok(pallet_subtensor::WeightsVersionKey::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setWeightsVersionKey(uint16,uint64)")] @@ -181,7 +232,7 @@ where weights_version_key: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_weights_version_key { - netuid, + netuid: netuid.into(), weights_version_key, }; @@ -194,7 +245,9 @@ where #[precompile::public("getWeightsSetRateLimit(uint16)")] #[precompile::view] fn get_weights_set_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::WeightsSetRateLimit::::get(netuid)) + Ok(pallet_subtensor::WeightsSetRateLimit::::get( + NetUid::from(netuid), + )) } #[precompile::public("setWeightsSetRateLimit(uint16,uint64)")] @@ -211,7 +264,9 @@ where #[precompile::public("getAdjustmentAlpha(uint16)")] #[precompile::view] fn get_adjustment_alpha(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::AdjustmentAlpha::::get(netuid)) + Ok(pallet_subtensor::AdjustmentAlpha::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setAdjustmentAlpha(uint16,uint64)")] @@ -222,7 +277,7 @@ where adjustment_alpha: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_adjustment_alpha { - netuid, + netuid: netuid.into(), adjustment_alpha, }; @@ -235,7 +290,9 @@ where #[precompile::public("getMaxWeightLimit(uint16)")] #[precompile::view] fn get_max_weight_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxWeightsLimit::::get(netuid)) + Ok(pallet_subtensor::MaxWeightsLimit::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setMaxWeightLimit(uint16,uint16)")] @@ -246,7 +303,7 @@ where max_weight_limit: u16, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_max_weight_limit { - netuid, + netuid: netuid.into(), max_weight_limit, }; @@ -259,7 +316,9 @@ where #[precompile::public("getImmunityPeriod(uint16)")] #[precompile::view] fn get_immunity_period(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ImmunityPeriod::::get(netuid)) + Ok(pallet_subtensor::ImmunityPeriod::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setImmunityPeriod(uint16,uint16)")] @@ -270,7 +329,7 @@ where immunity_period: u16, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_immunity_period { - netuid, + netuid: netuid.into(), immunity_period, }; @@ -283,7 +342,9 @@ where #[precompile::public("getMinAllowedWeights(uint16)")] #[precompile::view] fn get_min_allowed_weights(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinAllowedWeights::::get(netuid)) + Ok(pallet_subtensor::MinAllowedWeights::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setMinAllowedWeights(uint16,uint16)")] @@ -294,7 +355,7 @@ where min_allowed_weights: u16, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_min_allowed_weights { - netuid, + netuid: netuid.into(), min_allowed_weights, }; @@ -307,13 +368,16 @@ where #[precompile::public("getKappa(uint16)")] #[precompile::view] fn get_kappa(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Kappa::::get(netuid)) + Ok(pallet_subtensor::Kappa::::get(NetUid::from(netuid))) } #[precompile::public("setKappa(uint16,uint16)")] #[precompile::payable] fn set_kappa(handle: &mut impl PrecompileHandle, netuid: u16, kappa: u16) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_kappa { netuid, kappa }; + let call = pallet_admin_utils::Call::::sudo_set_kappa { + netuid: netuid.into(), + kappa, + }; handle.try_dispatch_runtime_call::( call, @@ -324,19 +388,22 @@ where #[precompile::public("getRho(uint16)")] #[precompile::view] fn get_rho(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Rho::::get(netuid)) + Ok(pallet_subtensor::Rho::::get(NetUid::from(netuid))) } #[precompile::public("getAlphaSigmoidSteepness(uint16)")] #[precompile::view] fn get_alpha_sigmoid_steepness(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::AlphaSigmoidSteepness::::get(netuid)) + Ok(pallet_subtensor::AlphaSigmoidSteepness::::get(NetUid::from(netuid)) as u16) } #[precompile::public("setRho(uint16,uint16)")] #[precompile::payable] fn set_rho(handle: &mut impl PrecompileHandle, netuid: u16, rho: u16) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_rho { netuid, rho }; + let call = pallet_admin_utils::Call::::sudo_set_rho { + netuid: netuid.into(), + rho, + }; handle.try_dispatch_runtime_call::( call, @@ -351,8 +418,10 @@ where netuid: u16, steepness: u16, ) -> EvmResult<()> { - let call = - pallet_admin_utils::Call::::sudo_set_alpha_sigmoid_steepness { netuid, steepness }; + let call = pallet_admin_utils::Call::::sudo_set_alpha_sigmoid_steepness { + netuid: netuid.into(), + steepness: (steepness as i16), + }; handle.try_dispatch_runtime_call::( call, @@ -363,7 +432,9 @@ where #[precompile::public("getActivityCutoff(uint16)")] #[precompile::view] fn get_activity_cutoff(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ActivityCutoff::::get(netuid)) + Ok(pallet_subtensor::ActivityCutoff::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setActivityCutoff(uint16,uint16)")] @@ -374,7 +445,7 @@ where activity_cutoff: u16, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_activity_cutoff { - netuid, + netuid: netuid.into(), activity_cutoff, }; @@ -391,7 +462,7 @@ where netuid: u16, ) -> EvmResult { Ok(pallet_subtensor::NetworkRegistrationAllowed::::get( - netuid, + NetUid::from(netuid), )) } @@ -403,7 +474,7 @@ where registration_allowed: bool, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_network_registration_allowed { - netuid, + netuid: netuid.into(), registration_allowed, }; @@ -420,7 +491,7 @@ where netuid: u16, ) -> EvmResult { Ok(pallet_subtensor::NetworkPowRegistrationAllowed::::get( - netuid, + NetUid::from(netuid), )) } @@ -432,7 +503,7 @@ where registration_allowed: bool, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_network_pow_registration_allowed { - netuid, + netuid: netuid.into(), registration_allowed, }; @@ -445,7 +516,7 @@ where #[precompile::public("getMinBurn(uint16)")] #[precompile::view] fn get_min_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MinBurn::::get(netuid)) + Ok(pallet_subtensor::MinBurn::::get(NetUid::from(netuid))) } #[precompile::public("setMinBurn(uint16,uint64)")] @@ -462,7 +533,7 @@ where #[precompile::public("getMaxBurn(uint16)")] #[precompile::view] fn get_max_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::MaxBurn::::get(netuid)) + Ok(pallet_subtensor::MaxBurn::::get(NetUid::from(netuid))) } #[precompile::public("setMaxBurn(uint16,uint64)")] @@ -479,7 +550,7 @@ where #[precompile::public("getDifficulty(uint16)")] #[precompile::view] fn get_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Difficulty::::get(netuid)) + Ok(pallet_subtensor::Difficulty::::get(NetUid::from(netuid))) } #[precompile::public("setDifficulty(uint16,uint64)")] @@ -489,7 +560,10 @@ where netuid: u16, difficulty: u64, ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_difficulty { netuid, difficulty }; + let call = pallet_admin_utils::Call::::sudo_set_difficulty { + netuid: netuid.into(), + difficulty, + }; handle.try_dispatch_runtime_call::( call, @@ -500,7 +574,9 @@ where #[precompile::public("getBondsMovingAverage(uint16)")] #[precompile::view] fn get_bonds_moving_average(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::BondsMovingAverage::::get(netuid)) + Ok(pallet_subtensor::BondsMovingAverage::::get( + NetUid::from(netuid), + )) } #[precompile::public("setBondsMovingAverage(uint16,uint64)")] @@ -511,7 +587,7 @@ where bonds_moving_average: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_bonds_moving_average { - netuid, + netuid: netuid.into(), bonds_moving_average, }; @@ -528,7 +604,7 @@ where netuid: u16, ) -> EvmResult { Ok(pallet_subtensor::CommitRevealWeightsEnabled::::get( - netuid, + NetUid::from(netuid), )) } @@ -540,7 +616,7 @@ where enabled: bool, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_enabled { - netuid, + netuid: netuid.into(), enabled, }; @@ -553,7 +629,9 @@ where #[precompile::public("getLiquidAlphaEnabled(uint16)")] #[precompile::view] fn get_liquid_alpha_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::LiquidAlphaOn::::get(netuid)) + Ok(pallet_subtensor::LiquidAlphaOn::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setLiquidAlphaEnabled(uint16,bool)")] @@ -563,7 +641,10 @@ where netuid: u16, enabled: bool, ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { netuid, enabled }; + let call = pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { + netuid: netuid.into(), + enabled, + }; handle.try_dispatch_runtime_call::( call, @@ -574,7 +655,15 @@ where #[precompile::public("getYuma3Enabled(uint16)")] #[precompile::view] fn get_yuma3_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Yuma3On::::get(netuid)) + Ok(pallet_subtensor::Yuma3On::::get(NetUid::from(netuid))) + } + + #[precompile::public("getBondsResetEnabled(uint16)")] + #[precompile::view] + fn get_bonds_reset_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::BondsResetOn::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setYuma3Enabled(uint16,bool)")] @@ -584,7 +673,28 @@ where netuid: u16, enabled: bool, ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_yuma3_enabled { netuid, enabled }; + let call = pallet_admin_utils::Call::::sudo_set_yuma3_enabled { + netuid: netuid.into(), + enabled, + }; + + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("setBondsResetEnabled(uint16,bool)")] + #[precompile::payable] + fn set_bonds_reset_enabled( + handle: &mut impl PrecompileHandle, + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_bonds_reset_enabled { + netuid: netuid.into(), + enabled, + }; handle.try_dispatch_runtime_call::( call, @@ -595,7 +705,9 @@ where #[precompile::public("getAlphaValues(uint16)")] #[precompile::view] fn get_alpha_values(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<(u16, u16)> { - Ok(pallet_subtensor::AlphaValues::::get(netuid)) + Ok(pallet_subtensor::AlphaValues::::get(NetUid::from( + netuid, + ))) } #[precompile::public("setAlphaValues(uint16,uint16,uint16)")] @@ -607,7 +719,7 @@ where alpha_high: u16, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_alpha_values { - netuid, + netuid: netuid.into(), alpha_low, alpha_high, }; @@ -624,7 +736,9 @@ where _: &mut impl PrecompileHandle, netuid: u16, ) -> EvmResult { - Ok(pallet_subtensor::RevealPeriodEpochs::::get(netuid)) + Ok(pallet_subtensor::RevealPeriodEpochs::::get( + NetUid::from(netuid), + )) } #[precompile::public("setCommitRevealWeightsInterval(uint16,uint64)")] @@ -635,7 +749,7 @@ where interval: u64, ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_interval { - netuid, + netuid: netuid.into(), interval, }; @@ -652,7 +766,10 @@ where netuid: u16, toggle: bool, ) -> EvmResult<()> { - let call = pallet_admin_utils::Call::::sudo_set_toggle_transfer { netuid, toggle }; + let call = pallet_admin_utils::Call::::sudo_set_toggle_transfer { + netuid: netuid.into(), + toggle, + }; handle.try_dispatch_runtime_call::( call, diff --git a/precompiles/src/uid_lookup.rs b/precompiles/src/uid_lookup.rs index 61fb9d6d7f..be8c803b45 100644 --- a/precompiles/src/uid_lookup.rs +++ b/precompiles/src/uid_lookup.rs @@ -45,7 +45,7 @@ where limit: u16, ) -> EvmResult> { Ok(pallet_subtensor::Pallet::::uid_lookup( - netuid, + netuid.into(), evm_address.0, limit, )) diff --git a/primitives/safe-math/Cargo.toml b/primitives/safe-math/Cargo.toml index e41c7878b5..eb39f35807 100644 --- a/primitives/safe-math/Cargo.toml +++ b/primitives/safe-math/Cargo.toml @@ -1,12 +1,15 @@ [package] name = "safe-math" version = "0.1.0" -edition = "2024" +edition = { workspace = true } [dependencies] substrate-fixed = { workspace = true } +sp-arithmetic = { workspace = true } sp-std = { workspace = true } -num-traits = { version = "0.2.19", default-features = false, features = ["libm"] } +num-traits = { version = "0.2.19", default-features = false, features = [ + "libm", +] } [lints] workspace = true @@ -16,5 +19,6 @@ default = ["std"] std = [ "substrate-fixed/std", "sp-std/std", + "sp-arithmetic/std", "num-traits/std", ] diff --git a/primitives/safe-math/src/lib.rs b/primitives/safe-math/src/lib.rs index d17c6b5708..966dbb4de4 100644 --- a/primitives/safe-math/src/lib.rs +++ b/primitives/safe-math/src/lib.rs @@ -3,10 +3,10 @@ #![cfg_attr(test, allow(clippy::arithmetic_side_effects))] #![cfg_attr(test, allow(clippy::unwrap_used))] -use substrate_fixed::{ - traits::Fixed, - types::{I32F32, I64F64, I96F32, I110F18, U64F64, U96F32, U110F18}, -}; +use core::f64::consts::LN_2; + +use sp_arithmetic::traits::UniqueSaturatedInto; +use substrate_fixed::traits::Fixed; /// Safe division trait pub trait SafeDiv { @@ -32,91 +32,217 @@ macro_rules! impl_safe_div_for_primitive { )* }; } -impl_safe_div_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, usize); +impl_safe_div_for_primitive!(u8, u16, u32, u64, u128, i8, i16, i32, i64, usize); -/// Implementation of safe division trait for substrate fixed types -macro_rules! impl_safe_div_for_fixed { - ($($t:ty),*) => { - $( - impl SafeDiv for $t { - fn safe_div_or(self, rhs: Self, def: Self) -> Self { - self.checked_div(rhs).unwrap_or(def) - } +pub trait FixedExt: Fixed { + fn checked_pow(&self, exponent: E) -> Option + where + E: UniqueSaturatedInto, + { + let exponent = exponent.unique_saturated_into(); - fn safe_div(self, rhs: Self) -> Self { - self.checked_div(rhs).unwrap_or_default() - } + if exponent == 0 { + return Some(Self::from_num(1)); + } + + if *self == Self::from_num(0) { + if exponent < 0 { + // Cannot raise zero to a negative power (division by zero) + return None; } - )* - }; -} -impl_safe_div_for_fixed!(I96F32, I32F32, I64F64, I110F18, U110F18, U64F64, U96F32); + return Some(Self::from_num(0)); // 0^(positive number) = 0 + } -fn abs_diff(a: T, b: T) -> T { - if a < b { - b.saturating_sub(a) - } else { - a.saturating_sub(b) - } -} + let mut result = Self::from_num(1); + let mut base = *self; + let mut exp = exponent.unsigned_abs(); -/// Safe sqrt with good precision -pub fn checked_sqrt(value: T, epsilon: T) -> Option { - let zero: T = T::saturating_from_num(0); - let two: T = T::saturating_from_num(2); + // Binary exponentiation algorithm + while exp > 0 { + if exp & 1 != 0 { + result = result.saturating_mul(base); + } + base = base.saturating_mul(base); + exp >>= 1; + } + + if exponent < 0 { + result = Self::from_num(1).checked_div(result).unwrap_or_default(); + } - if value < zero { - return None; + Some(result) } - let mut high: T = value; - let mut low: T = zero; - let mut middle: T = high.saturating_add(low).safe_div(two); + /// Safe sqrt with good precision + fn checked_sqrt(&self, epsilon: Self) -> Option { + let zero = Self::saturating_from_num(0); + let one = Self::saturating_from_num(1); + let two = Self::saturating_from_num(2); - let mut iteration: i32 = 0; - let max_iterations = 128; - let mut check_val: T = value.safe_div(middle); + if *self < zero { + return None; + } - // Iterative approximation using bisection - while abs_diff(check_val, middle) > epsilon { - if check_val < middle { - high = middle; + let mut high; + let mut low; + if *self > one { + high = *self; + low = zero; } else { - low = middle; + high = one; + low = *self; + } + + let mut middle = high.saturating_add(low).safe_div(two); + + let mut iteration: i32 = 0; + let max_iterations = 128; + let mut check_val = self.safe_div(middle); + + // Iterative approximation using bisection + while check_val.abs_diff(middle) > epsilon { + if check_val < middle { + high = middle; + } else { + low = middle; + } + + middle = high.saturating_add(low).safe_div(two); + check_val = self.safe_div(middle); + + iteration = iteration.saturating_add(1); + if iteration > max_iterations { + break; + } + } + + Some(middle) + } + + /// Natural logarithm (base e) + fn checked_ln(&self) -> Option { + if *self <= Self::from_num(0) { + return None; } - middle = high.saturating_add(low).safe_div(two); - check_val = value.safe_div(middle); + // Constants + let one = Self::from_num(1); + let two = Self::from_num(2); + let ln2 = Self::from_num(LN_2); + + // Find integer part of log2(x) + let mut exp = 0i64; + let mut y = *self; - iteration = iteration.saturating_add(1); - if iteration > max_iterations { - break; + // Scale y to be between 1 and 2 + while y >= two { + y = y.checked_div(two)?; + exp = exp.checked_add(1)?; } + while y < one { + y = y.checked_mul(two)?; + exp = exp.checked_sub(1)?; + } + + // At this point, 1 <= y < 2 + let z = y.checked_sub(one)?; + + // For better accuracy, use more terms in the Taylor series + let z2 = z.checked_mul(z)?; + let z3 = z2.checked_mul(z)?; + let z4 = z3.checked_mul(z)?; + let z5 = z4.checked_mul(z)?; + let z6 = z5.checked_mul(z)?; + let z7 = z6.checked_mul(z)?; + let z8 = z7.checked_mul(z)?; + + // More terms in the Taylor series for better accuracy + // ln(1+z) = z - z²/2 + z³/3 - z⁴/4 + z⁵/5 - z⁶/6 + z⁷/7 - z⁸/8 + ... + let ln_y = z + .checked_sub(z2.checked_mul(Self::from_num(0.5))?)? + .checked_add(z3.checked_mul(Self::from_num(1.0 / 3.0))?)? + .checked_sub(z4.checked_mul(Self::from_num(0.25))?)? + .checked_add(z5.checked_mul(Self::from_num(0.2))?)? + .checked_sub(z6.checked_mul(Self::from_num(1.0 / 6.0))?)? + .checked_add(z7.checked_mul(Self::from_num(1.0 / 7.0))?)? + .checked_sub(z8.checked_mul(Self::from_num(0.125))?)?; + + // Final result: ln(x) = ln(y) + exp * ln(2) + let exp_ln2 = Self::from_num(exp).checked_mul(ln2)?; + ln_y.checked_add(exp_ln2) } - Some(middle) + /// Logarithm with arbitrary base + fn checked_log(&self, base: Self) -> Option { + // Check for invalid base + if base <= Self::from_num(0) || base == Self::from_num(1) { + return None; + } + + // Calculate using change of base formula: log_b(x) = ln(x) / ln(b) + let ln_x = self.checked_ln()?; + let ln_base = base.checked_ln()?; + + ln_x.checked_div(ln_base) + } + + /// Returns the largest integer less than or equal to the fixed-point number. + fn checked_floor(&self) -> Option { + // Approach using the integer and fractional parts + if *self >= Self::from_num(0) { + // For non-negative numbers, simply return the integer part + return Some(Self::from_num(self.int())); + } + + // For negative numbers + let int_part = self.int(); + let frac_part = self.frac(); + + if frac_part == Self::from_num(0) { + // No fractional part, return as is + return Some(*self); + } + + // Has fractional part, we need to round down + int_part.checked_sub(Self::from_num(1)) + } + + fn abs_diff(&self, b: Self) -> Self { + if *self < b { + b.saturating_sub(*self) + } else { + self.saturating_sub(b) + } + } + + fn safe_div_or(&self, rhs: Self, def: Self) -> Self { + self.checked_div(rhs).unwrap_or(def) + } + + fn safe_div(&self, rhs: Self) -> Self { + self.checked_div(rhs).unwrap_or_default() + } } +impl FixedExt for T {} + #[cfg(test)] mod tests { - use super::*; - use substrate_fixed::types::U110F18; // Assuming U110F18 is properly imported + use core::f64::consts::LN_10; + use substrate_fixed::types::*; // Assuming U110F18 is properly imported - // Helper function for absolute difference - fn abs_diff(a: U110F18, b: U110F18) -> U110F18 { - if a > b { a - b } else { b - a } - } + use super::*; #[test] fn test_checked_sqrt_positive_values() { let value: U110F18 = U110F18::from_num(4.0); let epsilon: U110F18 = U110F18::from_num(0.0001); - let result: Option = checked_sqrt(value, epsilon); + let result: Option = value.checked_sqrt(epsilon); assert!(result.is_some()); let sqrt_result: U110F18 = result.unwrap(); let precise_sqrt: U110F18 = U110F18::from_num(4.0_f64.sqrt()); - assert!(abs_diff(sqrt_result, precise_sqrt) <= epsilon); + assert!(sqrt_result.abs_diff(precise_sqrt) <= epsilon); } #[test] @@ -124,11 +250,11 @@ mod tests { let value: U110F18 = U110F18::from_num(1_000_000_000_000_000_000.0); let epsilon: U110F18 = U110F18::from_num(0.0001); - let result: Option = checked_sqrt(value, epsilon); + let result = value.checked_sqrt(epsilon); assert!(result.is_some()); let sqrt_result: U110F18 = result.unwrap(); let precise_sqrt: U110F18 = U110F18::from_num(1_000_000_000_000_000_000.0_f64.sqrt()); - assert!(abs_diff(sqrt_result, precise_sqrt) <= epsilon); + assert!(sqrt_result.abs_diff(precise_sqrt) <= epsilon); } #[test] @@ -136,12 +262,12 @@ mod tests { let value: U110F18 = U110F18::from_num(441_000_000_000_000_000_000_000_000_000_000.0); let epsilon: U110F18 = U110F18::from_num(1000); - let result: Option = checked_sqrt(value, epsilon); + let result: Option = value.checked_sqrt(epsilon); assert!(result.is_some()); let sqrt_result: U110F18 = result.unwrap(); let precise_sqrt: U110F18 = U110F18::from_num(441_000_000_000_000_000_000_000_000_000_000.0_f64.sqrt()); - assert!(abs_diff(sqrt_result, precise_sqrt) <= epsilon); + assert!(sqrt_result.abs_diff(precise_sqrt) <= epsilon); } #[test] @@ -149,9 +275,10 @@ mod tests { let value: U110F18 = U110F18::from_num(0.0); let epsilon: U110F18 = U110F18::from_num(0.0001); - let result: Option = checked_sqrt(value, epsilon); + let result: Option = value.checked_sqrt(epsilon); assert!(result.is_some()); - assert_eq!(result.unwrap(), U110F18::from_num(0.0)); + let sqrt_result: U110F18 = result.unwrap(); + assert!(sqrt_result.abs_diff(U110F18::from_num(0)) <= epsilon); } #[test] @@ -159,18 +286,99 @@ mod tests { let value: U110F18 = U110F18::from_num(2.0); let epsilon: U110F18 = U110F18::from_num(0.0001); - let result: Option = checked_sqrt(value, epsilon); + let result = value.checked_sqrt(epsilon); assert!(result.is_some()); let sqrt_result: U110F18 = result.unwrap(); let precise_sqrt: U110F18 = U110F18::from_num(2.0_f64.sqrt()); - assert!(abs_diff(sqrt_result, precise_sqrt) <= epsilon); + assert!(sqrt_result.abs_diff(precise_sqrt) <= epsilon); } #[test] fn test_checked_sqrt_max_iterations() { let value: U110F18 = U110F18::from_num(2.0); let epsilon: U110F18 = U110F18::from_num(1e-30); // Very high precision - let result: Option = checked_sqrt(value, epsilon); + let result = value.checked_sqrt(epsilon); assert!(result.is_some()); // Check that it doesn't break, but may not be highly accurate } + + #[test] + fn test_checked_pow_fixed() { + let result = U64F64::from_num(2.5).checked_pow(3u32); + assert_eq!(result, Some(U64F64::from_num(15.625))); + + let result = I32F32::from_num(1.5).checked_pow(-2i64); + + assert!( + (result.unwrap() - I32F32::from_num(0.44444444)).abs() <= I32F32::from_num(0.00001) + ); + + let result = I32F32::from_num(0).checked_pow(-1); + assert!(result.is_none()); + } + + #[test] + fn test_checked_ln() { + // Natural logarithm + assert!( + I64F64::from_num(10.0) + .checked_ln() + .unwrap() + .abs_diff(I64F64::from_num(LN_10)) + < I64F64::from_num(0.00001) + ); + + // Log of negative number should return None + assert!(I64F64::from_num(-5.0).checked_ln().is_none()); + + // Log of zero should return None + assert!(I64F64::from_num(0.0).checked_ln().is_none()); + } + + #[test] + fn test_checked_log() { + let x = I64F64::from_num(10.0); + + // Log base 10 + assert!( + x.checked_log(I64F64::from_num(10.0)) + .unwrap() + .abs_diff(I64F64::from_num(1.0)) + < I64F64::from_num(0.00001) + ); + + // Log with invalid base should return None + assert!(x.checked_log(I64F64::from_num(-2.0)).is_none()); + + // Log with base 1 should return None + assert!(x.checked_log(I64F64::from_num(1.0)).is_none()); + } + + #[test] + fn test_checked_floor() { + // Test cases: (input, expected floor result) + let test_cases = [ + // Positive and negative integers (should remain unchanged) + (0.0, 0.0), + (1.0, 1.0), + (5.0, 5.0), + (-1.0, -1.0), + (-5.0, -5.0), + // Positive fractions (should truncate to integer part) + (0.5, 0.0), + (1.5, 1.0), + (3.75, 3.0), + (9.999, 9.0), + // Negative fractions (should round down to next integer) + (-0.1, -1.0), + (-1.5, -2.0), + (-3.75, -4.0), + (-9.999, -10.0), + ]; + + for &(input, expected) in &test_cases { + let x = I64F64::from_num(input); + let expected = I64F64::from_num(expected); + assert_eq!(x.checked_floor().unwrap(), expected,); + } + } } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index f417a18afc..2fa522b6bc 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -32,6 +32,10 @@ serde_json = { workspace = true, features = ["alloc"] } pallet-aura = { workspace = true } pallet-balances = { workspace = true } pallet-subtensor = { workspace = true } +pallet-subtensor-swap = { workspace = true } +pallet-subtensor-swap-runtime-api = { workspace = true } +substrate-fixed = { workspace = true } +subtensor-swap-interface = { workspace = true } frame-support = { workspace = true } pallet-grandpa = { workspace = true } pallet-insecure-randomness-collective-flip = { workspace = true } @@ -153,6 +157,10 @@ std = [ "frame-system/std", "frame-try-runtime/std", "pallet-subtensor/std", + "pallet-subtensor-swap/std", + "pallet-subtensor-swap-runtime-api/std", + "substrate-fixed/std", + "subtensor-swap-interface/std", "pallet-aura/std", "pallet-balances/std", "pallet-grandpa/std", @@ -226,10 +234,12 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "pallet-safe-mode/runtime-benchmarks", "pallet-subtensor/runtime-benchmarks", + "pallet-subtensor-swap/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-membership/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", diff --git a/runtime/src/check_nonce.rs b/runtime/src/check_nonce.rs index 94c06c6480..2e05c63867 100644 --- a/runtime/src/check_nonce.rs +++ b/runtime/src/check_nonce.rs @@ -1,12 +1,21 @@ +// Customized from the original implementation in the Polkadot SDK. +// https://github.com/paritytech/polkadot-sdk/blob/b600af050d6b6c8da59ae2a2a793ee2d8827ab1e/substrate/frame/system/src/extensions/check_nonce.rs + use codec::{Decode, Encode}; -use frame_support::dispatch::{DispatchInfo, Pays}; +use frame_support::{ + RuntimeDebugNoBound, + dispatch::{DispatchInfo, Pays}, +}; use frame_system::Config; use scale_info::TypeInfo; use sp_runtime::{ - Saturating, - traits::{DispatchInfoOf, Dispatchable, One, SignedExtension, Zero}, + DispatchResult, Saturating, Weight, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, One, PostDispatchInfoOf, + TransactionExtension, ValidateResult, Zero, + }, transaction_validity::{ - InvalidTransaction, TransactionLongevity, TransactionValidity, TransactionValidityError, + InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidityError, ValidTransaction, }, }; @@ -18,9 +27,14 @@ use subtensor_macros::freeze_struct; /// # Transaction Validity /// /// This extension affects `requires` and `provides` tags of validity, but DOES NOT -/// set the `priority` field. Make sure that AT LEAST one of the signed extension sets +/// set the `priority` field. Make sure that AT LEAST one of the transaction extension sets /// some kind of priority upon validating transactions. -#[freeze_struct("610b76f62cdb521e")] +/// +/// The preparation step assumes that the nonce information has not changed since the validation +/// step. This means that other extensions ahead of `CheckNonce` in the pipeline must not alter the +/// nonce during their own preparation step, or else the transaction may be rejected during dispatch +/// or lead to an inconsistent account state.. +#[freeze_struct("feac7c9db94d39ac")] #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckNonce(#[codec(compact)] pub T::Nonce); @@ -44,87 +58,119 @@ impl sp_std::fmt::Debug for CheckNonce { } } -impl SignedExtension for CheckNonce +/// Operation to perform from `validate` to `prepare` in [`CheckNonce`] transaction extension. +#[derive(RuntimeDebugNoBound)] +pub enum Val { + /// Account and its nonce to check for. + CheckNonce((T::AccountId, T::Nonce)), + /// Weight to refund. + Refund(Weight), +} + +/// Operation to perform from `prepare` to `post_dispatch_details` in [`CheckNonce`] transaction +/// extension. +#[derive(RuntimeDebugNoBound)] +pub enum Pre { + /// The transaction extension weight should not be refunded. + NonceChecked, + /// The transaction extension weight should be refunded. + Refund(Weight), +} + +impl TransactionExtension for CheckNonce where T::RuntimeCall: Dispatchable, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, { - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); - type Pre = (); const IDENTIFIER: &'static str = "CheckNonce"; + type Implicit = (); + type Val = Val; + type Pre = Pre; - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - _call: &Self::Call, - info: &DispatchInfoOf, - _len: usize, - ) -> Result<(), TransactionValidityError> { - let mut account = frame_system::Account::::get(who); - match info.pays_fee { - Pays::Yes => { - if account.providers.is_zero() && account.sufficients.is_zero() { - // Nonce storage not paid for - return Err(InvalidTransaction::Payment.into()); - } - } - // not check providers and sufficients for Pays::No extrinsic - Pays::No => {} - } - - if self.0 != account.nonce { - return Err(if self.0 < account.nonce { - InvalidTransaction::Stale - } else { - InvalidTransaction::Future - } - .into()); - } - account.nonce.saturating_inc(); - frame_system::Account::::insert(who, account); - Ok(()) + fn weight(&self, _: &T::RuntimeCall) -> Weight { + // TODO: benchmark transaction extension + Weight::zero() } fn validate( &self, - who: &Self::AccountId, - _call: &Self::Call, - info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + call: &T::RuntimeCall, + info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + _source: TransactionSource, + ) -> ValidateResult { + let Some(who) = origin.as_system_origin_signer() else { + return Ok((Default::default(), Val::Refund(self.weight(call)), origin)); + }; let account = frame_system::Account::::get(who); - match info.pays_fee { - Pays::Yes => { - if account.providers.is_zero() && account.sufficients.is_zero() { - // Nonce storage not paid for - return Err(InvalidTransaction::Payment.into()); - } - } - // not check providers and sufficients for Pays::No extrinsic - Pays::No => {} + if info.pays_fee == Pays::Yes + && account.providers.is_zero() + && account.sufficients.is_zero() + { + // Nonce storage not paid for + return Err(InvalidTransaction::Payment.into()); } if self.0 < account.nonce { - return InvalidTransaction::Stale.into(); + return Err(InvalidTransaction::Stale.into()); } - let provides = vec![Encode::encode(&(who, self.0))]; + let provides = vec![Encode::encode(&(&who, self.0))]; let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who, self.0.saturating_sub(One::one())))] + vec![Encode::encode(&(&who, self.0.saturating_sub(One::one())))] } else { vec![] }; - Ok(ValidTransaction { + let validity = ValidTransaction { priority: 0, requires, provides, longevity: TransactionLongevity::MAX, propagate: true, - }) + }; + + Ok(( + validity, + Val::CheckNonce((who.clone(), account.nonce)), + origin, + )) + } + + fn prepare( + self, + val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + let (who, mut nonce) = match val { + Val::CheckNonce((who, nonce)) => (who, nonce), + Val::Refund(weight) => return Ok(Pre::Refund(weight)), + }; + + // `self.0 < nonce` already checked in `validate`. + if self.0 > nonce { + return Err(InvalidTransaction::Future.into()); + } + nonce += T::Nonce::one(); + frame_system::Account::::mutate(who, |account| account.nonce = nonce); + Ok(Pre::NonceChecked) + } + + fn post_dispatch_details( + pre: Self::Pre, + _info: &DispatchInfo, + _post_info: &PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + ) -> Result { + match pre { + Pre::NonceChecked => Ok(Weight::zero()), + Pre::Refund(weight) => Ok(weight), + } } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 0b64ee3cde..8adf4b6c55 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -8,9 +8,13 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use core::num::NonZeroU64; + pub mod check_nonce; mod migrations; +extern crate alloc; + use codec::{Compact, Decode, Encode}; use frame_support::traits::{Imbalance, InsideBoth}; use frame_support::{ @@ -38,7 +42,7 @@ use pallet_subtensor::rpc_info::{ neuron_info::{NeuronInfo, NeuronInfoLite}, show_subnet::SubnetState, stake_info::StakeInfo, - subnet_info::{SubnetHyperparams, SubnetInfo, SubnetInfov2}, + subnet_info::{SubnetHyperparams, SubnetHyperparamsV2, SubnetInfo, SubnetInfov2}, }; use smallvec::smallvec; use sp_api::impl_runtime_apis; @@ -47,10 +51,10 @@ use sp_core::{ H160, H256, OpaqueMetadata, U256, crypto::{ByteArray, KeyTypeId}, }; +use sp_runtime::Cow; use sp_runtime::generic::Era; use sp_runtime::{ - AccountId32, ApplyExtrinsicResult, ConsensusEngineId, create_runtime_str, generic, - impl_opaque_keys, + AccountId32, ApplyExtrinsicResult, ConsensusEngineId, generic, impl_opaque_keys, traits::{ AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, One, PostDispatchInfoOf, UniqueSaturatedInto, Verify, @@ -113,47 +117,51 @@ impl frame_system::offchain::SigningTypes for Runtime { type Signature = Signature; } -impl frame_system::offchain::SendTransactionTypes for Runtime +impl frame_system::offchain::CreateTransactionBase for Runtime where RuntimeCall: From, { type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateInherent> for Runtime { + fn create_inherent(call: Self::RuntimeCall) -> Self::Extrinsic { + UncheckedExtrinsic::new_bare(call) + } } impl frame_system::offchain::CreateSignedTransaction> for Runtime { - fn create_transaction>( + fn create_signed_transaction< + S: frame_system::offchain::AppCrypto, + >( call: RuntimeCall, - public: ::Signer, - account: AccountId, - index: Index, - ) -> Option<( - RuntimeCall, - ::SignaturePayload, - )> { + public: Self::Public, + account: Self::AccountId, + nonce: Self::Nonce, + ) -> Option { use sp_runtime::traits::StaticLookup; let address = ::Lookup::unlookup(account.clone()); - let extra: SignedExtra = ( + let extra: TransactionExtensions = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(Era::Immortal), - check_nonce::CheckNonce::::from(index), + check_nonce::CheckNonce::::from(nonce).into(), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - pallet_subtensor::SubtensorSignedExtension::::new(), - pallet_commitments::CommitmentsSignedExtension::::new(), + pallet_subtensor::SubtensorTransactionExtension::::new(), frame_metadata_hash_extension::CheckMetadataHash::::new(true), ); let raw_payload = SignedPayload::new(call.clone(), extra.clone()).ok()?; let signature = raw_payload.using_encoded(|payload| S::sign(payload, public))?; - let signature_payload = (address, signature, extra); - - Some((call, signature_payload)) + Some(UncheckedExtrinsic::new_signed( + call, address, signature, extra, + )) } } @@ -201,19 +209,19 @@ pub mod opaque { // https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node-subtensor"), - impl_name: create_runtime_str!("node-subtensor"), + spec_name: Cow::Borrowed("node-subtensor"), + impl_name: Cow::Borrowed("node-subtensor"), authoring_version: 1, // The version of the runtime specification. A full node will not attempt to use its native // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 273, + spec_version: 279, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, - state_version: 1, + system_version: 1, }; pub const MAXIMUM_BLOCK_WEIGHT: Weight = @@ -321,6 +329,7 @@ impl frame_system::Config for Runtime { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } impl pallet_insecure_randomness_collective_flip::Config for Runtime {} @@ -432,6 +441,7 @@ impl pallet_balances::Config for Runtime { type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<50>; + type DoneSlashHandler = (); } pub struct LinearWeightToFee; @@ -489,6 +499,7 @@ impl pallet_transaction_payment::Config for Runtime { type OperationalFeeMultiplier = OperationalFeeMultiplier; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = ConstFeeMultiplier; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } // Configure collective pallet for council @@ -829,6 +840,10 @@ impl InstanceFilter for ProxyType { } _ => false, }, + ProxyType::SwapHotkey => matches!( + c, + RuntimeCall::SubtensorModule(pallet_subtensor::Call::swap_hotkey { .. }) + ), } } fn is_superset(&self, o: &Self) -> bool { @@ -943,7 +958,7 @@ impl CanRegisterIdentity for AllowIdentityReg { fn can_register(address: &AccountId, identified: &AccountId) -> bool { if address != identified { SubtensorModule::coldkey_owns_hotkey(address, identified) - && SubtensorModule::is_hotkey_registered_on_network(0, identified) + && SubtensorModule::is_hotkey_registered_on_network(NetUid::ROOT, identified) } else { SubtensorModule::is_subnet_owner(address) } @@ -993,12 +1008,12 @@ impl Get for MaxCommitFields { pub struct AllowCommitments; impl CanCommit for AllowCommitments { #[cfg(not(feature = "runtime-benchmarks"))] - fn can_commit(netuid: u16, address: &AccountId) -> bool { + fn can_commit(netuid: NetUid, address: &AccountId) -> bool { SubtensorModule::is_hotkey_registered_on_network(netuid, address) } #[cfg(feature = "runtime-benchmarks")] - fn can_commit(_: u16, _: &AccountId) -> bool { + fn can_commit(_: NetUid, _: &AccountId) -> bool { true } } @@ -1006,12 +1021,12 @@ impl CanCommit for AllowCommitments { pub struct ResetBondsOnCommit; impl OnMetadataCommitment for ResetBondsOnCommit { #[cfg(not(feature = "runtime-benchmarks"))] - fn on_metadata_commitment(netuid: u16, address: &AccountId) { + fn on_metadata_commitment(netuid: NetUid, address: &AccountId) { let _ = SubtensorModule::do_reset_bonds(netuid, address); } #[cfg(feature = "runtime-benchmarks")] - fn on_metadata_commitment(_: u16, _: &AccountId) {} + fn on_metadata_commitment(_: NetUid, _: &AccountId) {} } impl pallet_commitments::Config for Runtime { @@ -1030,13 +1045,13 @@ impl pallet_commitments::Config for Runtime { pub struct TempoInterface; impl pallet_commitments::GetTempoInterface for TempoInterface { - fn get_epoch_index(netuid: u16, cur_block: u64) -> u64 { + fn get_epoch_index(netuid: NetUid, cur_block: u64) -> u64 { SubtensorModule::get_epoch_index(netuid, cur_block) } } impl pallet_commitments::GetTempoInterface for Runtime { - fn get_epoch_index(netuid: u16, cur_block: u64) -> u64 { + fn get_epoch_index(netuid: NetUid, cur_block: u64) -> u64 { SubtensorModule::get_epoch_index(netuid, cur_block) } } @@ -1056,7 +1071,7 @@ pub const INITIAL_CHILDKEY_TAKE_RATELIMIT: u64 = 5; // Configure the pallet subtensor. parameter_types! { pub const SubtensorInitialRho: u16 = 10; - pub const SubtensorInitialAlphaSigmoidSteepness: u16 = 1000; + pub const SubtensorInitialAlphaSigmoidSteepness: i16 = 1000; pub const SubtensorInitialKappa: u16 = 32_767; // 0.5 = 65535/2 pub const SubtensorInitialMaxAllowedUids: u16 = 4096; pub const SubtensorInitialIssuance: u64 = 0; @@ -1087,7 +1102,7 @@ parameter_types! { pub const SubtensorInitialMinDifficulty: u64 = 10_000_000; pub const SubtensorInitialMaxDifficulty: u64 = u64::MAX / 4; pub const SubtensorInitialServingRateLimit: u64 = 50; - pub const SubtensorInitialBurn: u64 = 1_000_000_000; // 1 tao + pub const SubtensorInitialBurn: u64 = 100_000_000; // 0.1 tao pub const SubtensorInitialMinBurn: u64 = 500_000; // 500k RAO pub const SubtensorInitialMaxBurn: u64 = 100_000_000_000; // 100 tao pub const SubtensorInitialTxRateLimit: u64 = 1000; @@ -1118,6 +1133,8 @@ parameter_types! { } else { 7 * 24 * 60 * 60 / 12 // 7 days }; + pub const SubtensorInitialKeySwapOnSubnetCost: u64 = 1_000_000; // 0.001 TAO + pub const HotkeySwapOnSubnetInterval : BlockNumber = 5 * 24 * 60 * 60 / 12; // 5 days } impl pallet_subtensor::Config for Runtime { @@ -1187,6 +1204,31 @@ impl pallet_subtensor::Config for Runtime { type InitialDissolveNetworkScheduleDuration = InitialDissolveNetworkScheduleDuration; type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod; type DurationOfStartCall = DurationOfStartCall; + type SwapInterface = Swap; + type KeySwapOnSubnetCost = SubtensorInitialKeySwapOnSubnetCost; + type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval; +} + +parameter_types! { + pub const SwapProtocolId: PalletId = PalletId(*b"ten/swap"); + pub const SwapMaxFeeRate: u16 = 10000; // 15.26% + pub const SwapMaxPositions: u32 = 100; + pub const SwapMinimumLiquidity: u64 = 1_000; + pub const SwapMinimumReserve: NonZeroU64 = NonZeroU64::new(1_000_000) + .expect("1_000_000 fits NonZeroU64"); +} + +impl pallet_subtensor_swap::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SubnetInfo = SubtensorModule; + type BalanceOps = SubtensorModule; + type ProtocolId = SwapProtocolId; + type MaxFeeRate = SwapMaxFeeRate; + type MaxPositions = SwapMaxPositions; + type MinimumLiquidity = SwapMinimumLiquidity; + type MinimumReserve = SwapMinimumReserve; + // TODO: set measured weights when the pallet been benchmarked and the type is generated + type WeightInfo = pallet_subtensor_swap::weights::DefaultWeight; } use sp_runtime::BoundedVec; @@ -1266,7 +1308,6 @@ parameter_types! { pub const GasLimitPovSizeRatio: u64 = 0; pub PrecompilesValue: Precompiles = Precompiles::<_>::new(); pub WeightPerGas: Weight = weight_per_gas(); - pub SuicideQuickClearLimit: u32 = 0; } /// The difference between EVM decimals and Substrate decimals. @@ -1347,16 +1388,24 @@ impl pallet_evm::Config for Runtime { type OnCreate = (); type FindAuthor = FindAuthorTruncated; type GasLimitPovSizeRatio = GasLimitPovSizeRatio; - type SuicideQuickClearLimit = SuicideQuickClearLimit; type Timestamp = Timestamp; type WeightInfo = pallet_evm::weights::SubstrateWeight; type BalanceConverter = SubtensorEvmBalanceConverter; + type AccountProvider = pallet_evm::FrameSystemAccountProvider; + type GasLimitStorageGrowthRatio = (); } parameter_types! { pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; } +// Required for the IntermediateStateRoot +impl sp_core::Get for Runtime { + fn get() -> sp_version::RuntimeVersion { + VERSION + } +} + impl pallet_ethereum::Config for Runtime { type RuntimeEvent = RuntimeEvent; type StateRoot = pallet_ethereum::IntermediateStateRoot; @@ -1405,7 +1454,7 @@ impl fp_rpc::ConvertTransaction<::Extrinsic> for Transac &self, transaction: pallet_ethereum::Transaction, ) -> ::Extrinsic { - let extrinsic = UncheckedExtrinsic::new_unsigned( + let extrinsic = UncheckedExtrinsic::new_bare( pallet_ethereum::Call::::transact { transaction }.into(), ); let encoded = extrinsic.encode(); @@ -1540,8 +1589,8 @@ construct_runtime!( BaseFee: pallet_base_fee = 25, Drand: pallet_drand = 26, - Crowdloan: pallet_crowdloan = 27, + Swap: pallet_subtensor_swap = 28, } ); @@ -1551,8 +1600,8 @@ pub type Address = sp_runtime::MultiAddress; pub type Header = generic::Header; // Block type as expected by this runtime. pub type Block = generic::Block; -// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +// The extensions to the basic transaction logic. +pub type TransactionExtensions = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1561,8 +1610,7 @@ pub type SignedExtra = ( check_nonce::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, - pallet_subtensor::SubtensorSignedExtension, - pallet_commitments::CommitmentsSignedExtension, + pallet_subtensor::SubtensorTransactionExtension, frame_metadata_hash_extension::CheckMetadataHash, ); @@ -1576,14 +1624,14 @@ type Migrations = ( // Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - fp_self_contained::UncheckedExtrinsic; + fp_self_contained::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = - fp_self_contained::CheckedExtrinsic; + fp_self_contained::CheckedExtrinsic; // The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; // Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1875,9 +1923,8 @@ impl_runtime_apis! { } fn storage_at(address: H160, index: U256) -> H256 { - let mut tmp = [0u8; 32]; - index.to_big_endian(&mut tmp); - pallet_evm::AccountStorages::::get(address, H256::from_slice(&tmp[..])) + let index_hash = H256::from_slice(&index.to_big_endian()); + pallet_evm::AccountStorages::::get(address, index_hash) } fn call( @@ -2103,7 +2150,7 @@ impl_runtime_apis! { impl fp_rpc::ConvertTransactionRuntimeApi for Runtime { fn convert_transaction(transaction: EthereumTransaction) -> ::Extrinsic { - UncheckedExtrinsic::new_unsigned( + UncheckedExtrinsic::new_bare( pallet_ethereum::Call::::transact { transaction }.into(), ) } @@ -2130,7 +2177,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { + ) -> Result, alloc::string::String> { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; use sp_storage::TrackedStorageKey; @@ -2186,31 +2233,31 @@ impl_runtime_apis! { SubtensorModule::get_delegate(delegate_account) } - fn get_delegated(delegatee_account: AccountId32) -> Vec<(DelegateInfo, (Compact, Compact))> { + fn get_delegated(delegatee_account: AccountId32) -> Vec<(DelegateInfo, (Compact, Compact))> { SubtensorModule::get_delegated(delegatee_account) } } impl subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi for Runtime { - fn get_neurons_lite(netuid: u16) -> Vec> { + fn get_neurons_lite(netuid: NetUid) -> Vec> { SubtensorModule::get_neurons_lite(netuid) } - fn get_neuron_lite(netuid: u16, uid: u16) -> Option> { + fn get_neuron_lite(netuid: NetUid, uid: u16) -> Option> { SubtensorModule::get_neuron_lite(netuid, uid) } - fn get_neurons(netuid: u16) -> Vec> { + fn get_neurons(netuid: NetUid) -> Vec> { SubtensorModule::get_neurons(netuid) } - fn get_neuron(netuid: u16, uid: u16) -> Option> { + fn get_neuron(netuid: NetUid, uid: u16) -> Option> { SubtensorModule::get_neuron(netuid, uid) } } impl subtensor_custom_rpc_runtime_api::SubnetInfoRuntimeApi for Runtime { - fn get_subnet_info(netuid: u16) -> Option> { + fn get_subnet_info(netuid: NetUid) -> Option> { SubtensorModule::get_subnet_info(netuid) } @@ -2218,7 +2265,7 @@ impl_runtime_apis! { SubtensorModule::get_subnets_info() } - fn get_subnet_info_v2(netuid: u16) -> Option> { + fn get_subnet_info_v2(netuid: NetUid) -> Option> { SubtensorModule::get_subnet_info_v2(netuid) } @@ -2226,19 +2273,23 @@ impl_runtime_apis! { SubtensorModule::get_subnets_info_v2() } - fn get_subnet_hyperparams(netuid: u16) -> Option { + fn get_subnet_hyperparams(netuid: NetUid) -> Option { SubtensorModule::get_subnet_hyperparams(netuid) } - fn get_dynamic_info(netuid: u16) -> Option> { + fn get_subnet_hyperparams_v2(netuid: NetUid) -> Option { + SubtensorModule::get_subnet_hyperparams_v2(netuid) + } + + fn get_dynamic_info(netuid: NetUid) -> Option> { SubtensorModule::get_dynamic_info(netuid) } - fn get_metagraph(netuid: u16) -> Option> { + fn get_metagraph(netuid: NetUid) -> Option> { SubtensorModule::get_metagraph(netuid) } - fn get_subnet_state(netuid: u16) -> Option> { + fn get_subnet_state(netuid: NetUid) -> Option> { SubtensorModule::get_subnet_state(netuid) } @@ -2250,7 +2301,7 @@ impl_runtime_apis! { SubtensorModule::get_all_dynamic_info() } - fn get_selective_metagraph(netuid: u16, metagraph_indexes: Vec) -> Option> { + fn get_selective_metagraph(netuid: NetUid, metagraph_indexes: Vec) -> Option> { SubtensorModule::get_selective_metagraph(netuid, metagraph_indexes) } @@ -2265,11 +2316,11 @@ impl_runtime_apis! { SubtensorModule::get_stake_info_for_coldkeys( coldkey_accounts ) } - fn get_stake_info_for_hotkey_coldkey_netuid( hotkey_account: AccountId32, coldkey_account: AccountId32, netuid: u16 ) -> Option> { + fn get_stake_info_for_hotkey_coldkey_netuid( hotkey_account: AccountId32, coldkey_account: AccountId32, netuid: NetUid ) -> Option> { SubtensorModule::get_stake_info_for_hotkey_coldkey_netuid( hotkey_account, coldkey_account, netuid ) } - fn get_stake_fee( origin: Option<(AccountId32, u16)>, origin_coldkey_account: AccountId32, destination: Option<(AccountId32, u16)>, destination_coldkey_account: AccountId32, amount: u64 ) -> u64 { + fn get_stake_fee( origin: Option<(AccountId32, NetUid)>, origin_coldkey_account: AccountId32, destination: Option<(AccountId32, NetUid)>, destination_coldkey_account: AccountId32, amount: u64 ) -> u64 { SubtensorModule::get_stake_fee( origin, origin_coldkey_account, destination, destination_coldkey_account, amount ) } } @@ -2279,6 +2330,17 @@ impl_runtime_apis! { SubtensorModule::get_network_lock_cost() } } + + + impl pallet_subtensor_swap_runtime_api::SwapRuntimeApi for Runtime { + fn current_alpha_price(netuid: u16) -> u64 { + use substrate_fixed::types::U96F32; + + pallet_subtensor_swap::Pallet::::current_price(netuid.into()) + .saturating_mul(U96F32::from_num(1_000_000_000)) + .saturating_to_num() + } + } } #[test] diff --git a/runtime/tests/pallet_proxy.rs b/runtime/tests/pallet_proxy.rs index 1fcb36dec5..088da291e2 100644 --- a/runtime/tests/pallet_proxy.rs +++ b/runtime/tests/pallet_proxy.rs @@ -6,7 +6,7 @@ use node_subtensor_runtime::{ BalancesCall, BuildStorage, Proxy, Runtime, RuntimeCall, RuntimeEvent, RuntimeGenesisConfig, RuntimeOrigin, SubtensorModule, System, SystemCall, }; -use subtensor_runtime_common::{AccountId, ProxyType}; +use subtensor_runtime_common::{AccountId, NetUid, ProxyType}; const ACCOUNT: [u8; 32] = [1_u8; 32]; const DELEGATE: [u8; 32] = [2_u8; 32]; @@ -60,7 +60,7 @@ fn call_remark() -> RuntimeCall { // owner call fn call_owner_util() -> RuntimeCall { - let netuid = 1; + let netuid = NetUid::from(1); let serving_rate_limit = 2; RuntimeCall::AdminUtils(pallet_admin_utils::Call::sudo_set_serving_rate_limit { netuid, @@ -70,7 +70,7 @@ fn call_owner_util() -> RuntimeCall { // sn owner hotkey call fn call_sn_owner_hotkey() -> RuntimeCall { - let netuid = 1; + let netuid = NetUid::from(1); RuntimeCall::AdminUtils(pallet_admin_utils::Call::sudo_set_sn_owner_hotkey { netuid, hotkey: AccountId::from(ACCOUNT).into(), @@ -112,7 +112,7 @@ fn call_senate() -> RuntimeCall { // staking call fn call_add_stake() -> RuntimeCall { - let netuid = 1; + let netuid = NetUid::from(1); let amount_staked = 100; RuntimeCall::SubtensorModule(pallet_subtensor::Call::add_stake { hotkey: AccountId::from(DELEGATE), @@ -124,7 +124,7 @@ fn call_add_stake() -> RuntimeCall { // register call, account as hotkey, delegate as coldkey fn call_register() -> RuntimeCall { let block_number: u64 = 1; - let netuid: u16 = 2; + let netuid = NetUid::from(2); // lower diff first SubtensorModule::set_difficulty(netuid, 100); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c741364b2a..8b497b3762 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.86" +channel = "1.87" components = [ "cargo", "clippy", diff --git a/scripts/benchmark_action.sh b/scripts/benchmark_action.sh index 34043957de..e3259c69d0 100755 --- a/scripts/benchmark_action.sh +++ b/scripts/benchmark_action.sh @@ -10,6 +10,7 @@ declare -A DISPATCH_PATHS=( [admin_utils]="../pallets/admin-utils/src/lib.rs" [commitments]="../pallets/commitments/src/lib.rs" [drand]="../pallets/drand/src/lib.rs" + [swap]="../pallets/swap/src/pallet/mod.rs" ) # Max allowed drift (%)