diff --git a/.github/workflows/check-bittensor-e2e-tests.yml.yml b/.github/workflows/check-bittensor-e2e-tests.yml.yml index 6be275e3ee..1f0878a548 100644 --- a/.github/workflows/check-bittensor-e2e-tests.yml.yml +++ b/.github/workflows/check-bittensor-e2e-tests.yml.yml @@ -10,12 +10,7 @@ concurrency: on: pull_request: - branches: - - devnet - - devnet-ready - - testnet - - testnet-ready - - main + branches: ["*"] types: [opened, synchronize, reopened, labeled, unlabeled] workflow_dispatch: @@ -30,35 +25,10 @@ env: VERBOSE: ${{ github.event.inputs.verbose }} jobs: - apply-label-to-new-pr: - runs-on: ubuntu-latest - 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 @@ -68,17 +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_OUTPUT + 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_OUTPUT + 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 }} @@ -103,7 +73,7 @@ jobs: 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 }} @@ -164,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 @@ -261,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 diff --git a/Cargo.lock b/Cargo.lock index d71ab4dff7..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 = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +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 = "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 = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" +checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af" dependencies = [ - "http 1.1.0", + "beef", + "http 1.3.1", "serde", "serde_json", - "thiserror", + "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 = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loom" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +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" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "300.4.0+3.4.0" -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,18 +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", @@ -6044,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", @@ -6057,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", @@ -6073,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", @@ -6097,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", ] @@ -6105,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", @@ -6116,13 +7354,13 @@ 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", @@ -6144,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", ] @@ -6156,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", @@ -6169,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", @@ -6184,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", @@ -6201,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", @@ -6229,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", @@ -6240,7 +7480,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-dispatch" 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", "frame-support", @@ -6252,7 +7492,7 @@ dependencies = [ [[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", @@ -6261,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", @@ -6270,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", @@ -6279,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", @@ -6302,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", @@ -6316,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", @@ -6329,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", @@ -6345,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", @@ -6393,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]] @@ -6418,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", @@ -6438,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", @@ -6456,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", @@ -6473,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", @@ -6498,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", @@ -6514,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", @@ -6527,25 +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", @@ -6559,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", @@ -6572,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", @@ -6593,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", @@ -6609,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", @@ -6640,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", @@ -6660,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", ] @@ -6680,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]] @@ -6721,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", ] @@ -6768,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]] @@ -6792,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", ] @@ -6816,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", ] @@ -6859,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", @@ -6880,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]] @@ -6908,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" @@ -6944,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" @@ -6956,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" @@ -6969,7 +8496,7 @@ dependencies = [ "libc", "log", "polkavm-assembler", - "polkavm-common", + "polkavm-common 0.9.0", "polkavm-linux-raw", ] @@ -6991,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]] @@ -7006,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]] @@ -7018,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]] @@ -7032,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", ] @@ -7045,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", ] @@ -7083,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" @@ -7095,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", ] @@ -7105,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", @@ -7129,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]] @@ -7156,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", @@ -7166,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", @@ -7182,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]] @@ -7220,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", ] @@ -7265,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", ] @@ -7299,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]] @@ -7317,8 +8911,8 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.3", - "thiserror", + "parking_lot 0.12.4", + "thiserror 1.0.69", ] [[package]] @@ -7329,7 +8923,7 @@ checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "prometheus-client-derive-encode", ] @@ -7341,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]] @@ -7365,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", ] @@ -7499,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" @@ -7530,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" @@ -7564,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" @@ -7595,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" @@ -7622,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]] @@ -7633,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]] @@ -7642,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]] @@ -7652,7 +9220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -7661,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]] @@ -7711,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" @@ -7722,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]] @@ -7735,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]] @@ -7787,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", ] @@ -7808,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", @@ -7831,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" @@ -7866,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", @@ -7892,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", @@ -7900,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]] @@ -7927,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" @@ -7975,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" @@ -7994,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]] @@ -8028,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.20.9" +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-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 = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +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 = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +dependencies = [ + "byteorder", + "derive_more 0.99.20", + "twox-hash", +] [[package]] name = "rw-stream-sink" @@ -8112,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", ] @@ -8136,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", ] @@ -8154,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", @@ -8187,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", @@ -8202,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", @@ -8219,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", @@ -8230,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", @@ -8254,7 +10075,7 @@ dependencies = [ "names", "parity-bip39", "parity-scale-codec", - "rand", + "rand 0.8.5", "regex", "rpassword", "sc-client-api", @@ -8265,6 +10086,7 @@ dependencies = [ "sc-service", "sc-telemetry", "sc-tracing", + "sc-transaction-pool", "sc-utils", "serde", "serde_json", @@ -8275,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", @@ -8297,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", @@ -8319,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", @@ -8334,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", @@ -8353,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", @@ -8382,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", @@ -8398,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", @@ -8413,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", @@ -8436,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", @@ -8449,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", @@ -8471,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", @@ -8495,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", @@ -8530,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", @@ -8558,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", @@ -8581,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", @@ -8605,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", @@ -8640,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", @@ -8667,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", @@ -8678,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", @@ -8704,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", @@ -8723,7 +10545,7 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-prometheus-endpoint", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "unsigned-varint 0.7.2", @@ -8734,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", @@ -8752,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", @@ -8771,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", @@ -8822,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", @@ -8848,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", @@ -8889,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", @@ -8900,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", @@ -8908,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", @@ -8940,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", @@ -8955,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", @@ -8984,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", @@ -9009,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", @@ -9059,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", @@ -9072,7 +10896,7 @@ dependencies = [ "static_init", "substrate-prometheus-endpoint", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", @@ -9080,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", @@ -9153,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", @@ -9189,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", @@ -9210,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", ] @@ -9235,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]] @@ -9244,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", @@ -9267,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]] @@ -9282,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", ] @@ -9311,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" @@ -9330,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" @@ -9340,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" @@ -9374,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]] @@ -9403,12 +11320,26 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +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 = "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", @@ -9416,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", @@ -9430,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]] @@ -9439,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", ] @@ -9457,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" @@ -9465,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", ] @@ -9483,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", ] @@ -9502,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", @@ -9525,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", ] @@ -9566,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]] @@ -9584,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]] @@ -9605,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" @@ -9629,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", @@ -9648,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" @@ -9662,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", ] @@ -9674,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", ] @@ -9688,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", @@ -9706,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]] @@ -9725,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" @@ -9742,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" @@ -9762,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", ] @@ -9781,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", @@ -9791,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", @@ -9817,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", @@ -9856,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", @@ -9870,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", @@ -9888,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", @@ -9901,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", @@ -9917,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", @@ -9938,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", @@ -9956,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", @@ -9973,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", @@ -9984,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", @@ -10005,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", @@ -10031,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", @@ -10050,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", @@ -10065,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]] @@ -10077,7 +12166,7 @@ dependencies = [ "blake2b_simd", "byteorder", "digest 0.10.7", - "sha2 0.10.8", + "sha2 0.10.9", "sha3", "twox-hash", ] @@ -10085,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", ] @@ -10098,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", @@ -10146,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", @@ -10168,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", @@ -10190,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", @@ -10207,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", @@ -10217,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", @@ -10258,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", @@ -10268,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", @@ -10288,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", @@ -10299,7 +12388,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "paste", - "rand", + "rand 0.8.5", "scale-info", "serde", "simple-mermaid", @@ -10307,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)", @@ -10333,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", @@ -10353,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", @@ -10392,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", @@ -10405,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", @@ -10471,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", @@ -10526,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", @@ -10540,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", @@ -10563,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", @@ -10603,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", @@ -10615,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", @@ -10623,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]] @@ -10660,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", @@ -10683,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", @@ -10722,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", @@ -10748,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", @@ -10776,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", @@ -10803,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", @@ -10828,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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" -dependencies = [ - "cfg_aliases", - "memchr", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "str0m" -version = "0.5.1" +version = "1.0.4" 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", +checksum = "1389c88ddd739ec6d3f8f83343764a0e944cd23cfbf126a9796a714b0b6edd6f" +dependencies = [ + "cfg_aliases 0.1.1", + "memchr", + "proc-macro2", + "quote", + "syn 1.0.109", ] +[[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" @@ -10918,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" @@ -10951,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", @@ -10971,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", @@ -11007,7 +13072,7 @@ dependencies = [ "sp-version", "strum 0.26.3", "tempfile", - "toml 0.8.19", + "toml 0.8.23", "walkdir", "wasm-opt", ] @@ -11022,7 +13087,7 @@ dependencies = [ "quote", "rayon", "subtensor-linting", - "syn 2.0.90", + "syn 2.0.103", "walkdir", ] @@ -11030,7 +13095,7 @@ dependencies = [ name = "subtensor-custom-rpc" version = "0.0.2" dependencies = [ - "jsonrpsee", + "jsonrpsee 0.24.9", "pallet-subtensor", "parity-scale-codec", "serde", @@ -11062,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]] @@ -11093,13 +13158,15 @@ dependencies = [ "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]] @@ -11108,7 +13175,6 @@ version = "0.1.0" dependencies = [ "frame-support", "parity-scale-codec", - "precompile-utils", "scale-info", "serde", "sp-core", @@ -11116,13 +13182,24 @@ dependencies = [ "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]] name = "subtensor-tools" version = "0.1.0" dependencies = [ "anyhow", "clap", - "semver 1.0.23", + "semver 1.0.26", "toml_edit", ] @@ -11138,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" @@ -11151,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", @@ -11174,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" @@ -11218,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", ] @@ -11240,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]] @@ -11282,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]] @@ -11299,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" @@ -11311,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", @@ -11326,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", @@ -11349,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", ] @@ -11373,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", ] @@ -11418,7 +13694,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.103", ] [[package]] @@ -11431,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", @@ -11445,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", @@ -11483,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", @@ -11495,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" @@ -11536,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", @@ -11560,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", @@ -11572,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", @@ -11601,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" @@ -11623,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", @@ -11678,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", @@ -11704,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", @@ -11724,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", @@ -11748,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" @@ -11774,7 +14108,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand", + "rand 0.8.5", "static_assertions", ] @@ -11789,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" @@ -11811,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" @@ -11832,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" @@ -11844,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" @@ -11896,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", ] @@ -11911,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" @@ -11950,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" @@ -11986,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", @@ -12040,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" @@ -12077,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", ] @@ -12121,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" @@ -12131,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" @@ -12182,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", @@ -12204,7 +14644,7 @@ dependencies = [ "log", "object 0.30.4", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -12239,7 +14679,7 @@ dependencies = [ "object 0.30.4", "serde", "target-lexicon", - "thiserror", + "thiserror 1.0.69", "wasmparser", "wasmtime-types", ] @@ -12306,7 +14746,7 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand", + "rand 0.8.5", "rustix 0.36.17", "wasmtime-asm-macros", "wasmtime-environ", @@ -12322,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]] @@ -12353,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", @@ -12376,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" @@ -12413,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]] @@ -12529,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" @@ -12554,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" @@ -12572,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" @@ -12590,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" @@ -12614,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" @@ -12632,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" @@ -12650,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" @@ -12668,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", ] @@ -12687,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" @@ -12703,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", ] @@ -12721,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" @@ -12777,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" @@ -12792,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]] @@ -12830,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]] @@ -12873,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 8641f907ec..839558d18b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,32 +33,40 @@ members = [ ] resolver = "2" +[workspace.package] +edition = "2024" + [workspace.lints.clippy] -indexing-slicing = "deny" arithmetic-side-effects = "deny" -type_complexity = "allow" -unwrap-used = "deny" +indexing-slicing = "deny" manual_inspect = "allow" result_large_err = "allow" +type_complexity = "allow" +unwrap-used = "deny" 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 = [ @@ -68,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" @@ -98,132 +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-precompile-dispatch = { 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", @@ -247,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/common/Cargo.toml b/common/Cargo.toml index acbc72897c..b46a4de4a9 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -13,7 +13,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { workspace = true } frame-support = { workspace = true } -precompile-utils = { workspace = true } scale-info = { workspace = true } serde = { workspace = true } sp-core = { workspace = true } @@ -29,7 +28,6 @@ fast-blocks = [] std = [ "codec/std", "frame-support/std", - "precompile-utils/std", "scale-info/std", "serde/std", "sp-core/std", diff --git a/common/src/lib.rs b/common/src/lib.rs index 6e2f2900eb..9134b77295 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -66,6 +66,14 @@ impl NetUid { 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 { @@ -130,6 +138,7 @@ pub enum ProxyType { RootWeights, ChildKeys, SudoUncheckedSetCode, + SwapHotkey, } impl Default for ProxyType { @@ -139,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::*; 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/run-ci.sh b/evm-tests/run-ci.sh index dbdabfbd8b..7ad4bb2186 100755 --- a/evm-tests/run-ci.sh +++ b/evm-tests/run-ci.sh @@ -19,6 +19,13 @@ 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 # 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 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/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 bc1ed21712..1090c7e002 100644 --- a/pallets/admin-utils/Cargo.toml +++ b/pallets/admin-utils/Cargo.toml @@ -32,6 +32,7 @@ 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] @@ -43,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"] @@ -57,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", @@ -68,6 +71,7 @@ std = [ "sp-tracing/std", "sp-weights/std", "substrate-fixed/std", + "subtensor-swap-interface/std", "subtensor-runtime-common/std" ] runtime-benchmarks = [ @@ -79,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/lib.rs b/pallets/admin-utils/src/lib.rs index b4bd58364f..b8859e66a9 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -105,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)] @@ -149,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>, @@ -170,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); @@ -197,8 +199,8 @@ 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: NetUid, @@ -219,8 +221,8 @@ 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: NetUid, @@ -246,8 +248,8 @@ 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: NetUid, @@ -273,8 +275,8 @@ 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: NetUid, @@ -323,8 +325,8 @@ 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: NetUid, @@ -353,8 +355,8 @@ 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: NetUid, @@ -381,8 +383,8 @@ 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 ))] @@ -410,8 +412,8 @@ 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: NetUid, @@ -437,8 +439,8 @@ 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: NetUid, @@ -464,8 +466,8 @@ 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: NetUid, @@ -491,8 +493,8 @@ 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: NetUid, @@ -521,8 +523,8 @@ 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)))] + .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)?; @@ -540,8 +542,8 @@ 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)))] + .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)?; @@ -559,8 +561,8 @@ 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: NetUid, @@ -593,8 +595,8 @@ 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 ))] @@ -622,7 +624,7 @@ 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 ))] @@ -649,8 +651,8 @@ 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: NetUid, @@ -679,8 +681,8 @@ 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: NetUid, @@ -706,8 +708,8 @@ 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: NetUid, @@ -733,8 +735,8 @@ 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: NetUid, @@ -759,8 +761,8 @@ 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: NetUid, @@ -794,8 +796,8 @@ 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: NetUid, @@ -828,8 +830,8 @@ 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: NetUid, @@ -855,8 +857,8 @@ 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: NetUid, @@ -886,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 ))] @@ -909,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 ))] @@ -928,8 +930,8 @@ 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)))] + .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!( @@ -963,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 ))] @@ -986,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 ))] @@ -1009,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 ))] @@ -1024,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 ))] @@ -1086,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"); } @@ -1148,8 +1150,8 @@ 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: NetUid, @@ -1349,8 +1351,8 @@ 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: NetUid, @@ -1385,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)?; @@ -1411,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` @@ -1513,7 +1515,7 @@ pub mod pallet { pub fn sudo_set_subnet_owner_hotkey( origin: OriginFor, netuid: NetUid, - hotkey: T::AccountId, + hotkey: ::AccountId, ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner(origin.clone(), netuid)?; pallet_subtensor::Pallet::::set_subnet_owner_hotkey(netuid, &hotkey); @@ -1560,10 +1562,14 @@ 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)] @@ -1571,9 +1577,21 @@ pub mod pallet { pub fn sudo_set_alpha_sigmoid_steepness( origin: OriginFor, netuid: NetUid, - steepness: u16, + 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!( @@ -1675,7 +1693,7 @@ pub mod pallet { pub fn sudo_set_sn_owner_hotkey( origin: OriginFor, netuid: NetUid, - hotkey: T::AccountId, + hotkey: ::AccountId, ) -> DispatchResult { pallet_subtensor::Pallet::::do_set_sn_owner_hotkey(origin, netuid, &hotkey) } diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index 830c659c42..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; @@ -33,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, } ); @@ -69,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; @@ -212,6 +216,7 @@ impl pallet_subtensor::Config for Test { type InitialTaoWeight = InitialTaoWeight; type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod; type DurationOfStartCall = DurationOfStartCall; + type SwapInterface = Swap; type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost; type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval; } @@ -272,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 { @@ -366,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. diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index 9e70858566..260dc9f7c3 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -1146,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 = NetUid::from(1); - let alpha_low: u16 = 12_u16; + let alpha_low: u16 = 1638_u16; let alpha_high: u16 = u16::MAX - 10; let call = RuntimeCall::AdminUtils(crate::Call::sudo_set_alpha_values { netuid, @@ -1169,7 +1228,7 @@ fn test_set_alpha_values_dispatch_info_ok() { fn test_sudo_get_set_alpha() { new_test_ext().execute_with(|| { let netuid = NetUid::from(1); - let alpha_low: u16 = 12_u16; + let alpha_low: u16 = 1638_u16; let alpha_high: u16 = u16::MAX - 10; let hotkey: U256 = U256::from(1); @@ -1252,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(), @@ -1289,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(), 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/src/lib.rs b/pallets/commitments/src/lib.rs index 217451a00f..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; @@ -344,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, @@ -401,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 8b8e58150e..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, @@ -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/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 dd172befc0..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. 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 cd9cf258c1..93f88139ef 100644 --- a/pallets/subtensor/Cargo.toml +++ b/pallets/subtensor/Cargo.toml @@ -44,6 +44,8 @@ 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 } @@ -58,11 +60,11 @@ ark-serialize = { workspace = true, default-features = false } w3f-bls = { workspace = true, default-features = false } sha2 = { workspace = true } rand_chacha = { workspace = true } -subtensor-runtime-common = { 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 } @@ -91,6 +93,7 @@ std = [ "pallet-membership/std", "pallet-preimage/std", "pallet-scheduler/std", + "pallet-subtensor-swap/std", "pallet-transaction-payment/std", "pallet-utility/std", "rand_chacha/std", @@ -111,6 +114,7 @@ std = [ "substrate-fixed/std", "substrate-fixed/std", "subtensor-runtime-common/std", + "subtensor-swap-interface/std", "tle/std", "w3f-bls/std", ] @@ -120,13 +124,15 @@ 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", diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index b6512c6055..eb3c7b11ca 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -58,6 +58,12 @@ pub trait SubtensorCustomApi { fn get_subnets_info_v2(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetHyperparams")] 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")] @@ -284,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); diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index ac2de7e9d9..e482a01251 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -9,7 +9,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 sp_runtime::AccountId32; use subtensor_runtime_common::NetUid; @@ -36,6 +36,7 @@ sp_api::decl_runtime_apis! { fn get_subnet_info_v2(netuid: NetUid) -> Option>; fn get_subnets_info_v2() -> Vec>>; 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: NetUid) -> Option>; diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index b6a8f903be..c62d1dcecc 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -705,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; @@ -1316,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 f1c8478e22..4f6fb9d95f 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -6,6 +6,7 @@ use substrate_fixed::{ types::{I96F32, U96F32}, }; use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::SwapHandler; impl Pallet { /// Calculates the dynamic TAO emission for a given subnet. @@ -39,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/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 833f0e7c8f..1274a84a6f 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -3,6 +3,7 @@ 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; @@ -70,7 +71,7 @@ impl Pallet { // 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); @@ -138,6 +139,8 @@ 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); } // --- 5. Compute owner cuts and remove them from alpha_out remaining. @@ -192,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. diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index 715eb89f69..a636cdd9a1 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -1298,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 = @@ -1341,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 ); diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 1a48024bb0..f4801d63f0 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,7 +25,10 @@ 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; @@ -595,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] @@ -800,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 { @@ -836,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 { @@ -1050,6 +1042,9 @@ pub mod pallet { #[pallet::storage] // --- MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. pub type SubnetTAO = 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, NetUid, u64, ValueQuery, DefaultZeroU64>; @@ -1062,7 +1057,12 @@ pub mod pallet { #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. pub type SubnetAlphaIn = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. + #[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. + /// TODO: Deprecate, not accurate and not used in v3 anymore pub type SubnetAlphaOut = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it @@ -1292,7 +1292,7 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( netuid ) --> AlphaSigmoidSteepness pub type AlphaSigmoidSteepness = - StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultAlphaSigmoidSteepness>; + StorageMap<_, Identity, NetUid, i16, ValueQuery, DefaultAlphaSigmoidSteepness>; #[pallet::storage] /// --- MAP ( netuid ) --> Kappa pub type Kappa = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultKappa>; @@ -1685,6 +1685,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. @@ -1837,22 +1848,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())) + } +} + +#[freeze_struct("2e02eb32e5cb25d3")] +#[derive(Default, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)] +pub struct SubtensorTransactionExtension(pub PhantomData); -impl Default for SubtensorSignedExtension -where - ::RuntimeCall: - Dispatchable, - ::RuntimeCall: IsSubType>, -{ - fn default() -> Self { - Self::new() +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, @@ -1886,59 +1898,31 @@ where 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, @@ -1948,127 +1932,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 { @@ -2077,11 +2053,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( @@ -2094,6 +2068,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_staked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::add_stake_limit { hotkey, @@ -2103,18 +2078,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 @@ -2129,6 +2098,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_staked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::remove_stake { hotkey, @@ -2147,6 +2117,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_unstaked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::remove_stake_limit { hotkey, @@ -2158,10 +2129,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 @@ -2176,6 +2144,7 @@ where ), Self::get_priority_staking(who, hotkey, *amount_unstaked), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::unstake_all { hotkey }) => { // Fully validate the user input @@ -2183,6 +2152,7 @@ where 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 @@ -2190,6 +2160,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, @@ -2199,10 +2170,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 @@ -2221,6 +2189,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, @@ -2230,10 +2199,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 @@ -2252,6 +2218,7 @@ where ), Self::get_priority_staking(who, hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::swap_stake { hotkey, @@ -2260,10 +2227,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 @@ -2282,6 +2246,7 @@ where ), Self::get_priority_staking(who, hotkey, *alpha_amount), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } Some(Call::swap_stake_limit { hotkey, @@ -2292,10 +2257,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 @@ -2304,10 +2266,7 @@ where *destination_netuid, *limit_price, ) else { - return InvalidTransaction::Custom( - CustomTransactionError::ZeroMaxAmount.into(), - ) - .into(); + return Err(CustomTransactionError::ZeroMaxAmount.into()); }; // Fully validate the user input @@ -2326,13 +2285,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 = @@ -2342,29 +2299,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 { @@ -2392,6 +2351,7 @@ where ), Self::get_priority_vanilla(), ) + .map(|validity| (validity, Some(who.clone()), origin.clone())) } _ => { if let Some( @@ -2401,102 +2361,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(()) } } @@ -2584,6 +2519,98 @@ 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 + ); + + 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 + ); + + 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)] diff --git a/pallets/subtensor/src/macros/config.rs b/pallets/subtensor/src/macros/config.rs index b0f2483331..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; diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 7f07c5e29e..8ceccc5fa2 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -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 { @@ -585,9 +585,9 @@ 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, @@ -924,9 +924,9 @@ 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: NetUid, @@ -1045,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, @@ -1465,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( @@ -1608,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) } @@ -1637,9 +1637,9 @@ 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, @@ -1680,9 +1680,9 @@ 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, @@ -1722,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 @@ -1787,9 +1787,9 @@ 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(14)) - .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, @@ -1851,9 +1851,9 @@ 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, @@ -1895,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 @@ -2001,12 +2001,11 @@ mod dispatches { pub fn associate_evm_key( origin: T::RuntimeOrigin, netuid: NetUid, - hotkey: T::AccountId, 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 @@ -2058,5 +2057,17 @@ mod dispatches { ) -> DispatchResult { Self::do_burn_alpha(origin, hotkey, amount, netuid) } + + /// 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 6e701014ae..fd7bc12e16 100644 --- a/pallets/subtensor/src/macros/errors.rs +++ b/pallets/subtensor/src/macros/errors.rs @@ -216,5 +216,7 @@ mod errors { 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 b327376aad..3f3c71860d 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -51,7 +51,7 @@ mod events { /// Rho value is set. RhoSet(NetUid, u16), /// steepness of the sigmoid used to compute alpha values. - AlphaSigmoidSteepnessSet(NetUid, u16), + AlphaSigmoidSteepnessSet(NetUid, i16), /// Kappa is set for a subnet. KappaSet(NetUid, u16), /// minimum allowed weight is set for a subnet. diff --git a/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs b/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs index 068fcc35b3..eae5eedc87 100644 --- a/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs +++ b/pallets/subtensor/src/migrations/migrate_delete_subnet_21.rs @@ -1,6 +1,5 @@ use super::*; use frame_support::{ - pallet_prelude::*, storage_alias, traits::{Get, GetStorageVersion, StorageVersion}, weights::Weight, diff --git a/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs b/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs index fde7e09920..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, diff --git a/pallets/subtensor/src/migrations/migrate_rao.rs b/pallets/subtensor/src/migrations/migrate_rao.rs index f4cd87b356..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::*; 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 b97acaa4a3..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, 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/rpc_info/stake_info.rs b/pallets/subtensor/src/rpc_info/stake_info.rs index 56a0a066cb..5fd9f6f7b8 100644 --- a/pallets/subtensor/src/rpc_info/stake_info.rs +++ b/pallets/subtensor/src/rpc_info/stake_info.rs @@ -1,9 +1,11 @@ -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("56f5e9f33e5ec9da")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] @@ -117,29 +119,12 @@ impl Pallet { pub fn get_stake_fee( origin: Option<(T::AccountId, NetUid)>, - origin_coldkey_account: T::AccountId, + _origin_coldkey_account: T::AccountId, destination: Option<(T::AccountId, NetUid)>, - destination_coldkey_account: T::AccountId, + _destination_coldkey_account: T::AccountId, amount: u64, ) -> u64 { - let origin_ = 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 02ebb35b3c..cab1f8800b 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -3,6 +3,7 @@ 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("dd2293544ffd8f2e")] @@ -84,6 +85,44 @@ 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: NetUid) -> Option> { if !Self::if_subnet_exist(netuid) { @@ -288,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 f04bffe898..77b4a8fa48 100644 --- a/pallets/subtensor/src/staking/add_stake.rs +++ b/pallets/subtensor/src/staking/add_stake.rs @@ -1,6 +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. @@ -69,14 +71,13 @@ 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(()) @@ -163,19 +164,11 @@ 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(()) @@ -194,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 aacc448952..286877b1c9 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -1,8 +1,3 @@ -use super::*; -use safe_math::*; -use substrate_fixed::types::U96F32; -use subtensor_runtime_common::NetUid; - use frame_support::traits::{ Imbalance, tokens::{ @@ -10,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. @@ -42,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 @@ -64,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::() } @@ -179,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, + ); + } } } } @@ -278,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 56cdf69511..ebacd90194 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -1,8 +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. @@ -321,7 +322,7 @@ impl Pallet { 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)? @@ -350,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); @@ -382,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 @@ -410,6 +401,8 @@ 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: NetUid, destination_netuid: NetUid, @@ -456,8 +449,10 @@ impl Pallet { } // 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); } @@ -465,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); } @@ -480,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/remove_stake.rs b/pallets/subtensor/src/staking/remove_stake.rs index 0fa7e94977..5f54a7449b 100644 --- a/pallets/subtensor/src/staking/remove_stake.rs +++ b/pallets/subtensor/src/staking/remove_stake.rs @@ -1,5 +1,6 @@ +use subtensor_swap_interface::{OrderType, SwapHandler}; + use super::*; -use substrate_fixed::types::U96F32; use subtensor_runtime_common::NetUid; impl Pallet { @@ -64,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); @@ -158,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); @@ -253,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); @@ -281,8 +274,8 @@ impl Pallet { &coldkey, NetUid::ROOT, total_tao_unstaked, - 0, // no fee for restaking - ); + T::SwapInterface::max_price(), + )?; // 5. Done and ok. Ok(()) @@ -365,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); @@ -405,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 dc2da75785..35867f82ca 100644 --- a/pallets/subtensor/src/staking/set_children.rs +++ b/pallets/subtensor/src/staking/set_children.rs @@ -1,5 +1,5 @@ use super::*; -use sp_core::Get; + use subtensor_runtime_common::NetUid; impl Pallet { @@ -124,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)); diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 6629fd562d..cc1a1ad148 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -2,8 +2,9 @@ use super::*; use safe_math::*; use share_pool::{SharePool, SharePoolDataOperations}; 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. @@ -20,32 +21,6 @@ impl Pallet { 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: NetUid) -> U96F32 { - if netuid.is_root() { - 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: NetUid) -> U96F32 { let one = U96F32::saturating_from_num(1.0); if netuid.is_root() { @@ -82,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`` @@ -631,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: NetUid, 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: NetUid, 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: NetUid, 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: NetUid, 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, + }) } } @@ -782,14 +732,24 @@ impl Pallet { coldkey: &T::AccountId, 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. @@ -799,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. @@ -841,54 +792,64 @@ impl Pallet { coldkey: &T::AccountId, 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( @@ -900,7 +861,6 @@ impl Pallet { } /// Validate add_stake user input - /// pub fn validate_add_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, @@ -916,7 +876,16 @@ impl Pallet { 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); @@ -939,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); @@ -972,14 +945,13 @@ impl Pallet { // 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 @@ -1104,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 @@ -1122,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!( @@ -1149,65 +1108,43 @@ impl Pallet { Ok(()) } - pub(crate) fn calculate_staking_fee( - origin: Option<(&T::AccountId, NetUid)>, - _origin_coldkey: &T::AccountId, - destination: Option<(&T::AccountId, NetUid)>, - _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.is_root() || 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)); + } + } + + 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)); } } } diff --git a/pallets/subtensor/src/subnets/registration.rs b/pallets/subtensor/src/subnets/registration.rs index b01abec248..a2eb180af1 100644 --- a/pallets/subtensor/src/subnets/registration.rs +++ b/pallets/subtensor/src/subnets/registration.rs @@ -3,6 +3,7 @@ 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"; @@ -140,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. @@ -482,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!( diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index 4b598c77d6..9cb79a1002 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -55,36 +55,36 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads(2)); - // 7. Swap LastTxBlock + // 7. Ensure the new hotkey is not already registered on any network + ensure!( + !Self::is_hotkey_registered_on_any_network(new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + + // 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)); - // 8. Swap LastTxBlockDelegateTake + // 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)); - // 9. Swap LastTxBlockChildKeyTake + // 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)); - // 10. fork for swap hotkey on a specific subnet case after do the common check + // 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 - // 11. Ensure the new hotkey is not already registered on any network - ensure!( - !Self::is_hotkey_registered_on_any_network(new_hotkey), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - // 12. Get the cost for swapping the key let swap_cost = Self::get_key_swap_cost(); log::debug!("Swap cost: {:?}", swap_cost); diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 556b19c380..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; @@ -2205,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 = NetUid::from(0); - let child_netuid = NetUid::from(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, @@ -2413,13 +2426,19 @@ fn test_revoke_child_no_min_stake_check() { 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, NetUid::ROOT, - StakeThreshold::::get(), + StakeThreshold::::get() + fee, ); // Schedule parent-child relationship @@ -2439,7 +2458,7 @@ fn test_revoke_child_no_min_stake_check() { &parent, &coldkey, NetUid::ROOT, - StakeThreshold::::get(), + StakeThreshold::::get() + fee, ); // Ensure the childkeys are applied @@ -2485,13 +2504,17 @@ fn test_do_set_child_registration_disabled() { 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 @@ -2510,7 +2533,7 @@ fn test_do_set_child_registration_disabled() { &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get() + fee, ); // Ensure the childkeys are applied @@ -2817,6 +2840,7 @@ fn test_childkey_take_drain() { // 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); @@ -2959,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. @@ -3158,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. @@ -3187,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) @@ -3211,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); @@ -3219,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 @@ -3230,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) - @@ -3268,6 +3304,7 @@ fn test_dividend_distribution_with_children() { new_test_ext(1).execute_with(|| { 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); @@ -3290,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. @@ -3318,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) @@ -3495,12 +3531,12 @@ fn test_dynamic_parent_child_relationships() { 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); @@ -3517,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 @@ -3557,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)]); @@ -3795,6 +3833,7 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { 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); @@ -3810,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. @@ -3836,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) @@ -3953,14 +3991,14 @@ 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); @@ -3970,6 +4008,7 @@ fn test_pending_cooldown_one_day() { 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); diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 338b8ad9a2..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}; @@ -439,6 +441,7 @@ fn test_owner_cut_base() { new_test_ext(1).execute_with(|| { 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)); @@ -456,6 +459,7 @@ fn test_pending_swapped() { 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(NetUid::ROOT, 1_000_000_000); // Add root weight. @@ -464,12 +468,18 @@ fn test_pending_swapped() { 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) }); } @@ -1988,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); @@ -2142,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/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index 0e567796d7..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)] @@ -561,17 +561,23 @@ fn test_1_graph() { 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( @@ -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 )); }); @@ -2227,7 +2237,7 @@ fn test_validator_permits() { fn test_get_set_alpha() { new_test_ext(1).execute_with(|| { let netuid = NetUid::from(1); - let alpha_low: u16 = 12_u16; + 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(), @@ -2643,7 +2659,7 @@ fn setup_yuma_3_scenario(netuid: NetUid, n: u16, sparse: bool, max_stake: u64, s 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 @@ -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 95d0c4e6db..a65e69c207 100644 --- a/pallets/subtensor/src/tests/evm.rs +++ b/pallets/subtensor/src/tests/evm.rs @@ -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, @@ -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,43 +123,6 @@ 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 = NetUid::from(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(|| { @@ -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, @@ -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/mock.rs b/pallets/subtensor/src/tests/mock.rs index 53972ef391..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; @@ -20,7 +23,9 @@ use sp_runtime::{ }; 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; @@ -40,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, } ); @@ -55,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)] @@ -156,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; @@ -445,10 +449,32 @@ 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; impl PrivilegeCmp for OriginPrivilegeCmp { @@ -532,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; @@ -555,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(), (), ())) } } @@ -857,8 +894,14 @@ pub fn increase_stake_on_coldkey_hotkey_account( tao_staked: u64, 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. @@ -875,3 +918,59 @@ pub fn increase_stake_on_hotkey_account(hotkey: &U256, increment: u64, netuid: N 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/move_stake.rs b/pallets/subtensor/src/tests/move_stake.rs index fd8b890f96..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 @@ -18,12 +25,18 @@ fn test_do_move_success() { 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 ); }); } @@ -143,7 +158,9 @@ fn test_do_move_nonexistent_subnet() { let destination_hotkey = U256::from(3); 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, ); }); } @@ -242,12 +259,20 @@ fn test_do_move_nonexistent_destination_hotkey() { let nonexistent_destination_hotkey = U256::from(99); // Assuming this hotkey doesn't exist 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), @@ -520,10 +581,19 @@ fn test_do_move_wrong_origin() { let destination_hotkey = U256::from(3); 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 ); }); } @@ -739,17 +821,23 @@ fn test_do_move_max_values() { let destination_hotkey = U256::from(3); let max_stake = u64::MAX; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let fee = 0; // 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 = 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 ); }); } @@ -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); }); } @@ -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); @@ -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/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index 277d56c81f..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 ); diff --git a/pallets/subtensor/src/tests/registration.rs b/pallets/subtensor/src/tests/registration.rs index d3dd827898..084eda0b66 100644 --- a/pallets/subtensor/src/tests/registration.rs +++ b/pallets/subtensor/src/tests/registration.rs @@ -1,18 +1,19 @@ #![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 *********************************************/ @@ -38,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 } @@ -219,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 @@ -272,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); @@ -301,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); @@ -316,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 @@ -356,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); @@ -384,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); @@ -401,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 @@ -430,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 @@ -549,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); @@ -602,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; @@ -1504,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); diff --git a/pallets/subtensor/src/tests/senate.rs b/pallets/subtensor/src/tests/senate.rs index a71a97b1e2..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(); @@ -67,7 +68,6 @@ fn test_senate_join_works() { 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( @@ -141,7 +144,6 @@ fn test_senate_vote_works() { 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( @@ -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), @@ -315,7 +324,6 @@ fn test_senate_leave_works() { 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( @@ -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( @@ -479,12 +494,16 @@ fn test_senate_leave_vote_removal() { SubtensorModule::set_target_registrations_per_interval(other_netuid, 1000); 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 @@ -535,7 +554,6 @@ fn test_senate_not_leave_when_stake_removed() { 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); @@ -543,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), @@ -575,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( @@ -626,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), @@ -693,12 +718,16 @@ fn test_adjust_senate_events() { let hotkey_account_id = U256::from(6); let burn_cost = 1000; let coldkey_account_id = U256::from(667); - let root_netuid = NetUid::ROOT; - 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 @@ -716,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( @@ -807,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 @@ -825,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 4bf4bf2689..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}; @@ -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 } @@ -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 } @@ -1411,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 @@ -1429,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 b0fc25fc8c..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 ************************************************************/ @@ -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,11 +53,12 @@ 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 = 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 @@ -119,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 @@ -131,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 @@ -167,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( @@ -343,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 } @@ -381,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( @@ -400,23 +424,17 @@ 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 ); }); } @@ -568,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::()); @@ -581,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, @@ -597,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) @@ -615,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!( @@ -651,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 + ),); }); } @@ -692,12 +711,13 @@ fn test_remove_stake_total_issuance_no_change() { let coldkey_account_id = U256::from(81337); let amount = DefaultMinStake::::get() * 10; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - 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); + mock::setup_reserves(netuid, amount * 100, amount * 100); + // Some basic assertions assert_eq!( SubtensorModule::get_total_stake(), @@ -716,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, @@ -731,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, @@ -742,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), @@ -751,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, @@ -766,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, ); }); @@ -776,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 = 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); + }); }); } @@ -994,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 ); }); } @@ -1024,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 @@ -1246,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( @@ -1281,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( @@ -1968,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); @@ -1976,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, @@ -2056,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, @@ -2114,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); @@ -2151,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); @@ -2173,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); @@ -2188,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, @@ -2214,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 ); }); } @@ -2342,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(|| { @@ -2351,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); @@ -2389,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(|| { @@ -2397,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); @@ -2425,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(|| { @@ -2462,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); @@ -2477,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), @@ -2496,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); }); } @@ -2514,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); @@ -2530,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, @@ -2551,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); @@ -2591,7 +2612,8 @@ fn test_add_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)); // Give it some $$$ in his coldkey balance @@ -2613,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() ); }); } @@ -2655,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 @@ -2673,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() ); }); } @@ -2696,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, @@ -2714,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 ); }); } @@ -2740,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 { @@ -2763,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() ); }); } @@ -2790,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 { @@ -2818,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() ); }); } @@ -2845,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); @@ -2854,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 }); @@ -2872,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() ); }); } @@ -2962,176 +3009,109 @@ 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(NetUid::ROOT, 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!( @@ -3211,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) @@ -3235,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), ), ( @@ -3276,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() @@ -3350,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 + ); + } + } }, ); }); @@ -3462,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 @@ -3492,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: @@ -3541,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 @@ -3578,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: @@ -3819,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 ); } @@ -3847,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 = 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 @@ -3866,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 @@ -3886,24 +3849,29 @@ 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, ); }); } @@ -3923,7 +3891,10 @@ fn test_add_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()); + // 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 @@ -3932,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!( @@ -3999,58 +3970,62 @@ 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 = 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, + 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, ); }); } @@ -4079,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 @@ -4162,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, @@ -4195,7 +4178,6 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { let coldkey_account_id = U256::from(81337); let amount = 10_000_000_000; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - let mut fee = DefaultStakingFee::::get(); register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); // Give it some $$$ in his coldkey balance @@ -4216,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, @@ -4224,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), @@ -4253,13 +4236,13 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { let coldkey_account_id = U256::from(81337); let amount = 10_000_000_000; let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - 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); // 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, @@ -4273,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, @@ -4281,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!( @@ -4332,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. @@ -4382,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 @@ -4416,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 = 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); }); } @@ -4463,40 +4455,35 @@ 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 = 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); - - 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( + // Give the neuron some stake to remove + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(coldkey), + hotkey, + netuid, + stake_amount + )); + + // 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( RuntimeOrigin::signed(coldkey), hotkey, )); 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_root = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, @@ -4514,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 = 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, @@ -4547,12 +4529,485 @@ 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_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() { new_test_ext(1).execute_with(|| { @@ -4599,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 7b50dd5e85..0c98a83bb1 100644 --- a/pallets/subtensor/src/tests/staking2.rs +++ b/pallets/subtensor/src/tests/staking2.rs @@ -1,12 +1,16 @@ -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] @@ -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!( @@ -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); @@ -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,24 +768,17 @@ 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 = NetUid::from(1); let netuid1 = NetUid::from(2); @@ -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 3800a801f9..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 *****************************/ @@ -17,6 +19,7 @@ fn test_do_start_call_ok() { 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); @@ -57,7 +60,14 @@ fn test_do_start_call_fail_not_owner() { 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); @@ -81,6 +91,13 @@ fn test_do_start_call_fail_with_cannot_start_call_now() { 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); @@ -102,10 +119,25 @@ fn test_do_start_call_fail_for_set_again() { 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(); @@ -135,6 +167,7 @@ fn test_do_start_call_ok_with_same_block_number_after_coinbase() { 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); @@ -307,15 +340,12 @@ fn test_subtoken_enable_reject_trading_before_enable() { Error::::SubtokenDisabled ); - // For unstake_all and unstake_all_alpha, the result is Ok, but the + // 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 - ), - () - ); + 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( @@ -326,12 +356,13 @@ fn test_subtoken_enable_reject_trading_before_enable() { stake_bal ); - assert_ok!( + // 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!( @@ -436,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); @@ -520,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, @@ -566,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 e2afc98c89..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] @@ -86,6 +90,9 @@ fn test_swap_total_coldkey_stake() { 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, @@ -290,6 +297,9 @@ fn test_swap_idempotency() { let hotkey = U256::from(3); 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); @@ -344,7 +354,6 @@ fn test_swap_with_max_values() { 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 = NetUid::from(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 ); }); } @@ -538,15 +579,9 @@ fn test_swap_concurrent_modifications() { 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))); }); } @@ -649,6 +681,9 @@ fn test_do_swap_coldkey_success() { 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,9 +857,7 @@ 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 @@ -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,9 +1013,7 @@ 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 @@ -990,11 +1023,13 @@ fn test_swap_staking_hotkeys_for_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 = NetUid::from(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( @@ -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); @@ -1613,7 +1662,10 @@ fn test_coldkey_delegations() { 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); }); @@ -1752,6 +1808,9 @@ fn test_schedule_swap_coldkey_execution() { let hotkey = U256::from(3); 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( @@ -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), @@ -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), @@ -2050,6 +2111,7 @@ fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() { 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), @@ -2119,7 +2181,11 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { 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); }); @@ -2374,7 +2515,10 @@ fn test_coldkey_in_swap_schedule_prevents_critical_calls() { 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 ba003b442c..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] @@ -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 = 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), @@ -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 ); }); } @@ -611,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); diff --git a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs index 7ed66cd8ac..5654498011 100644 --- a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs +++ b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs @@ -70,7 +70,7 @@ fn test_swap_total_hotkey_stake() { let coldkey = U256::from(3); let amount = DefaultMinStake::::get() * 10; - let fee = DefaultStakingFee::::get(); + let fee = (amount as f64 * 0.003) as u64; //add network let netuid = add_dynamic_network(&old_hotkey, &coldkey); @@ -497,7 +497,8 @@ 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 coldkey = U256::from(3); + let new_hotkey_2 = U256::from(3); + let coldkey = U256::from(4); SubtensorModule::add_balance_to_coldkey_account(&coldkey, u64::MAX); @@ -519,12 +520,12 @@ fn test_swap_hotkey_with_multiple_subnets() { assert_ok!(SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &new_hotkey, + &new_hotkey_2, Some(netuid2) )); assert!(IsNetworkMember::::get(new_hotkey, netuid1)); - assert!(IsNetworkMember::::get(new_hotkey, netuid2)); + assert!(IsNetworkMember::::get(new_hotkey_2, netuid2)); assert!(!IsNetworkMember::::get(old_hotkey, netuid1)); assert!(!IsNetworkMember::::get(old_hotkey, netuid2)); }); @@ -628,8 +629,9 @@ 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 coldkey1 = U256::from(3); - let coldkey2 = U256::from(4); + 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; @@ -687,7 +689,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { assert_ok!(SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey1), &old_hotkey, - &new_hotkey, + &new_hotkey_2, Some(netuid2) )); @@ -697,6 +699,11 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { 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!( @@ -709,7 +716,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &new_hotkey, + &new_hotkey_2, &coldkey2, netuid2 ), @@ -739,7 +746,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { )); assert!(SubtensorModule::is_hotkey_registered_on_network( netuid2, - &new_hotkey + &new_hotkey_2 )); assert!(!SubtensorModule::is_hotkey_registered_on_network( netuid1, @@ -752,7 +759,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { // Check total stake transfer assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), + 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); @@ -1143,7 +1151,8 @@ fn test_swap_multiple_subnets() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); - let coldkey = U256::from(3); + 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); @@ -1169,13 +1178,13 @@ fn test_swap_multiple_subnets() { assert_ok!(SubtensorModule::do_swap_hotkey( RuntimeOrigin::signed(coldkey), &old_hotkey, - &new_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, netuid2), children2); + 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()); }); @@ -1490,7 +1499,6 @@ fn test_swap_owner_check_swap_record_clean_up() { 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); @@ -1514,3 +1522,37 @@ fn test_swap_owner_check_swap_record_clean_up() { )); }); } + +// 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/weights.rs b/pallets/subtensor/src/tests/weights.rs index eb189d1ab5..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 @@ -69,7 +72,7 @@ fn test_set_rootweights_validate() { 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); }); @@ -186,7 +211,6 @@ fn test_commit_weights_validate() { 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); }); @@ -296,7 +343,6 @@ fn test_set_weights_validate() { 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); }); @@ -371,7 +433,7 @@ fn test_reveal_weights_validate() { 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); }); diff --git a/pallets/subtensor/src/utils/evm.rs b/pallets/subtensor/src/utils/evm.rs index 5d4f1ad493..ba6214968d 100644 --- a/pallets/subtensor/src/utils/evm.rs +++ b/pallets/subtensor/src/utils/evm.rs @@ -44,17 +44,11 @@ impl Pallet { pub fn do_associate_evm_key( origin: T::RuntimeOrigin, netuid: NetUid, - hotkey: T::AccountId, 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 { diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index cf7c5f1a18..9641cfb0ee 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -699,7 +699,7 @@ impl Pallet { (converted_low, converted_high) } - pub fn set_alpha_sigmoid_steepness(netuid: NetUid, steepness: u16) { + pub fn set_alpha_sigmoid_steepness(netuid: NetUid, steepness: i16) { AlphaSigmoidSteepness::::insert(netuid, steepness); } pub fn get_alpha_sigmoid_steepness(netuid: NetUid) -> I32F32 { @@ -723,6 +723,14 @@ impl Pallet { 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 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..f09928a2b2 --- /dev/null +++ b/pallets/swap-interface/src/lib.rs @@ -0,0 +1,50 @@ +#![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); + 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, +} 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..3f54dbfd74 --- /dev/null +++ b/pallets/swap/src/pallet/impls.rs @@ -0,0 +1,1197 @@ +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) { + // Get updated reserves, calculate liquidity + let tao_reserve = ::SubnetInfo::tao_reserve(netuid.into()); + let alpha_reserve = ::SubnetInfo::alpha_reserve(netuid.into()); + let liquidity = + helpers_128bit::sqrt((tao_reserve as u128).saturating_mul(alpha_reserve as u128)) + as 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) { + position.liquidity = 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, + }) + } + + 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 + if (liquidity_delta < 0) + && (position.liquidity.saturating_sub(delta_liquidity_abs) < T::MinimumLiquidity::get()) + { + delta_liquidity_abs = position.liquidity; + } + + // 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); + } + Positions::::insert(&(netuid, coldkey_account_id, position.id), position); + + // TODO: Withdraw balances and update pool reserves + + Ok(UpdateLiquidityResult { + tao: tao.saturating_to_num::(), + alpha: alpha.saturating_to_num::(), + fee_tao, + fee_alpha, + }) + } + + /// 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) { + Self::adjust_protocol_liquidity(netuid); + } + + 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..3a0e00bc8d --- /dev/null +++ b/pallets/swap/src/pallet/mod.rs @@ -0,0 +1,501 @@ +use core::num::NonZeroU64; + +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 liquidity is added to a subnet's liquidity pool. + LiquidityAdded { + /// The coldkey account that owns the position + coldkey: T::AccountId, + /// The hotkey account associated with the position + 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 liquidity is removed from a subnet's liquidity pool. + LiquidityRemoved { + /// The coldkey account that owns the position + coldkey: 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, + }, + } + + #[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, + 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::LiquidityAdded { + coldkey: coldkey.clone(), + hotkey: hotkey.clone(), + netuid, + position_id, + liquidity: liquidity_delta as u64, + tao: result.tao, + alpha: result.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 + Self::deposit_event(Event::LiquidityRemoved { + coldkey: coldkey.clone(), + netuid, + position_id, + tao: result.tao, + alpha: result.alpha, + 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 57fc8c67fb..16c73ac76d 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -31,7 +31,9 @@ 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 @@ -53,6 +55,7 @@ std = [ "pallet-evm/std", "pallet-proxy/std", "pallet-subtensor/std", + "pallet-subtensor-swap/std", "precompile-utils/std", "sp-core/std", "sp-io/std", @@ -60,4 +63,5 @@ 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 index ff37244cd0..3a4a36fb79 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -1,10 +1,12 @@ 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; @@ -12,7 +14,7 @@ pub struct AlphaPrecompile(PhantomData); impl PrecompileExt for AlphaPrecompile where - R: frame_system::Config + pallet_subtensor::Config, + R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config, R::AccountId: From<[u8; 32]>, { const INDEX: u64 = 2056; @@ -21,12 +23,15 @@ where #[precompile_utils::precompile] impl AlphaPrecompile where - R: frame_system::Config + pallet_subtensor::Config, + 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: U96F32 = pallet_subtensor::Pallet::::get_alpha_price(netuid.into()); + let price = + as SwapHandler>::current_alpha_price( + netuid.into(), + ); Ok(U256::from(price.saturating_to_num::())) } @@ -70,7 +75,7 @@ where #[precompile::public("getTaoWeight()")] #[precompile::view] fn get_tao_weight(_handle: &mut impl PrecompileHandle) -> EvmResult { - let weight: U96F32 = pallet_subtensor::Pallet::::get_tao_weight(); + let weight = pallet_subtensor::Pallet::::get_tao_weight(); Ok(U256::from(weight.saturating_to_num::())) } @@ -81,10 +86,16 @@ where netuid: u16, tao: u64, ) -> EvmResult { - let alpha_option = - pallet_subtensor::Pallet::::sim_swap_tao_for_alpha(netuid.into(), tao); - let result = alpha_option.unwrap_or(0); - Ok(U256::from(result)) + 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)")] @@ -94,10 +105,16 @@ where netuid: u16, alpha: u64, ) -> EvmResult { - let tao_option = - pallet_subtensor::Pallet::::sim_swap_alpha_for_tao(netuid.into(), alpha); - let result = tao_option.unwrap_or(0); - Ok(U256::from(result)) + 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)")] 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 c88f1e4b91..19020a0d1b 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -56,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> @@ -80,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> @@ -127,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> @@ -137,7 +140,7 @@ where + Dispatchable + Decode, <::RuntimeCall as Dispatchable>::RuntimeOrigin: - From>, + From>>, ::AddressMapping: AddressMapping, ::Balance: TryFrom, <::Lookup as StaticLookup>::Source: From, diff --git a/precompiles/src/solidity/subnet.abi b/precompiles/src/solidity/subnet.abi index b853a6f94c..805c0057d9 100644 --- a/precompiles/src/solidity/subnet.abi +++ b/precompiles/src/solidity/subnet.abi @@ -411,12 +411,12 @@ "type": "uint16" } ], - "name": "getServingRateLimit", + "name": "getAlphaSigmoidSteepness", "outputs": [ { - "internalType": "uint64", + "internalType": "uint16", "name": "", - "type": "uint64" + "type": "uint16" } ], "stateMutability": "view", @@ -957,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 a6086759bb..7517db3019 100644 --- a/precompiles/src/solidity/subnet.sol +++ b/precompiles/src/solidity/subnet.sol @@ -102,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( @@ -174,7 +183,7 @@ interface ISubnet { function getBondsResetEnabled(uint16 netuid) external view returns (bool); function setBondsResetEnabled( - uint16 netuid, + uint16 netuid, bool bondsResetEnabled ) external payable; diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index 03b2fa56ac..3a598db61c 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -394,9 +394,7 @@ where #[precompile::public("getAlphaSigmoidSteepness(uint16)")] #[precompile::view] fn get_alpha_sigmoid_steepness(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::AlphaSigmoidSteepness::::get( - NetUid::from(netuid), - )) + Ok(pallet_subtensor::AlphaSigmoidSteepness::::get(NetUid::from(netuid)) as u16) } #[precompile::public("setRho(uint16,uint16)")] @@ -422,7 +420,7 @@ where ) -> EvmResult<()> { let call = pallet_admin_utils::Call::::sudo_set_alpha_sigmoid_steepness { netuid: netuid.into(), - steepness, + steepness: (steepness as i16), }; handle.try_dispatch_runtime_call::( 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 581e3d2252..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: 276, + 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 { @@ -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; @@ -1189,10 +1204,33 @@ 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; pub struct AuraPalletIntrf; @@ -1270,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. @@ -1351,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; @@ -1409,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(); @@ -1544,8 +1589,8 @@ construct_runtime!( BaseFee: pallet_base_fee = 25, Drand: pallet_drand = 26, - Crowdloan: pallet_crowdloan = 27, + Swap: pallet_subtensor_swap = 28, } ); @@ -1555,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, @@ -1565,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, ); @@ -1580,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, @@ -1879,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( @@ -2107,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(), ) } @@ -2134,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; @@ -2234,6 +2277,10 @@ impl_runtime_apis! { SubtensorModule::get_subnet_hyperparams(netuid) } + 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) } @@ -2283,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/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 (%)