diff --git a/.github/workflows/docker-localnet.yml b/.github/workflows/docker-localnet.yml index 01de6eece8..b8e2f3eb09 100644 --- a/.github/workflows/docker-localnet.yml +++ b/.github/workflows/docker-localnet.yml @@ -12,6 +12,9 @@ on: push: branches: - devnet-ready + - main + - testnet + - devnet permissions: contents: read diff --git a/Cargo.lock b/Cargo.lock index 690e234d47..c0151a3c6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,7 +122,7 @@ dependencies = [ "const-hex", "derive_more 2.0.1", "foldhash", - "indexmap 2.9.0", + "indexmap 2.10.0", "itoa", "k256", "keccak-asm", @@ -758,9 +758,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -806,7 +806,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.0.7", + "rustix 1.0.8", "slab", "tracing", "windows-sys 0.59.0", @@ -840,7 +840,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", @@ -849,7 +849,7 @@ dependencies = [ "cfg-if", "event-listener 5.4.0", "futures-lite", - "rustix 1.0.7", + "rustix 1.0.8", "tracing", ] @@ -865,7 +865,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.7", + "rustix 1.0.8", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -1226,11 +1226,11 @@ dependencies = [ [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-task", "futures-io", "futures-lite", @@ -1279,9 +1279,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byte-slice-cast" @@ -1373,9 +1373,9 @@ checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" dependencies = [ "jobserver", "libc", @@ -1531,9 +1531,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -1541,9 +1541,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -1554,9 +1554,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1897,9 +1897,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -1955,9 +1955,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -2151,9 +2151,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71ea7f29c73f7ffa64c50b83c9fe4d3a6d4be89a86b009eb80d5a6d3429d741" +checksum = "be1149bab7a5580cb267215751389597c021bfad13c0bb00c54e19559333764c" dependencies = [ "cc", "cxxbridge-cmd", @@ -2165,12 +2165,13 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a8232661d66dcf713394726157d3cfe0a89bfc85f52d6e9f9bbc2306797fe7" +checksum = "6aeeaf1aefae8e0f5141920a7ecbc64a22ab038d4b4ac59f2d19e0effafd5b53" dependencies = [ "cc", "codespan-reporting", + "indexmap 2.10.0", "proc-macro2", "quote", "scratch", @@ -2179,12 +2180,13 @@ dependencies = [ [[package]] name = "cxxbridge-cmd" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f44296c8693e9ea226a48f6a122727f77aa9e9e338380cb021accaeeb7ee279" +checksum = "c36ac1f9a72064b1f41fd7b49a4c1b3bf33b9ccb1274874dda6d264f57c55964" dependencies = [ "clap", "codespan-reporting", + "indexmap 2.10.0", "proc-macro2", "quote", "syn 2.0.104", @@ -2192,16 +2194,17 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f69c181c176981ae44ba9876e2ea41ce8e574c296b38d06925ce9214fb8e4" +checksum = "170c6ff5d009663866857a91ebee55b98ea4d4b34e7d7aba6dc4a4c95cc7b748" [[package]] name = "cxxbridge-macro" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8faff5d4467e0709448187df29ccbf3b0982cc426ee444a193f87b11afb565a8" +checksum = "4984a142211026786011a7e79fa22faa1eca1e9cbf0e60bffecfd57fd3db88f1" dependencies = [ + "indexmap 2.10.0", "proc-macro2", "quote", "rustversion", @@ -2646,9 +2649,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", @@ -3035,7 +3038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" dependencies = [ "expander", - "indexmap 2.9.0", + "indexmap 2.10.0", "proc-macro-crate 3.3.0", "proc-macro2", "quote", @@ -4151,9 +4154,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", @@ -4161,7 +4164,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.9.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -4170,9 +4173,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -4180,7 +4183,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.9.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -4494,7 +4497,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -4517,7 +4520,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.10", + "h2 0.4.11", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -4555,7 +4558,7 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "log", - "rustls 0.23.28", + "rustls 0.23.29", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -4565,9 +4568,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" dependencies = [ "bytes", "futures-channel", @@ -4902,9 +4905,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", @@ -4954,6 +4957,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "io-uring" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +dependencies = [ + "bitflags 2.9.1", + "cfg-if", + "libc", +] + [[package]] name = "ip_network" version = "0.4.1" @@ -5146,7 +5160,7 @@ dependencies = [ "http 1.3.1", "jsonrpsee-core 0.23.2", "pin-project", - "rustls 0.23.28", + "rustls 0.23.29", "rustls-pki-types", "rustls-platform-verifier", "soketto 0.8.1", @@ -5583,9 +5597,9 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb68ea10844211a59ce46230909fd0ea040e8a192454d4cc2ee0d53e12280eb" +checksum = "3104e13b51e4711ff5738caa1fb54467c8604c2e94d607e27745bcf709068774" dependencies = [ "bs58", "ed25519-dalek", @@ -5889,9 +5903,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ "bitflags 2.9.1", "libc", @@ -6066,7 +6080,7 @@ dependencies = [ "futures", "futures-timer", "hickory-resolver", - "indexmap 2.9.0", + "indexmap 2.10.0", "libc", "mockall 0.13.1", "multiaddr 0.17.1", @@ -6282,9 +6296,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" dependencies = [ "libc", ] @@ -6750,7 +6764,7 @@ dependencies = [ "futures", "hex", "jsonrpsee 0.24.9", - "memmap2 0.9.5", + "memmap2 0.9.7", "node-subtensor-runtime", "num-traits", "pallet-commitments", @@ -7049,18 +7063,19 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", @@ -7218,7 +7233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43dfaf083aef571385fccfdc3a2f8ede8d0a1863160455d4f2b014d8f7d04a3f" dependencies = [ "expander", - "indexmap 2.9.0", + "indexmap 2.10.0", "itertools 0.11.0", "petgraph 0.6.5", "proc-macro-crate 3.3.0", @@ -8198,7 +8213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.9.0", + "indexmap 2.10.0", ] [[package]] @@ -8208,7 +8223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.9.0", + "indexmap 2.10.0", ] [[package]] @@ -8524,9 +8539,9 @@ dependencies = [ [[package]] name = "polkavm-common" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed9e5af472f729fcf3b3c1cf17508ddbb3505259dd6e2ee0fb5a29e105d22" +checksum = "49a5794b695626ba70d29e66e3f4f4835767452a6723f3a0bc20884b07088fe8" [[package]] name = "polkavm-derive" @@ -8539,11 +8554,11 @@ dependencies = [ [[package]] name = "polkavm-derive" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176144f8661117ea95fa7cf868c9a62d6b143e8a2ebcb7582464c3faade8669a" +checksum = "95282a203ae1f6828a04ff334145c3f6dc718bba6d3959805d273358b45eab93" dependencies = [ - "polkavm-derive-impl-macro 0.24.0", + "polkavm-derive-impl-macro 0.26.0", ] [[package]] @@ -8560,11 +8575,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a21844afdfcc10c92b9ef288ccb926211af27478d1730fcd55e4aec710179d" +checksum = "6069dc7995cde6e612b868a02ce48b54397c6d2582bd1b97b63aabbe962cd779" dependencies = [ - "polkavm-common 0.24.0", + "polkavm-common 0.26.0", "proc-macro2", "quote", "syn 2.0.104", @@ -8582,11 +8597,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl-macro" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0ef0f17ad81413ea1ca5b1b67553aedf5650c88269b673d3ba015c83bc2651" +checksum = "581d34cafec741dc5ffafbb341933c205b6457f3d76257a9d99fb56687219c91" dependencies = [ - "polkavm-derive-impl 0.24.0", + "polkavm-derive-impl 0.26.0", "syn 2.0.104", ] @@ -8621,7 +8636,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.5.2", "pin-project-lite", - "rustix 1.0.7", + "rustix 1.0.8", "tracing", "windows-sys 0.59.0", ] @@ -9689,15 +9704,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -9728,15 +9743,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.28" +version = "0.23.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" dependencies = [ "log", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.3", + "rustls-webpki 0.103.4", "subtle 2.6.1", "zeroize", ] @@ -9816,7 +9831,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.28", + "rustls 0.23.29", "rustls-native-certs 0.7.3", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", @@ -9855,9 +9870,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring 0.17.14", "rustls-pki-types", @@ -10033,7 +10048,7 @@ dependencies = [ "array-bytes", "docify", "log", - "memmap2 0.9.5", + "memmap2 0.9.7", "parity-scale-codec", "sc-chain-spec-derive", "sc-client-api", @@ -10708,7 +10723,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.4", "rand 0.8.5", - "rustls 0.23.28", + "rustls 0.23.29", "sc-client-api", "sc-network", "sc-network-common", @@ -11005,7 +11020,7 @@ dependencies = [ "async-trait", "futures", "futures-timer", - "indexmap 2.9.0", + "indexmap 2.10.0", "itertools 0.11.0", "linked-hash-map", "log", @@ -11217,9 +11232,9 @@ dependencies = [ [[package]] name = "schnorrkel" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +checksum = "6e9fcb6c2e176e86ec703e22560d99d65a5ee9056ae45a08e13e84ebf796296f" dependencies = [ "aead", "arrayref", @@ -11283,7 +11298,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "secp256k1-sys 0.8.1", + "secp256k1-sys 0.8.2", ] [[package]] @@ -11297,9 +11312,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" dependencies = [ "cc", ] @@ -11710,7 +11725,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-executor", "async-fs", "async-io", @@ -11782,7 +11797,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-lock", "base64 0.21.7", "blake2-rfc", @@ -12124,7 +12139,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -12220,7 +12235,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "proc-macro2", "quote", @@ -12230,7 +12245,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "environmental", "parity-scale-codec", @@ -12410,12 +12425,12 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive 0.24.0", + "polkavm-derive 0.26.0", "primitive-types 0.13.1", "sp-externalities 0.25.0", "sp-runtime-interface-proc-macro 17.0.0", @@ -12448,7 +12463,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "Inflector", "expander", @@ -12550,12 +12565,12 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "impl-serde 0.5.0", "parity-scale-codec", @@ -12591,9 +12606,10 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "parity-scale-codec", + "regex", "tracing", "tracing-core", "tracing-subscriber 0.3.19", @@ -12687,7 +12703,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#5072bf9b93dc1c9dff0161ab6efe2799036045e9" +source = "git+https://github.com/paritytech/polkadot-sdk#495d5a24c8078a0da1eb5e0fe8742a09f1f1bd5c" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -12784,7 +12800,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.4", "hashlink 0.10.0", - "indexmap 2.9.0", + "indexmap 2.10.0", "log", "memchr", "native-tls", @@ -13155,6 +13171,7 @@ dependencies = [ "log", "pallet-admin-utils", "pallet-balances", + "pallet-crowdloan", "pallet-evm", "pallet-evm-precompile-dispatch", "pallet-evm-precompile-modexp", @@ -13177,12 +13194,14 @@ dependencies = [ name = "subtensor-runtime-common" version = "0.1.0" dependencies = [ + "approx", "frame-support", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-runtime", + "substrate-fixed", "subtensor-macros", ] @@ -13465,7 +13484,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -13484,7 +13503,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 1.0.7", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -13674,17 +13693,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.1" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot 0.12.4", "pin-project-lite", "signal-hook-registry", + "slab", "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", @@ -13728,7 +13749,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.28", + "rustls 0.23.29", "tokio", ] @@ -13752,7 +13773,7 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.23.28", + "rustls 0.23.29", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -13810,7 +13831,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", @@ -14090,7 +14111,7 @@ dependencies = [ "httparse", "log", "rand 0.9.1", - "rustls 0.23.28", + "rustls 0.23.29", "rustls-pki-types", "sha1", "thiserror 2.0.12", @@ -15290,9 +15311,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -15390,9 +15411,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" [[package]] name = "xmltree" diff --git a/common/Cargo.toml b/common/Cargo.toml index b46a4de4a9..c0de294180 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -17,13 +17,17 @@ scale-info = { workspace = true } serde = { workspace = true } sp-core = { workspace = true } sp-runtime = { workspace = true } +substrate-fixed = { workspace = true } subtensor-macros = { workspace = true } +approx = {workspace = true, optional = true} + [lints] workspace = true [features] default = ["std"] +approx = ["dep:approx"] fast-blocks = [] std = [ "codec/std", @@ -32,4 +36,5 @@ std = [ "serde/std", "sp-core/std", "sp-runtime/std", + "substrate-fixed/std", ] diff --git a/common/src/currency.rs b/common/src/currency.rs new file mode 100644 index 0000000000..f50e2bc9a1 --- /dev/null +++ b/common/src/currency.rs @@ -0,0 +1,231 @@ +use core::fmt::{self, Display, Formatter}; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; + +#[cfg(feature = "approx")] +use approx::AbsDiffEq; +use codec::{Compact, CompactAs, Decode, Encode, Error as CodecError, MaxEncodedLen}; +use frame_support::pallet_prelude::*; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; +use substrate_fixed::traits::{Fixed, ToFixed}; +use subtensor_macros::freeze_struct; + +#[freeze_struct("b21dcd0434b67c67")] +#[repr(transparent)] +#[derive( + Deserialize, + Serialize, + Clone, + Copy, + Decode, + Default, + Encode, + Eq, + Hash, + MaxEncodedLen, + Ord, + PartialEq, + PartialOrd, + RuntimeDebug, +)] +pub struct AlphaCurrency(u64); + +impl TypeInfo for AlphaCurrency { + type Identity = ::Identity; + fn type_info() -> scale_info::Type { + ::type_info() + } +} + +impl Display for AlphaCurrency { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl CompactAs for AlphaCurrency { + type As = u64; + + fn encode_as(&self) -> &Self::As { + &self.0 + } + + fn decode_from(v: Self::As) -> Result { + Ok(Self(v)) + } +} + +impl From> for AlphaCurrency { + fn from(c: Compact) -> Self { + c.0 + } +} + +impl From for u64 { + fn from(val: AlphaCurrency) -> Self { + val.0 + } +} + +impl From for AlphaCurrency { + fn from(value: u64) -> Self { + Self(value) + } +} + +impl ToFixed for AlphaCurrency { + fn to_fixed(self) -> F { + self.0.to_fixed() + } + + fn checked_to_fixed(self) -> Option { + self.0.checked_to_fixed() + } + + fn saturating_to_fixed(self) -> F { + self.0.saturating_to_fixed() + } + fn wrapping_to_fixed(self) -> F { + self.0.wrapping_to_fixed() + } + + fn overflowing_to_fixed(self) -> (F, bool) { + self.0.overflowing_to_fixed() + } +} + +impl Currency for AlphaCurrency { + const MAX: Self = Self(u64::MAX); + const ZERO: Self = Self(0); +} + +pub trait Currency: ToFixed + Into + From + Clone + Copy { + const MAX: Self; + const ZERO: Self; + + fn is_zero(&self) -> bool { + Into::::into(*self) == 0 + } + + fn to_u64(&self) -> u64 { + (*self).into() + } + + fn saturating_add(&self, rhv: Self) -> Self { + Into::::into(*self).saturating_add(rhv.into()).into() + } + + #[allow(clippy::arithmetic_side_effects)] + fn saturating_div(&self, rhv: Self) -> Self { + Into::::into(*self).saturating_div(rhv.into()).into() + } + + fn saturating_sub(&self, rhv: Self) -> Self { + Into::::into(*self).saturating_sub(rhv.into()).into() + } + + fn saturating_mul(&self, rhv: Self) -> Self { + Into::::into(*self).saturating_mul(rhv.into()).into() + } +} + +macro_rules! impl_arithmetic_operators { + ($currency_type:ident) => { + impl Add for $currency_type { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn add(self, rhs: Self) -> Self::Output { + let lhs_u64: u64 = self.into(); + let rhs_u64: u64 = rhs.into(); + (lhs_u64 + rhs_u64).into() + } + } + + impl Sub for $currency_type { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn sub(self, rhs: Self) -> Self::Output { + let lhs_u64: u64 = self.into(); + let rhs_u64: u64 = rhs.into(); + (lhs_u64 - rhs_u64).into() + } + } + + impl Mul for $currency_type { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn mul(self, rhs: Self) -> Self::Output { + let lhs_u64: u64 = self.into(); + let rhs_u64: u64 = rhs.into(); + (lhs_u64 * rhs_u64).into() + } + } + + impl Div for $currency_type { + type Output = Self; + + #[allow(clippy::arithmetic_side_effects)] + fn div(self, rhs: Self) -> Self::Output { + let lhs_u64: u64 = self.into(); + let rhs_u64: u64 = rhs.into(); + (lhs_u64 / rhs_u64).into() + } + } + + impl AddAssign for $currency_type { + #[allow(clippy::arithmetic_side_effects)] + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs; + } + } + + impl SubAssign for $currency_type { + #[allow(clippy::arithmetic_side_effects)] + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs; + } + } + + impl MulAssign for $currency_type { + #[allow(clippy::arithmetic_side_effects)] + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; + } + } + + impl DivAssign for $currency_type { + #[allow(clippy::arithmetic_side_effects)] + fn div_assign(&mut self, rhs: Self) { + *self = *self / rhs; + } + } + }; +} + +impl_arithmetic_operators!(AlphaCurrency); + +macro_rules! impl_approx { + ($currency_type:ident) => { + #[cfg(feature = "approx")] + impl AbsDiffEq for $currency_type { + type Epsilon = Self; + + fn default_epsilon() -> Self::Epsilon { + u64::default_epsilon().into() + } + + fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { + u64::abs_diff_eq(&u64::from(*self), &u64::from(*other), epsilon.into()) + } + + fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool { + u64::abs_diff_ne(&u64::from(*self), &u64::from(*other), epsilon.into()) + } + } + }; +} + +impl_approx!(AlphaCurrency); diff --git a/common/src/lib.rs b/common/src/lib.rs index 1df3b3eb35..44b7fb879a 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -11,6 +11,10 @@ use sp_runtime::{ }; use subtensor_macros::freeze_struct; +pub use currency::*; + +mod currency; + /// Balance of an account. pub type Balance = u64; @@ -151,7 +155,7 @@ impl Default for ProxyType { pub trait SubnetInfo { fn tao_reserve(netuid: NetUid) -> u64; - fn alpha_reserve(netuid: NetUid) -> u64; + fn alpha_reserve(netuid: NetUid) -> AlphaCurrency; fn exists(netuid: NetUid) -> bool; fn mechanism(netuid: NetUid) -> u16; fn is_owner(account_id: &AccountId, netuid: NetUid) -> bool; @@ -159,25 +163,25 @@ pub trait SubnetInfo { pub trait BalanceOps { fn tao_balance(account_id: &AccountId) -> u64; - fn alpha_balance(netuid: NetUid, coldkey: &AccountId, hotkey: &AccountId) -> u64; + fn alpha_balance(netuid: NetUid, coldkey: &AccountId, hotkey: &AccountId) -> AlphaCurrency; 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, + alpha: AlphaCurrency, ) -> Result<(), DispatchError>; fn decrease_stake( coldkey: &AccountId, hotkey: &AccountId, netuid: NetUid, - alpha: u64, - ) -> Result; + alpha: AlphaCurrency, + ) -> 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); + fn increase_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency); + fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency); } pub mod time { diff --git a/docker-compose.yml b/docker-compose.yml index 1fe7dae9e1..ad8ab222ce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,10 +9,11 @@ volumes: services: common: &common image: ghcr.io/opentensor/subtensor:latest - build: - context: . - dockerfile: Dockerfile - target: subtensor +## Uncomment to build from scratch: +# build: +# context: . +# dockerfile: Dockerfile +# target: subtensor cpu_count: 4 mem_limit: 40000000000 memswap_limit: 80000000000 @@ -40,6 +41,9 @@ services: - --no-mdns - --bootnodes=/dns/bootnode.finney.chain.opentensor.ai/tcp/30333/ws/p2p/12D3KooWRwbMb85RWnT8DSXSYMWQtuDwh4LJzndoRrTDotTR5gDC - --sync=warp + - --database paritydb + - --db-cache 4096 + - --trie-cache-size 2048 mainnet-archive: <<: *common @@ -70,6 +74,9 @@ services: - --sync=warp - --reserved-nodes=/dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr - --reserved-only + - --database paritydb + - --db-cache 4096 + - --trie-cache-size 2048 testnet-archive: <<: *common diff --git a/evm-tests/src/contracts/alpha.ts b/evm-tests/src/contracts/alpha.ts index 35baf83129..a87702eb80 100644 --- a/evm-tests/src/contracts/alpha.ts +++ b/evm-tests/src/contracts/alpha.ts @@ -9,7 +9,7 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getAlphaPrice", + "name": "getAlphaInEmission", "outputs": [ { "internalType": "uint256", @@ -28,12 +28,12 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getMovingAlphaPrice", + "name": "getAlphaInPool", "outputs": [ { - "internalType": "uint256", + "internalType": "uint64", "name": "", - "type": "uint256" + "type": "uint64" } ], "stateMutability": "view", @@ -47,7 +47,7 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getTaoInPool", + "name": "getAlphaIssuance", "outputs": [ { "internalType": "uint64", @@ -66,12 +66,12 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getAlphaInPool", + "name": "getAlphaOutEmission", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" } ], "stateMutability": "view", @@ -104,7 +104,26 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getAlphaIssuance", + "name": "getAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getEMAPriceHalvingBlocks", "outputs": [ { "internalType": "uint64", @@ -116,8 +135,14 @@ export const IAlphaABI = [ "type": "function" }, { - "inputs": [], - "name": "getTaoWeight", + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMovingAlphaPrice", "outputs": [ { "internalType": "uint256", @@ -128,20 +153,47 @@ export const IAlphaABI = [ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getRootNetuid", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "uint16", "name": "netuid", "type": "uint16" - }, + } + ], + "name": "getSubnetMechanism", + "outputs": [ { - "internalType": "uint64", - "name": "tao", - "type": "uint64" + "internalType": "uint16", + "name": "", + "type": "uint16" } ], - "name": "simSwapTaoForAlpha", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetVolume", "outputs": [ { "internalType": "uint256", @@ -158,14 +210,9 @@ export const IAlphaABI = [ "internalType": "uint16", "name": "netuid", "type": "uint16" - }, - { - "internalType": "uint64", - "name": "alpha", - "type": "uint64" } ], - "name": "simSwapAlphaForTao", + "name": "getTaoInEmission", "outputs": [ { "internalType": "uint256", @@ -184,12 +231,12 @@ export const IAlphaABI = [ "type": "uint16" } ], - "name": "getSubnetMechanism", + "name": "getTaoInPool", "outputs": [ { - "internalType": "uint16", + "internalType": "uint64", "name": "", - "type": "uint16" + "type": "uint64" } ], "stateMutability": "view", @@ -197,12 +244,12 @@ export const IAlphaABI = [ }, { "inputs": [], - "name": "getRootNetuid", + "name": "getTaoWeight", "outputs": [ { - "internalType": "uint16", + "internalType": "uint256", "name": "", - "type": "uint16" + "type": "uint256" } ], "stateMutability": "view", @@ -214,14 +261,19 @@ export const IAlphaABI = [ "internalType": "uint16", "name": "netuid", "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" } ], - "name": "getEMAPriceHalvingBlocks", + "name": "simSwapAlphaForTao", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" } ], "stateMutability": "view", @@ -233,9 +285,27 @@ export const IAlphaABI = [ "internalType": "uint16", "name": "netuid", "type": "uint16" + }, + { + "internalType": "uint64", + "name": "tao", + "type": "uint64" } ], - "name": "getSubnetVolume", + "name": "simSwapTaoForAlpha", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSumAlphaPrice", "outputs": [ { "internalType": "uint256", diff --git a/evm-tests/src/contracts/crowdloan.ts b/evm-tests/src/contracts/crowdloan.ts new file mode 100644 index 0000000000..e104c7d4bd --- /dev/null +++ b/evm-tests/src/contracts/crowdloan.ts @@ -0,0 +1,261 @@ +export const ICROWDLOAN_ADDRESS = "0x0000000000000000000000000000000000000809"; + +export const ICrowdloanABI = [ + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + } + ], + "name": "contribute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "deposit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minContribution", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cap", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "end", + "type": "uint32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "create", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "dissolve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "finalize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getContribution", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "getCrowdloan", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "creator", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "deposit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "min_contribution", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "end", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "cap", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "funds_account", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "raised", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "has_target_address", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "target_address", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "contributors_count", + "type": "uint32" + } + ], + "internalType": "struct CrowdloanInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "refund", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "newCap", + "type": "uint64" + } + ], + "name": "updateCap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "newEnd", + "type": "uint32" + } + ], + "name": "updateEnd", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "newMinContribution", + "type": "uint64" + } + ], + "name": "updateMinContribution", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/evm-tests/src/contracts/staking.ts b/evm-tests/src/contracts/staking.ts index 55c3ed33e6..7b9e671c23 100644 --- a/evm-tests/src/contracts/staking.ts +++ b/evm-tests/src/contracts/staking.ts @@ -252,6 +252,19 @@ export const IStakingV2ABI = [ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getNominatorMinRequiredStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/evm-tests/src/substrate.ts b/evm-tests/src/substrate.ts index bd6d725d48..2970d9d4bb 100644 --- a/evm-tests/src/substrate.ts +++ b/evm-tests/src/substrate.ts @@ -124,25 +124,25 @@ export async function waitForTransactionWithRetry( api: TypedApi, tx: Transaction<{}, string, string, void>, signer: PolkadotSigner, - ) { +) { let success = false; let retries = 0; - + // set max retries times while (!success && retries < 5) { - await waitForTransactionCompletion(api, tx, signer) - .then(() => {success = true}) - .catch((error) => { - console.log(`transaction error ${error}`); - }); - await new Promise((resolve) => setTimeout(resolve, 1000)); - retries += 1; + await waitForTransactionCompletion(api, tx, signer) + .then(() => { success = true }) + .catch((error) => { + console.log(`transaction error ${error}`); + }); + await new Promise((resolve) => setTimeout(resolve, 1000)); + retries += 1; } - + if (!success) { - console.log("Transaction failed after 5 retries"); + console.log("Transaction failed after 5 retries"); } - } +} export async function waitForTransactionCompletion(api: TypedApi, tx: Transaction<{}, string, string, void>, signer: PolkadotSigner,) { const transactionPromise = await getTransactionWatchPromise(tx, signer) @@ -201,44 +201,6 @@ export async function getTransactionWatchPromise(tx: Transaction<{}, string, str }); } -export async function waitForFinalizedBlock(api: TypedApi) { - const currentBlockNumber = await api.query.System.Number.getValue() - return new Promise((resolve, reject) => { - - const subscription = api.query.System.Number.watchValue().subscribe({ - // TODO check why the block number event just get once - next(value: number) { - console.log("Event block number is :", value); - - if (value > currentBlockNumber + 6) { - console.log("Transaction is finalized in block:", value); - subscription.unsubscribe(); - - resolve(); - - } - - }, - error(err: Error) { - console.error("Transaction failed:", err); - subscription.unsubscribe(); - // Reject the promise in case of an error - reject(err); - - }, - complete() { - console.log("Subscription complete"); - } - }); - - setTimeout(() => { - subscription.unsubscribe(); - console.log('unsubscribed!'); - resolve() - }, 2000); - }); -} - // second solution to wait for transaction finalization. pass the raw data to avoid the complex transaction type definition export async function waitForTransactionCompletion2(api: TypedApi, raw: Binary, signer: PolkadotSigner,) { const tx = await api.txFromCallData(raw); @@ -281,14 +243,13 @@ export async function waitForNonceChange(api: TypedApi, ss58Addre } } - -// other approach to convert public key to ss58 -// export function convertPublicKeyToSs58(publicKey: Uint8Array, ss58Format: number = 42): string { -// // Create a keyring instance -// const keyring = new Keyring({ type: 'sr25519', ss58Format }); - -// // Add the public key to the keyring -// const address = keyring.encodeAddress(publicKey); - -// return address -// } \ No newline at end of file +export function waitForFinalizedBlock(api: TypedApi, end: number) { + return new Promise((resolve) => { + const subscription = api.query.System.Number.watchValue("finalized").subscribe((current) => { + if (current > end) { + subscription.unsubscribe(); + resolve(); + } + }) + }) +} \ No newline at end of file diff --git a/evm-tests/src/subtensor.ts b/evm-tests/src/subtensor.ts index e3d5526268..5c886514ae 100644 --- a/evm-tests/src/subtensor.ts +++ b/evm-tests/src/subtensor.ts @@ -351,4 +351,39 @@ export async function setMaxChildkeyTake(api: TypedApi, take: num const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) await waitForTransactionWithRetry(api, tx, alice) +} + +// Swap coldkey to contract address +export async function swapColdkey( + api: TypedApi, + coldkey: KeyPair, + contractAddress: string, +) { + const alice = getAliceSigner(); + const internal_tx = api.tx.SubtensorModule.swap_coldkey({ + old_coldkey: convertPublicKeyToSs58(coldkey.publicKey), + new_coldkey: convertH160ToSS58(contractAddress), + swap_cost: tao(10), + }); + const tx = api.tx.Sudo.sudo({ + call: internal_tx.decodedCall, + }); + await waitForTransactionWithRetry(api, tx, alice); +} + +// Set target registrations per interval to 1000 +export async function setTargetRegistrationsPerInterval( + api: TypedApi, + netuid: number, +) { + const alice = getAliceSigner(); + const internal_tx = api.tx.AdminUtils + .sudo_set_target_registrations_per_interval({ + netuid, + target_registrations_per_interval: 1000, + }); + const tx = api.tx.Sudo.sudo({ + call: internal_tx.decodedCall, + }); + await waitForTransactionWithRetry(api, tx, alice); } \ No newline at end of file diff --git a/evm-tests/test/alpha.precompile.test.ts b/evm-tests/test/alpha.precompile.test.ts index 85161aae92..31b31da135 100644 --- a/evm-tests/test/alpha.precompile.test.ts +++ b/evm-tests/test/alpha.precompile.test.ts @@ -118,6 +118,43 @@ describe("Test Alpha Precompile", () => { // Both should be defined and valid assert.ok(alphaPrice !== undefined && movingAlphaPrice !== undefined); }); + + it("Tao in / Alpha in / Alpha out are consistent for same subnet", async () => { + const taoInEmission = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getTaoInEmission", + args: [subnetId] + }) + + const alphaInEmission = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaInEmission", + args: [subnetId] + }) + + const alphaOutEmission = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getAlphaOutEmission", + args: [subnetId] + }) + + // all should be defined and valid + assert.ok(taoInEmission !== undefined && alphaInEmission !== undefined && alphaOutEmission !== undefined); + }); + + it("getSumAlphaPrice returns valid sum of alpha prices", async () => { + const sumAlphaPrice = await publicClient.readContract({ + abi: IAlphaABI, + address: toViemAddress(IALPHA_ADDRESS), + functionName: "getSumAlphaPrice", + args: [] + }) + + assert.ok(sumAlphaPrice !== undefined, "Sum alpha price should be defined"); + }) }); describe("Pool Data Functions", () => { diff --git a/evm-tests/test/crowdloan.precompile.test.ts b/evm-tests/test/crowdloan.precompile.test.ts new file mode 100644 index 0000000000..7abd54d617 --- /dev/null +++ b/evm-tests/test/crowdloan.precompile.test.ts @@ -0,0 +1,455 @@ +import { PublicClient } from "viem"; +import { ETH_LOCAL_URL } from "../src/config"; +import { generateRandomEthersWallet, getPublicClient } from "../src/utils"; +import { ethers } from "ethers"; +import { ICROWDLOAN_ADDRESS, ICrowdloanABI } from "../src/contracts/crowdloan"; +import { Binary, TypedApi } from "polkadot-api"; +import { devnet } from "@polkadot-api/descriptors"; +import { getAliceSigner, getDevnetApi, waitForFinalizedBlock } from "../src/substrate"; +import { forceSetBalanceToEthAddress } from "../src/subtensor"; +import { decodeAddress } from "@polkadot/util-crypto"; +import { u8aToHex } from "@polkadot/util"; +import { assert } from "chai"; +import { convertH160ToSS58 } from "../src/address-utils"; + +describe("Test Crowdloan precompile", () => { + let publicClient: PublicClient; + let api: TypedApi + + const alice = getAliceSigner(); + const wallet1 = generateRandomEthersWallet(); + const wallet2 = generateRandomEthersWallet(); + const wallet3 = generateRandomEthersWallet(); + const wallet4 = generateRandomEthersWallet(); + + const crowdloanContract = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet1); + + before(async () => { + publicClient = await getPublicClient(ETH_LOCAL_URL) + api = await getDevnetApi() + + await forceSetBalanceToEthAddress(api, wallet1.address) + await forceSetBalanceToEthAddress(api, wallet2.address) + await forceSetBalanceToEthAddress(api, wallet3.address) + await forceSetBalanceToEthAddress(api, wallet4.address) + }) + + it("gets an existing crowdloan created on substrate side", async () => { + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + await api.tx.Crowdloan.create({ + deposit: BigInt(15_000_000_000), // 15 TAO + min_contribution: BigInt(1_000_000_000), // 1 TAO + cap: BigInt(100_000_000_000), // 100 TAO + end: 1000, + target_address: undefined, + call: api.tx.System.remark({ remark: Binary.fromText("foo") }).decodedCall + }).signAndSubmit(alice); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + const crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + + assert.isDefined(crowdloan); + assert.equal(crowdloanInfo[0], u8aToHex(decodeAddress(crowdloan.creator))); + assert.equal(crowdloanInfo[1], crowdloan.deposit); + assert.equal(crowdloanInfo[2], crowdloan.min_contribution); + assert.equal(crowdloanInfo[3], crowdloan.end); + assert.equal(crowdloanInfo[4], crowdloan.cap); + assert.equal(crowdloanInfo[5], u8aToHex(decodeAddress(crowdloan.funds_account))); + assert.equal(crowdloanInfo[6], crowdloan.raised); + assert.equal(crowdloanInfo[7], false); // has_target_address + assert.equal(crowdloanInfo[8], u8aToHex(Uint8Array.from(Array(32).fill(0)))); // target_address + assert.equal(crowdloanInfo[9], false); // finalized + assert.equal(crowdloanInfo[10], 1); // contributors_count + }); + + it("creates a new crowdloan and retrieves it", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(2_000_000_000); // 2 TAO + const cap = BigInt(200_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + const tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait(); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.creator, convertH160ToSS58(wallet1.address)); + assert.equal(crowdloan.deposit, deposit); + assert.equal(crowdloan.min_contribution, minContribution); + assert.equal(crowdloan.cap, cap); + assert.equal(crowdloan.end, end); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.target_address, convertH160ToSS58(targetAddress.address)); + assert.equal(crowdloan.finalized, false); + assert.equal(crowdloan.contributors_count, 1); + + const crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[0], u8aToHex(decodeAddress(crowdloan.creator))); + assert.equal(crowdloanInfo[1], crowdloan.deposit); + assert.equal(crowdloanInfo[2], crowdloan.min_contribution); + assert.equal(crowdloanInfo[3], crowdloan.end); + assert.equal(crowdloanInfo[4], crowdloan.cap); + assert.equal(crowdloanInfo[5], u8aToHex(decodeAddress(crowdloan.funds_account))); + assert.equal(crowdloanInfo[6], crowdloan.raised); + assert.equal(crowdloanInfo[7], true); // has_target_address + assert.equal(crowdloanInfo[8], u8aToHex(decodeAddress(crowdloan.target_address))); // target_address + assert.equal(crowdloanInfo[9], crowdloan.finalized); + assert.equal(crowdloanInfo[10], crowdloan.contributors_count); + }); + + it("contributes/withdraws to a crowdloan created on substrate side", async () => { + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + const deposit = BigInt(15_000_000_000); // 15 TAO + + await api.tx.Crowdloan.create({ + deposit, + min_contribution: BigInt(1_000_000_000), // 1 TAO + cap: BigInt(100_000_000_000), // 100 TAO + end: 1000, + target_address: undefined, + call: api.tx.System.remark({ remark: Binary.fromText("foo") }).decodedCall + }).signAndSubmit(alice); + + let crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.contributors_count, 1); + + let crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit); + assert.equal(crowdloanInfo[10], 1); + + let balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + + const contribution = BigInt(5_000_000_000); + const tx = await crowdloanContract.contribute(nextId, contribution); + await tx.wait(); + + let balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + assert.approximately(Number(balanceBefore.data.free - balanceAfter.data.free), Number(contribution), 1_000_000); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit + contribution); + assert.equal(crowdloan.contributors_count, 2); + + crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit + contribution); + assert.equal(crowdloanInfo[10], 2); + + balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + + const tx2 = await crowdloanContract.withdraw(nextId); + await tx2.wait(); + + balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + assert.approximately(Number(balanceAfter.data.free), Number(balanceBefore.data.free + contribution), 1_000_000); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.contributors_count, 1); + + crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit); + assert.equal(crowdloanInfo[10], 1); + }); + + it("contributes/withdraws to a crowdloan", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(2_000_000_000); // 2 TAO + const cap = BigInt(200_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + let balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + + let tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait(); + + let balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + assert.approximately(Number(balanceBefore.data.free - balanceAfter.data.free), Number(deposit), 1_000_000); + + let crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.contributors_count, 1); + + let crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit); + assert.equal(crowdloanInfo[10], 1); + + balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + + const contribution = BigInt(3_000_000_000); + const crowdloanContract2 = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet2); + tx = await crowdloanContract2.contribute(nextId, contribution); + await tx.wait(); + + balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + assert.approximately(Number(balanceBefore.data.free - balanceAfter.data.free), Number(contribution), 1_000_000); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit + contribution); + assert.equal(crowdloan.contributors_count, 2); + + crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit + contribution); + assert.equal(crowdloanInfo[10], 2); + + balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + + const tx2 = await crowdloanContract2.withdraw(nextId); + await tx2.wait(); + + balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + assert.approximately(Number(balanceAfter.data.free), Number(balanceBefore.data.free + contribution), 1_000_000); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.contributors_count, 1); + + crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit); + assert.equal(crowdloanInfo[10], 1); + }); + + it("finalizes a crowdloan", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(2_000_000_000); // 2 TAO + const cap = BigInt(100_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const balanceBefore = await api.query.System.Account.getValue(convertH160ToSS58(targetAddress.address)); + assert.equal(balanceBefore.data.free, BigInt(0)); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + let tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait() + + const contribution = cap - deposit; + const crowdloanContract2 = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet2); + tx = await crowdloanContract2.contribute(nextId, contribution); + await tx.wait(); + + await waitForFinalizedBlock(api, end); + + tx = await crowdloanContract.finalize(nextId); + await tx.wait(); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.isTrue(crowdloan.finalized); + + const crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.isTrue(crowdloanInfo[9]); + + const balanceAfter = await api.query.System.Account.getValue(convertH160ToSS58(targetAddress.address)); + assert.equal(balanceAfter.data.free, cap); + }); + + it("refunds/dissolves a crowdloan", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(2_000_000_000); // 2 TAO + const cap = BigInt(100_000_000_000); // 100 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + const balanceBefore1 = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + let tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait() + + const balanceBefore2 = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + const contribution = BigInt(20_000_000_000); // 20 TAO + const crowdloanContract2 = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet2); + tx = await crowdloanContract2.contribute(nextId, contribution); + await tx.wait(); + + const balanceBefore3 = await api.query.System.Account.getValue(convertH160ToSS58(wallet3.address)); + const crowdloanContract3 = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet3); + tx = await crowdloanContract3.contribute(nextId, contribution); + await tx.wait(); + + const balanceBefore4 = await api.query.System.Account.getValue(convertH160ToSS58(wallet4.address)); + const crowdloanContract4 = new ethers.Contract(ICROWDLOAN_ADDRESS, ICrowdloanABI, wallet4); + tx = await crowdloanContract4.contribute(nextId, contribution); + await tx.wait(); + + await waitForFinalizedBlock(api, end); + + let crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit + contribution * BigInt(3)); + assert.equal(crowdloan.contributors_count, 4); + + let crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit + contribution * BigInt(3)); + assert.equal(crowdloanInfo[10], 4); + + tx = await crowdloanContract.refund(nextId); + await tx.wait(); + + const balanceAfter2 = await api.query.System.Account.getValue(convertH160ToSS58(wallet2.address)); + assert.approximately(Number(balanceAfter2.data.free), Number(balanceBefore2.data.free), 1_000_000); + const balanceAfter3 = await api.query.System.Account.getValue(convertH160ToSS58(wallet3.address)); + assert.approximately(Number(balanceAfter3.data.free), Number(balanceBefore3.data.free), 1_000_000); + const balanceAfter4 = await api.query.System.Account.getValue(convertH160ToSS58(wallet4.address)); + assert.approximately(Number(balanceAfter4.data.free), Number(balanceBefore4.data.free), 1_000_000); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.raised, deposit); + assert.equal(crowdloan.contributors_count, 1); + + crowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(crowdloanInfo[6], deposit); + assert.equal(crowdloanInfo[10], 1); + + tx = await crowdloanContract.dissolve(nextId); + await tx.wait(); + + crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isUndefined(crowdloan); + + const balanceAfter1 = await api.query.System.Account.getValue(convertH160ToSS58(wallet1.address)); + assert.approximately(Number(balanceAfter1.data.free), Number(balanceBefore1.data.free), 2_000_000); + }); + + it("updates the min contribution", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(1_000_000_000); // 1 TAO + const cap = BigInt(200_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + let tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait(); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.min_contribution, BigInt(1_000_000_000)); + + const newMinContribution = BigInt(2_000_000_000); + tx = await crowdloanContract.updateMinContribution(nextId, newMinContribution); + await tx.wait(); + + const updatedCrowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(updatedCrowdloan); + assert.equal(updatedCrowdloan.min_contribution, newMinContribution); + + const updatedCrowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(updatedCrowdloanInfo[2], newMinContribution); + }); + + it("updates the end", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(1_000_000_000); // 1 TAO + const cap = BigInt(200_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + const tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait(); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.end, end); + + const newEnd = end + 200; + const tx2 = await crowdloanContract.updateEnd(nextId, newEnd); + await tx2.wait(); + + const updatedCrowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(updatedCrowdloan); + assert.equal(updatedCrowdloan.end, newEnd); + + const updatedCrowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(updatedCrowdloanInfo[3], newEnd); + }); + + it("updates the cap", async () => { + const deposit = BigInt(20_000_000_000); // 20 TAO + const minContribution = BigInt(1_000_000_000); // 1 TAO + const cap = BigInt(200_000_000_000); // 200 TAO + const end = await api.query.System.Number.getValue() + 100; + const targetAddress = generateRandomEthersWallet(); + + const nextId = await api.query.Crowdloan.NextCrowdloanId.getValue(); + + const tx = await crowdloanContract.create( + deposit, + minContribution, + cap, + end, + targetAddress + ); + await tx.wait(); + + const crowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(crowdloan); + assert.equal(crowdloan.cap, BigInt(200_000_000_000)); + + const newCap = BigInt(300_000_000_000); + const tx2 = await crowdloanContract.updateCap(nextId, newCap); + await tx2.wait(); + + const updatedCrowdloan = await api.query.Crowdloan.Crowdloans.getValue(nextId); + assert.isDefined(updatedCrowdloan); + assert.equal(updatedCrowdloan.cap, newCap); + + const updatedCrowdloanInfo = await crowdloanContract.getCrowdloan(nextId); + assert.equal(updatedCrowdloanInfo[4], newCap); + }); +}); \ No newline at end of file diff --git a/evm-tests/test/staking.precompile.stake-get.test.ts b/evm-tests/test/staking.precompile.stake-get.test.ts index 460aeabf32..d9cc79aeab 100644 --- a/evm-tests/test/staking.precompile.stake-get.test.ts +++ b/evm-tests/test/staking.precompile.stake-get.test.ts @@ -57,4 +57,19 @@ describe("Test staking precompile get methods", () => { assert.ok(alpha > 0) }) + + it("Get nominator min required stake", async () => { + const contract = new ethers.Contract( + ISTAKING_V2_ADDRESS, + IStakingV2ABI, + wallet1 + ); + + const stake = await contract.getNominatorMinRequiredStake() + const stakeOnChain = await api.query.SubtensorModule.NominatorMinRequiredStake.getValue() + + assert.ok(stake !== undefined) + assert.equal(stake.toString(), stakeOnChain.toString()) + + }) }) diff --git a/evm-tests/test/subnet.precompile.hyperparameter.test.ts b/evm-tests/test/subnet.precompile.hyperparameter.test.ts index bc95ca0716..b8a6f19075 100644 --- a/evm-tests/test/subnet.precompile.hyperparameter.test.ts +++ b/evm-tests/test/subnet.precompile.hyperparameter.test.ts @@ -56,27 +56,28 @@ describe("Test the Subnet precompile contract", () => { const totalNetworkAfterAdd = await api.query.SubtensorModule.TotalNetworks.getValue() assert.ok(totalNetwork + 1 === totalNetworkAfterAdd) }); - - it.only("Can register network with identity info and logo url", async () => { - const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() - const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); - const tx = await contract["registerNetwork(bytes32,string,string,string,string,string,string,string,string)"]( - hotkey2.publicKey, - "name", - "repo", - "contact", - "subnetUrl", - "discord", - "description", - "logoUrl", - "additional" - ); - await tx.wait(); + // it.only("Can register network with identity info and logo url", async () => { + // const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() - const totalNetworkAfterAdd = await api.query.SubtensorModule.TotalNetworks.getValue() - assert.ok(totalNetwork + 1 === totalNetworkAfterAdd) - }); + // const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); + + // const tx = await contract["registerNetwork(bytes32,string,string,string,string,string,string,string,string)"]( + // hotkey2.publicKey, + // "name", + // "repo", + // "contact", + // "subnetUrl", + // "discord", + // "description", + // "logoUrl", + // "additional" + // ); + // await tx.wait(); + + // const totalNetworkAfterAdd = await api.query.SubtensorModule.TotalNetworks.getValue() + // assert.ok(totalNetwork + 1 === totalNetworkAfterAdd) + // }); it("Can set servingRateLimit parameter", async () => { @@ -330,26 +331,26 @@ describe("Test the Subnet precompile contract", () => { assert.equal(valueFromContract, onchainValue); }) - it("Can set networkRegistrationAllowed parameter", async () => { + // it("Can set networkRegistrationAllowed parameter", async () => { - const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() - const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); - const netuid = totalNetwork - 1; + // const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() + // const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); + // const netuid = totalNetwork - 1; - const newValue = true; - const tx = await contract.setNetworkRegistrationAllowed(netuid, newValue); - await tx.wait(); + // const newValue = true; + // const tx = await contract.setNetworkRegistrationAllowed(netuid, newValue); + // await tx.wait(); - let onchainValue = await api.query.SubtensorModule.NetworkRegistrationAllowed.getValue(netuid) + // let onchainValue = await api.query.SubtensorModule.NetworkRegistrationAllowed.getValue(netuid) - let valueFromContract = Boolean( - await contract.getNetworkRegistrationAllowed(netuid) - ); + // let valueFromContract = Boolean( + // await contract.getNetworkRegistrationAllowed(netuid) + // ); - assert.equal(valueFromContract, newValue) - assert.equal(valueFromContract, onchainValue); - }) + // assert.equal(valueFromContract, newValue) + // assert.equal(valueFromContract, onchainValue); + // }) it("Can set networkPowRegistrationAllowed parameter", async () => { @@ -492,52 +493,51 @@ describe("Test the Subnet precompile contract", () => { assert.equal(valueFromContract, onchainValue); }) - it("Can set yuma3Enabled hyperparameter", async () => - { - const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() - const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); - const netuid = totalNetwork - 1; + it("Can set yuma3Enabled hyperparameter", async () => { + const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() + const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); + const netuid = totalNetwork - 1; - const newValue = true; - const tx = await contract.setYuma3Enabled(netuid, newValue); - await tx.wait(); + const newValue = true; + const tx = await contract.setYuma3Enabled(netuid, newValue); + await tx.wait(); - let onchainValue = await api.query.SubtensorModule.Yuma3On.getValue(netuid) + let onchainValue = await api.query.SubtensorModule.Yuma3On.getValue(netuid) - let valueFromContract = Boolean( - await contract.getYuma3Enabled(netuid) - ); - assert.equal(valueFromContract, newValue) - assert.equal(valueFromContract, onchainValue); + let valueFromContract = Boolean( + await contract.getYuma3Enabled(netuid) + ); + assert.equal(valueFromContract, newValue) + assert.equal(valueFromContract, onchainValue); }) - it("Can set alphaValues parameter", async () => { - const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() - const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); - const netuid = totalNetwork - 1; + // it("Can set alphaValues parameter", async () => { + // const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() + // const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); + // const netuid = totalNetwork - 1; - const newValue = [118, 52429]; - const tx = await contract.setAlphaValues(netuid, newValue[0], newValue[1]); - await tx.wait(); + // const newValue = [118, 52429]; + // const tx = await contract.setAlphaValues(netuid, newValue[0], newValue[1]); + // await tx.wait(); - let onchainValue = await api.query.SubtensorModule.AlphaValues.getValue(netuid) + // let onchainValue = await api.query.SubtensorModule.AlphaValues.getValue(netuid) - let value = await contract.getAlphaValues(netuid) - let valueFromContract = [Number(value[0]), Number(value[1])] + // let value = await contract.getAlphaValues(netuid) + // let valueFromContract = [Number(value[0]), Number(value[1])] - assert.equal(valueFromContract[0], newValue[0]) - assert.equal(valueFromContract[1], newValue[1]) - assert.equal(valueFromContract[0], onchainValue[0]); - assert.equal(valueFromContract[1], onchainValue[1]); - }) + // assert.equal(valueFromContract[0], newValue[0]) + // assert.equal(valueFromContract[1], newValue[1]) + // assert.equal(valueFromContract[0], onchainValue[0]); + // assert.equal(valueFromContract[1], onchainValue[1]); + // }) it("Can set commitRevealWeightsInterval parameter", async () => { const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue() const contract = new ethers.Contract(ISUBNET_ADDRESS, ISubnetABI, wallet); const netuid = totalNetwork - 1; - const newValue = 119; + const newValue = 99; const tx = await contract.setCommitRevealWeightsInterval(netuid, newValue); await tx.wait(); diff --git a/node/src/command.rs b/node/src/command.rs index fa89f71d22..f8f4990d0f 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -6,6 +6,7 @@ use crate::{ }; use fc_db::{DatabaseSource, kv::frontier_database_dir}; +use clap::{CommandFactory, FromArgMatches, parser::ValueSource}; use futures::TryFutureExt; use node_subtensor_runtime::Block; use sc_cli::SubstrateCli; @@ -55,7 +56,9 @@ impl SubstrateCli for Cli { // Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { - let cli = Cli::from_args(); + let cmd = Cli::command(); + let arg_matches = cmd.get_matches(); + let cli = Cli::from_arg_matches(&arg_matches)?; match &cli.subcommand { Some(Subcommand::Key(cmd)) => cmd.run(&cli), @@ -236,6 +239,19 @@ pub fn run() -> sc_cli::Result<()> { if cli.run.rpc_params.rpc_rate_limit.is_none() { config.rpc.rate_limit = None; } + // If the operator did **not** supply `--rpc-max-subscriptions-per-connection` set to high value. + config.rpc.max_subs_per_conn = + match arg_matches.value_source("rpc_max_subscriptions_per_connection") { + Some(ValueSource::CommandLine) => { + cli.run.rpc_params.rpc_max_subscriptions_per_connection + } + _ => 10000, + }; + // If the operator did **not** supply `--rpc-max-connections` set to high value. + config.rpc.max_connections = match arg_matches.value_source("rpc_max_connections") { + Some(ValueSource::CommandLine) => cli.run.rpc_params.rpc_max_connections, + _ => 10000, + }; service::build_full(config, cli.eth, cli.sealing) .map_err(Into::into) .await diff --git a/node/src/service.rs b/node/src/service.rs index 8edcdc0548..2dc9cbd479 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -9,6 +9,7 @@ use sc_consensus::{ }; use sc_consensus_grandpa::BlockNumberOps; use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; +use sc_network::config::SyncMode; 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}; @@ -348,6 +349,15 @@ where NumberFor: BlockNumberOps, NB: sc_network::NetworkBackend::Hash>, { + // Substrate doesn't seem to support fast sync option in our configuration. + if matches!(config.network.sync_mode, SyncMode::LightState { .. }) { + log::error!( + "Supported sync modes: full, warp. Provided: {:?}", + config.network.sync_mode + ); + return Err(ServiceError::Other("Unsupported sync mode".to_string())); + } + let build_import_queue = if sealing.is_some() { build_manual_seal_import_queue } else { diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index e78565a3a8..444d553bc4 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -107,6 +107,8 @@ pub mod pallet { BondsMovingAverageMaxReached, /// Only root can set negative sigmoid steepness values NegativeSigmoidSteepness, + /// Reveal Peroid is not within the valid range. + RevealPeriodOutOfBounds, } /// Enum for specifying the type of precompile operation. #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, Copy)] @@ -125,6 +127,8 @@ pub mod pallet { UidLookup, /// Enum for alpha precompile Alpha, + /// Enum for crowdloan precompile + Crowdloan, } #[pallet::type_value] @@ -1364,6 +1368,12 @@ pub mod pallet { Error::::SubnetDoesNotExist ); + const MAX_COMMIT_REVEAL_PEROIDS: u64 = 100; + ensure!( + interval <= MAX_COMMIT_REVEAL_PEROIDS, + Error::::RevealPeriodOutOfBounds + ); + pallet_subtensor::Pallet::::set_reveal_period(netuid, interval); log::debug!( "SetWeightCommitInterval( netuid: {:?}, interval: {:?} ) ", diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index 7aff92aa8e..51f2f7364c 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -1014,7 +1014,7 @@ mod sudo_set_nominator_min_required_stake { #[test] fn can_only_be_called_by_admin() { new_test_ext().execute_with(|| { - let to_be_set: u64 = SubtensorModule::get_nominator_min_required_stake() + 5_u64; + let to_be_set = SubtensorModule::get_nominator_min_required_stake() + 5; assert_eq!( AdminUtils::sudo_set_nominator_min_required_stake( <::RuntimeOrigin>::signed(U256::from(0)), @@ -1030,21 +1030,21 @@ mod sudo_set_nominator_min_required_stake { new_test_ext().execute_with(|| { assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake( <::RuntimeOrigin>::root(), - 10u64 + 10 )); let default_min_stake = pallet_subtensor::DefaultMinStake::::get(); assert_eq!( SubtensorModule::get_nominator_min_required_stake(), - 10_u64 * default_min_stake / 1_000_000_u64 + 10 * default_min_stake / 1_000_000 ); assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake( <::RuntimeOrigin>::root(), - 5u64 + 5 )); assert_eq!( SubtensorModule::get_nominator_min_required_stake(), - 5_u64 * default_min_stake / 1_000_000_u64 + 5 * default_min_stake / 1_000_000 ); }); } @@ -1052,7 +1052,7 @@ mod sudo_set_nominator_min_required_stake { #[test] fn sets_a_higher_value() { new_test_ext().execute_with(|| { - let to_be_set: u64 = SubtensorModule::get_nominator_min_required_stake() + 5_u64; + let to_be_set = SubtensorModule::get_nominator_min_required_stake() + 5; let default_min_stake = pallet_subtensor::DefaultMinStake::::get(); assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake( <::RuntimeOrigin>::root(), @@ -1060,7 +1060,7 @@ mod sudo_set_nominator_min_required_stake { )); assert_eq!( SubtensorModule::get_nominator_min_required_stake(), - to_be_set * default_min_stake / 1_000_000_u64 + to_be_set * default_min_stake / 1_000_000 ); }); } @@ -1456,6 +1456,16 @@ fn sudo_set_commit_reveal_weights_interval() { let netuid = NetUid::from(1); add_network(netuid, 10); + let too_high = 101; + assert_err!( + AdminUtils::sudo_set_commit_reveal_weights_interval( + <::RuntimeOrigin>::root(), + netuid, + too_high + ), + Error::::RevealPeriodOutOfBounds + ); + let to_be_set = 55; let init_value = SubtensorModule::get_reveal_period(netuid); @@ -1619,9 +1629,9 @@ fn test_sets_a_lower_value_clears_small_nominations() { let owner_coldkey: U256 = U256::from(1); let staker_coldkey: U256 = U256::from(2); - let initial_nominator_min_required_stake = 10u64; - let nominator_min_required_stake_0 = 5u64; - let nominator_min_required_stake_1 = 20u64; + let initial_nominator_min_required_stake = 10; + let nominator_min_required_stake_0 = 5; + let nominator_min_required_stake_1 = 20; assert!(nominator_min_required_stake_0 < nominator_min_required_stake_1); assert!(nominator_min_required_stake_0 < initial_nominator_min_required_stake); @@ -1654,7 +1664,7 @@ fn test_sets_a_lower_value_clears_small_nominations() { &hotkey, &staker_coldkey, netuid, - to_stake, + to_stake.into(), ); let default_min_stake = pallet_subtensor::DefaultMinStake::::get(); @@ -1673,7 +1683,7 @@ fn test_sets_a_lower_value_clears_small_nominations() { &hotkey, &staker_coldkey, netuid - ) > 0 + ) > 0.into() ); assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake( @@ -1692,7 +1702,7 @@ fn test_sets_a_lower_value_clears_small_nominations() { &staker_coldkey, netuid ), - 0 + 0.into() ); }); } diff --git a/pallets/subtensor/Cargo.toml b/pallets/subtensor/Cargo.toml index 5c9c5bb743..2ea43f96c1 100644 --- a/pallets/subtensor/Cargo.toml +++ b/pallets/subtensor/Cargo.toml @@ -45,7 +45,7 @@ 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 } +subtensor-runtime-common = { workspace = true, features = ["approx"] } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../collective" } pallet-drand = { path = "../drand", default-features = false } diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index e482a01251..aa85aeffa8 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -12,7 +12,7 @@ use pallet_subtensor::rpc_info::{ subnet_info::{SubnetHyperparams, SubnetHyperparamsV2, SubnetInfo, SubnetInfov2}, }; use sp_runtime::AccountId32; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; // Here we declare the runtime API. It is implemented it the `impl` block in // src/neuron_info.rs, src/subnet_info.rs, and src/delegate_info.rs @@ -20,7 +20,7 @@ sp_api::decl_runtime_apis! { pub trait DelegateInfoRuntimeApi { fn get_delegates() -> Vec>; fn get_delegate( delegate_account: AccountId32 ) -> Option>; - fn get_delegated( delegatee_account: AccountId32 ) -> Vec<(DelegateInfo, (Compact, Compact))>; + fn get_delegated( delegatee_account: AccountId32 ) -> Vec<(DelegateInfo, (Compact, Compact))>; } pub trait NeuronInfoRuntimeApi { diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 7257e9b8ea..b239adb70e 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -15,6 +15,7 @@ use sp_runtime::{ traits::{BlakeTwo256, Hash}, }; use sp_std::vec; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; #[frame_benchmarking::v2::benchmarks] mod pallet_benchmarks { @@ -582,8 +583,8 @@ mod pallet_benchmarks { hotkey.clone() )); - let alpha_amount: u64 = 1_000_000; - SubnetAlphaOut::::insert(netuid, alpha_amount * 2); + let alpha_amount = AlphaCurrency::from(1_000_000); + SubnetAlphaOut::::insert(netuid, alpha_amount * 2.into()); Subtensor::::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -592,7 +593,10 @@ mod pallet_benchmarks { alpha_amount, ); - assert_eq!(TotalHotkeyAlpha::::get(&hotkey, netuid), alpha_amount); + assert_eq!( + TotalHotkeyAlpha::::get(&hotkey, netuid), + alpha_amount.into() + ); #[extrinsic_call] _( @@ -622,21 +626,24 @@ mod pallet_benchmarks { hotkey.clone() )); - let alpha_amount: u64 = 1_000_000; - SubnetAlphaOut::::insert(netuid, alpha_amount * 2); + let alpha_amount = 1_000_000; + SubnetAlphaOut::::insert(netuid, AlphaCurrency::from(alpha_amount * 2)); Subtensor::::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, - alpha_amount, + alpha_amount.into(), + ); + assert_eq!( + TotalHotkeyAlpha::::get(&hotkey, netuid), + alpha_amount.into() ); - assert_eq!(TotalHotkeyAlpha::::get(&hotkey, netuid), alpha_amount); #[extrinsic_call] _( RawOrigin::Signed(coldkey.clone()), hotkey.clone(), - alpha_amount, + alpha_amount.into(), netuid, ); } @@ -709,7 +716,7 @@ mod pallet_benchmarks { Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount); let tao_reserve = 150_000_000_000_u64; - let alpha_in = 100_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve); SubnetAlphaIn::::insert(netuid, alpha_in); @@ -752,7 +759,7 @@ mod pallet_benchmarks { )); SubnetTAO::::insert(netuid, deposit); - SubnetAlphaIn::::insert(netuid, deposit); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(deposit)); TotalStake::::set(deposit); assert_ok!(Subtensor::::add_stake_limit( @@ -764,7 +771,7 @@ mod pallet_benchmarks { false )); - let alpha_to_move: u64 = + let alpha_to_move = Subtensor::::get_stake_for_hotkey_and_coldkey_on_subnet(&origin, &coldkey, netuid); Subtensor::::create_account_if_non_existent(&coldkey, &destination); @@ -805,7 +812,7 @@ mod pallet_benchmarks { let limit: u64 = 1_000_000_000; let tao_reserve = 150_000_000_000_u64; - let alpha_in = 100_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve); SubnetAlphaIn::::insert(netuid, alpha_in); @@ -828,7 +835,7 @@ mod pallet_benchmarks { u64_staked_amt )); - let amount_unstaked: u64 = 30_000_000_000; + let amount_unstaked = AlphaCurrency::from(30_000_000_000); // Remove stake limit for benchmark StakingOperationRateLimiter::::remove((hotkey.clone(), coldkey.clone(), netuid)); @@ -858,7 +865,7 @@ mod pallet_benchmarks { Subtensor::::init_new_network(netuid2, 1); let tao_reserve = 150_000_000_000_u64; - let alpha_in = 100_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid1, tao_reserve); SubnetAlphaIn::::insert(netuid1, alpha_in); SubnetTAO::::insert(netuid2, tao_reserve); @@ -869,7 +876,7 @@ mod pallet_benchmarks { let limit_stake: u64 = 6_000_000_000; let limit_swap: u64 = 1_000_000_000; let amount_to_be_staked = 440_000_000_000; - let amount_swapped: u64 = 30_000_000_000; + let amount_swapped = AlphaCurrency::from(30_000_000_000); Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount); assert_ok!(Subtensor::::burned_register( @@ -930,7 +937,7 @@ mod pallet_benchmarks { )); SubnetTAO::::insert(netuid, deposit); - SubnetAlphaIn::::insert(netuid, deposit); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(deposit)); TotalStake::::set(deposit); assert_ok!(Subtensor::::add_stake_limit( @@ -942,7 +949,7 @@ mod pallet_benchmarks { false )); - let alpha_to_transfer: u64 = + let alpha_to_transfer = Subtensor::::get_stake_for_hotkey_and_coldkey_on_subnet(&hot, &coldkey, netuid); Subtensor::::create_account_if_non_existent(&dest, &hot); @@ -985,9 +992,9 @@ mod pallet_benchmarks { )); SubnetTAO::::insert(netuid1, deposit); - SubnetAlphaIn::::insert(netuid1, deposit); + SubnetAlphaIn::::insert(netuid1, AlphaCurrency::from(deposit)); SubnetTAO::::insert(netuid2, deposit); - SubnetAlphaIn::::insert(netuid2, deposit); + SubnetAlphaIn::::insert(netuid2, AlphaCurrency::from(deposit)); TotalStake::::set(deposit); assert_ok!(Subtensor::::add_stake_limit( @@ -999,7 +1006,7 @@ mod pallet_benchmarks { false )); - let alpha_to_swap: u64 = + let alpha_to_swap = Subtensor::::get_stake_for_hotkey_and_coldkey_on_subnet(&hot, &coldkey, netuid1); // Remove stake limit for benchmark @@ -1347,7 +1354,7 @@ mod pallet_benchmarks { Subtensor::::set_burn(netuid, 1); SubnetTAO::::insert(netuid, 150_000_000_000); - SubnetAlphaIn::::insert(netuid, 100_000_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(100_000_000_000)); Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 1000000u32.into()); @@ -1396,7 +1403,7 @@ mod pallet_benchmarks { let limit: u64 = 1_000_000_000; let tao_reserve = 150_000_000_000_u64; - let alpha_in = 100_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve); SubnetAlphaIn::::insert(netuid, alpha_in); diff --git a/pallets/subtensor/src/coinbase/reveal_commits.rs b/pallets/subtensor/src/coinbase/reveal_commits.rs index 1fc9f49493..9318321633 100644 --- a/pallets/subtensor/src/coinbase/reveal_commits.rs +++ b/pallets/subtensor/src/coinbase/reveal_commits.rs @@ -34,9 +34,9 @@ impl Pallet { cur_epoch.saturating_sub(Self::get_reveal_period(netuid).saturating_sub(1)); // Clean expired commits - for (epoch, _) in CRV3WeightCommits::::iter_prefix(netuid) { + for (epoch, _) in CRV3WeightCommitsV2::::iter_prefix(netuid) { if epoch < reveal_epoch { - CRV3WeightCommits::::remove(netuid, epoch); + CRV3WeightCommitsV2::::remove(netuid, epoch); } } @@ -46,10 +46,12 @@ impl Pallet { return Ok(()); } - let mut entries = CRV3WeightCommits::::take(netuid, reveal_epoch); + let mut entries = CRV3WeightCommitsV2::::take(netuid, reveal_epoch); // Keep popping item off the end of the queue until we sucessfully reveal a commit. - while let Some((who, serialized_compresssed_commit, round_number)) = entries.pop_front() { + while let Some((who, _commit_block, serialized_compresssed_commit, round_number)) = + entries.pop_front() + { let reader = &mut &serialized_compresssed_commit[..]; let commit = match TLECiphertext::::deserialize_compressed(reader) { Ok(c) => c, diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index add7ae3d8f..279132e938 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -22,7 +22,7 @@ use frame_support::weights::Weight; use safe_math::*; use sp_core::Get; use substrate_fixed::types::I64F64; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; impl Pallet { /// Fetches the total count of root network validators @@ -139,7 +139,7 @@ impl Pallet { } else { // --- 13.1.1 The network is full. Perform replacement. // Find the neuron with the lowest stake value to replace. - let mut lowest_stake: u64 = u64::MAX; + let mut lowest_stake = AlphaCurrency::MAX; let mut lowest_uid: u16 = 0; // Iterate over all keys in the root network to find the neuron with the lowest stake. diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index f4954df971..aaccb1f749 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -2,7 +2,7 @@ use super::*; use alloc::collections::BTreeMap; use safe_math::*; use substrate_fixed::types::U96F32; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; use subtensor_swap_interface::SwapHandler; // Distribute dividends to each hotkey @@ -69,7 +69,7 @@ impl Pallet { log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total let alpha_emission_i: U96F32 = asfloat!( - Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)) + Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i).into()) .unwrap_or(0) ); log::debug!("alpha_emission_i: {:?}", alpha_emission_i); @@ -101,13 +101,15 @@ impl Pallet { // This operation changes the pool liquidity each block. for netuid_i in subnets_to_emit_to.iter() { // Inject Alpha in. - let alpha_in_i: u64 = tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0))); + let alpha_in_i: AlphaCurrency = + tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0))).into(); SubnetAlphaInEmission::::insert(*netuid_i, alpha_in_i); SubnetAlphaIn::::mutate(*netuid_i, |total| { *total = total.saturating_add(alpha_in_i); }); // Injection Alpha out. - let alpha_out_i: u64 = tou64!(*alpha_out.get(netuid_i).unwrap_or(&asfloat!(0))); + let alpha_out_i: AlphaCurrency = + tou64!(*alpha_out.get(netuid_i).unwrap_or(&asfloat!(0))).into(); SubnetAlphaOutEmission::::insert(*netuid_i, alpha_out_i); SubnetAlphaOut::::mutate(*netuid_i, |total| { *total = total.saturating_add(alpha_out_i); @@ -146,7 +148,7 @@ impl Pallet { alpha_out.insert(*netuid_i, alpha_out_i.saturating_sub(owner_cut_i)); // Accumulate the owner cut in pending. PendingOwnerCut::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(owner_cut_i)); + *total = total.saturating_add(tou64!(owner_cut_i).into()); }); } @@ -182,7 +184,7 @@ impl Pallet { // Sell root emission through the pool (do not pay fees) let swap_result = Self::swap_alpha_for_tao( *netuid_i, - tou64!(root_alpha), + tou64!(root_alpha).into(), T::SwapInterface::min_price(), true, ); @@ -192,11 +194,11 @@ impl Pallet { log::debug!("root_tao: {:?}", root_tao); // Accumulate alpha emission in pending. PendingAlphaSwapped::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(root_alpha)); + *total = total.saturating_add(tou64!(root_alpha).into()); }); // Accumulate alpha emission in pending. PendingEmission::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(pending_alpha)); + *total = total.saturating_add(tou64!(pending_alpha).into()); }); // Accumulate root divs for subnet. PendingRootDivs::::mutate(*netuid_i, |total| { @@ -230,20 +232,20 @@ impl Pallet { LastMechansimStepBlock::::insert(netuid, current_block); // Get and drain the subnet pending emission. - let pending_alpha: u64 = PendingEmission::::get(netuid); - PendingEmission::::insert(netuid, 0); + let pending_alpha = PendingEmission::::get(netuid); + PendingEmission::::insert(netuid, AlphaCurrency::ZERO); // Get and drain the subnet pending root divs. let pending_tao: u64 = PendingRootDivs::::get(netuid); PendingRootDivs::::insert(netuid, 0); // Get this amount as alpha that was swapped for pending root divs. - let pending_swapped: u64 = PendingAlphaSwapped::::get(netuid); - PendingAlphaSwapped::::insert(netuid, 0); + let pending_swapped = PendingAlphaSwapped::::get(netuid); + PendingAlphaSwapped::::insert(netuid, AlphaCurrency::ZERO); // Get owner cut and drain. - let owner_cut: u64 = PendingOwnerCut::::get(netuid); - PendingOwnerCut::::insert(netuid, 0); + let owner_cut = PendingOwnerCut::::get(netuid); + PendingOwnerCut::::insert(netuid, AlphaCurrency::ZERO); // Drain pending root divs, alpha emission, and owner cut. Self::drain_pending_emission( @@ -262,10 +264,13 @@ impl Pallet { pub fn calculate_dividends_and_incentives( netuid: NetUid, - hotkey_emission: Vec<(T::AccountId, u64, u64)>, - ) -> (BTreeMap, BTreeMap) { + hotkey_emission: Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)>, + ) -> ( + BTreeMap, + BTreeMap, + ) { // Accumulate emission of dividends and incentive per hotkey. - let mut incentives: BTreeMap = BTreeMap::new(); + let mut incentives: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); for (hotkey, incentive, dividend) in hotkey_emission { // Accumulate incentives to miners. @@ -274,7 +279,7 @@ impl Pallet { .and_modify(|e| *e = e.saturating_add(incentive)) .or_insert(incentive); // Accumulate dividends to parents. - let div_tuples: Vec<(T::AccountId, u64)> = + let div_tuples: Vec<(T::AccountId, AlphaCurrency)> = Self::get_parent_child_dividends_distribution(&hotkey, netuid, dividend); // Accumulate dividends per hotkey. for (parent, parent_div) in div_tuples { @@ -291,10 +296,10 @@ impl Pallet { } pub fn calculate_dividend_distribution( - pending_alpha: u64, + pending_alpha: AlphaCurrency, pending_tao: u64, tao_weight: U96F32, - stake_map: BTreeMap, + stake_map: BTreeMap, dividends: BTreeMap, ) -> ( BTreeMap, @@ -316,22 +321,24 @@ impl Pallet { let mut root_dividends: BTreeMap = BTreeMap::new(); let mut alpha_dividends: BTreeMap = BTreeMap::new(); for (hotkey, dividend) in dividends { - if let Some((alpha_stake_u64, root_stake_u64)) = stake_map.get(&hotkey) { + if let Some((alpha_stake, root_stake)) = stake_map.get(&hotkey) { + let alpha_stake = alpha_stake.to_u64(); + let root_stake = root_stake.to_u64(); // Get hotkey ALPHA on subnet. - let alpha_stake: U96F32 = asfloat!(*alpha_stake_u64); + let alpha_stake = asfloat!(alpha_stake); // Get hotkey TAO on root. - let root_stake: U96F32 = asfloat!(*root_stake_u64); + let root_stake = asfloat!(root_stake); // Convert TAO to alpha with weight. - let root_alpha: U96F32 = root_stake.saturating_mul(tao_weight); + let root_alpha = root_stake.saturating_mul(tao_weight); // Get total from root and local - let total_alpha: U96F32 = alpha_stake.saturating_add(root_alpha); + let total_alpha = alpha_stake.saturating_add(root_alpha); // Compute root prop. - let root_prop: U96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); + let root_prop = root_alpha.checked_div(total_alpha).unwrap_or(zero); // Compute root dividends - let root_divs: U96F32 = dividend.saturating_mul(root_prop); + let root_divs = dividend.saturating_mul(root_prop); // Compute alpha dividends - let alpha_divs: U96F32 = dividend.saturating_sub(root_divs); + let alpha_divs = dividend.saturating_sub(root_divs); // Record the alpha dividends. alpha_dividends .entry(hotkey.clone()) @@ -378,7 +385,7 @@ impl Pallet { log::debug!("hotkey: {:?}, alpha_share: {:?}", hotkey, alpha_share); // Compute the proportional pending_alpha to this hotkey. - let prop_alpha: U96F32 = asfloat!(pending_alpha).saturating_mul(alpha_share); + let prop_alpha = asfloat!(pending_alpha).saturating_mul(alpha_share); log::debug!("hotkey: {:?}, prop_alpha: {:?}", hotkey, prop_alpha); // Record the proportional alpha dividends. prop_alpha_dividends @@ -393,8 +400,8 @@ impl Pallet { pub fn distribute_dividends_and_incentives( netuid: NetUid, - owner_cut: u64, - incentives: BTreeMap, + owner_cut: AlphaCurrency, + incentives: BTreeMap, alpha_dividends: BTreeMap, tao_dividends: BTreeMap, ) { @@ -458,14 +465,14 @@ impl Pallet { &hotkey, &Owner::::get(&hotkey), netuid, - tou64!(alpha_take), + tou64!(alpha_take).into(), ); // Give all other nominators. log::debug!("hotkey: {:?} alpha_divs: {:?}", hotkey, alpha_divs); - Self::increase_stake_for_hotkey_on_subnet(&hotkey, netuid, tou64!(alpha_divs)); + Self::increase_stake_for_hotkey_on_subnet(&hotkey, netuid, tou64!(alpha_divs).into()); // Record dividends for this hotkey. AlphaDividendsPerSubnet::::mutate(netuid, &hotkey, |divs| { - *divs = divs.saturating_add(tou64!(alpha_divs)); + *divs = divs.saturating_add(tou64!(alpha_divs).into()); }); // Record total hotkey alpha based on which this value of AlphaDividendsPerSubnet // was calculated @@ -486,11 +493,15 @@ impl Pallet { &hotkey, &Owner::::get(hotkey.clone()), NetUid::ROOT, - tou64!(tao_take), + tou64!(tao_take).into(), ); // Give rest to nominators. log::debug!("hotkey: {:?} root_tao: {:?}", hotkey, root_tao); - Self::increase_stake_for_hotkey_on_subnet(&hotkey, NetUid::ROOT, tou64!(root_tao)); + Self::increase_stake_for_hotkey_on_subnet( + &hotkey, + NetUid::ROOT, + tou64!(root_tao).into(), + ); // Record root dividends for this validator on this subnet. TaoDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { *divs = divs.saturating_add(tou64!(root_tao)); @@ -498,7 +509,7 @@ impl Pallet { // Update the total TAO on the subnet with root tao dividends. SubnetTAO::::mutate(NetUid::ROOT, |total| { *total = total - .saturating_add(validator_stake) + .saturating_add(validator_stake.to_u64()) .saturating_add(tou64!(root_tao)); }); } @@ -507,13 +518,13 @@ impl Pallet { pub fn get_stake_map( netuid: NetUid, hotkeys: Vec<&T::AccountId>, - ) -> BTreeMap { - let mut stake_map: BTreeMap = BTreeMap::new(); + ) -> BTreeMap { + let mut stake_map: BTreeMap = BTreeMap::new(); for hotkey in hotkeys { // Get hotkey ALPHA on subnet. - let alpha_stake: u64 = Self::get_stake_for_hotkey_on_subnet(hotkey, netuid); + let alpha_stake = Self::get_stake_for_hotkey_on_subnet(hotkey, netuid); // Get hotkey TAO on root. - let root_stake: u64 = Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT); + let root_stake = Self::get_stake_for_hotkey_on_subnet(hotkey, NetUid::ROOT); stake_map.insert(hotkey.clone(), (alpha_stake, root_stake)); } stake_map @@ -522,11 +533,11 @@ impl Pallet { pub fn calculate_dividend_and_incentive_distribution( netuid: NetUid, pending_tao: u64, - pending_validator_alpha: u64, - hotkey_emission: Vec<(T::AccountId, u64, u64)>, + pending_validator_alpha: AlphaCurrency, + hotkey_emission: Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)>, tao_weight: U96F32, ) -> ( - BTreeMap, + BTreeMap, ( BTreeMap, BTreeMap, @@ -535,8 +546,7 @@ impl Pallet { let (incentives, dividends) = Self::calculate_dividends_and_incentives(netuid, hotkey_emission); - let stake_map: BTreeMap = - Self::get_stake_map(netuid, dividends.keys().collect::>()); + let stake_map = Self::get_stake_map(netuid, dividends.keys().collect::>()); let (alpha_dividends, tao_dividends) = Self::calculate_dividend_distribution( pending_validator_alpha, @@ -551,10 +561,10 @@ impl Pallet { pub fn drain_pending_emission( netuid: NetUid, - pending_alpha: u64, + pending_alpha: AlphaCurrency, pending_tao: u64, - pending_swapped: u64, - owner_cut: u64, + pending_swapped: AlphaCurrency, + owner_cut: AlphaCurrency, ) { log::debug!( "Draining pending alpha emission for netuid {:?}, pending_alpha: {:?}, pending_tao: {:?}, pending_swapped: {:?}, owner_cut: {:?}", @@ -568,7 +578,7 @@ impl Pallet { let tao_weight = Self::get_tao_weight(); // Run the epoch. - let hotkey_emission: Vec<(T::AccountId, u64, u64)> = + let hotkey_emission: Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)> = Self::epoch(netuid, pending_alpha.saturating_add(pending_swapped)); log::debug!("hotkey_emission: {:?}", hotkey_emission); @@ -579,14 +589,15 @@ impl Pallet { // Important! If the incentives are 0, then Validators get 100% of the alpha. let incentive_sum = hotkey_emission .iter() - .map(|(_, incentive, _)| incentive) - .sum::(); + .fold(AlphaCurrency::default(), |acc, (_, incentive, _)| { + acc.saturating_add(*incentive) + }); log::debug!("incentive_sum: {:?}", incentive_sum); - let pending_validator_alpha: u64 = if incentive_sum != 0 { + let pending_validator_alpha = if !incentive_sum.is_zero() { pending_alpha .saturating_add(pending_swapped) - .saturating_div(2) + .saturating_div(2.into()) .saturating_sub(pending_swapped) } else { // If the incentive is 0, then Validators get 100% of the alpha. @@ -660,10 +671,10 @@ impl Pallet { pub fn get_parent_child_dividends_distribution( hotkey: &T::AccountId, netuid: NetUid, - dividends: u64, - ) -> Vec<(T::AccountId, u64)> { + dividends: AlphaCurrency, + ) -> Vec<(T::AccountId, AlphaCurrency)> { // hotkey dividends. - let mut dividend_tuples: Vec<(T::AccountId, u64)> = vec![]; + let mut dividend_tuples: Vec<(T::AccountId, AlphaCurrency)> = vec![]; // Calculate the hotkey's share of the validator emission based on its childkey take let validating_emission: U96F32 = U96F32::saturating_from_num(dividends); @@ -781,7 +792,10 @@ impl Pallet { log::debug!("remaining emission: {:?}", remaining_emission); // Add the parent's emission to the distribution list - dividend_tuples.push((parent.clone(), parent_emission.saturating_to_num::())); + dividend_tuples.push(( + parent.clone(), + parent_emission.saturating_to_num::().into(), + )); // Keep track of total emission distributed to parents to_parents = to_parents.saturating_add(parent_emission.saturating_to_num::()); @@ -799,7 +813,8 @@ impl Pallet { // This includes the take left from the parents and the self contribution. let child_emission = remaining_emission .saturating_add(total_child_emission_take) - .saturating_to_num::(); + .saturating_to_num::() + .into(); // Add the hotkey's own emission to the distribution list dividend_tuples.push((hotkey.clone(), child_emission)); diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index a636cdd9a1..c536ffff82 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -4,13 +4,16 @@ use frame_support::IterableStorageDoubleMap; use safe_math::*; use sp_std::vec; use substrate_fixed::types::{I32F32, I64F64, I96F32}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; impl Pallet { /// Calculates reward consensus and returns the emissions for uids/hotkeys in a given `netuid`. /// (Dense version used only for testing purposes.) #[allow(clippy::indexing_slicing)] - pub fn epoch_dense(netuid: NetUid, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { + pub fn epoch_dense( + netuid: NetUid, + rao_emission: AlphaCurrency, + ) -> Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)> { // Get subnetwork size. let n: u16 = Self::get_subnetwork_n(netuid); log::trace!("n: {:?}", n); @@ -314,18 +317,18 @@ impl Pallet { .iter() .map(|se: &I32F32| I96F32::saturating_from_num(*se).saturating_mul(float_rao_emission)) .collect(); - let server_emission: Vec = server_emission + let server_emission: Vec = server_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| e.saturating_to_num::().into()) .collect(); let validator_emission: Vec = normalized_validator_emission .iter() .map(|ve: &I32F32| I96F32::saturating_from_num(*ve).saturating_mul(float_rao_emission)) .collect(); - let validator_emission: Vec = validator_emission + let validator_emission: Vec = validator_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| e.saturating_to_num::().into()) .collect(); // Used only to track combined emission in the storage. @@ -333,9 +336,9 @@ impl Pallet { .iter() .map(|ce: &I32F32| I96F32::saturating_from_num(*ce).saturating_mul(float_rao_emission)) .collect(); - let combined_emission: Vec = combined_emission + let combined_emission: Vec = combined_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| AlphaCurrency::from(e.saturating_to_num::())) .collect(); log::trace!("nSE: {:?}", &normalized_server_emission); @@ -352,7 +355,7 @@ impl Pallet { // =================== // == Value storage == // =================== - let cloned_emission: Vec = combined_emission.clone(); + let cloned_emission = combined_emission.clone(); let cloned_stake_weight: Vec = stake .iter() .map(|xi| fixed_proportion_to_u16(*xi)) @@ -439,9 +442,12 @@ impl Pallet { /// - Print debugging outputs. /// #[allow(clippy::indexing_slicing)] - pub fn epoch(netuid: NetUid, rao_emission: u64) -> Vec<(T::AccountId, u64, u64)> { + pub fn epoch( + netuid: NetUid, + rao_emission: AlphaCurrency, + ) -> Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)> { // Get subnetwork size. - let n: u16 = Self::get_subnetwork_n(netuid); + let n = Self::get_subnetwork_n(netuid); log::trace!("Number of Neurons in Network: {:?}", n); // ====================== @@ -577,6 +583,53 @@ impl Pallet { ); log::trace!("Weights (permit+diag+outdate): {:?}", &weights); + if Self::get_commit_reveal_weights_enabled(netuid) { + let mut commit_blocks: Vec = vec![u64::MAX; n as usize]; // MAX ⇒ “no active commit” + + // helper: hotkey → uid + let uid_of = |acct: &T::AccountId| -> Option { + hotkeys + .iter() + .find(|(_, a)| a == acct) + .map(|(uid, _)| *uid as usize) + }; + + // ---------- v2 ------------------------------------------------------ + for (who, q) in WeightCommits::::iter_prefix(netuid) { + for (_, cb, _, _) in q.iter() { + if !Self::is_commit_expired(netuid, *cb) { + if let Some(i) = uid_of(&who) { + commit_blocks[i] = commit_blocks[i].min(*cb); + } + break; // earliest active found + } + } + } + + // ---------- v3 ------------------------------------------------------ + for (_epoch, q) in CRV3WeightCommitsV2::::iter_prefix(netuid) { + for (who, cb, ..) in q.iter() { + if !Self::is_commit_expired(netuid, *cb) { + if let Some(i) = uid_of(who) { + commit_blocks[i] = commit_blocks[i].min(*cb); + } + } + } + } + + weights = vec_mask_sparse_matrix( + &weights, + &commit_blocks, + &block_at_registration, + &|cb, reg| cb < reg, + ); + + log::trace!( + "Commit-reveal column mask applied ({} masked rows)", + commit_blocks.iter().filter(|&&cb| cb != u64::MAX).count() + ); + } + // Normalize remaining weights. inplace_row_normalize_sparse(&mut weights); log::trace!("Weights (mask+norm): {:?}", &weights); @@ -758,18 +811,18 @@ impl Pallet { .iter() .map(|se: &I32F32| I96F32::saturating_from_num(*se).saturating_mul(float_rao_emission)) .collect(); - let server_emission: Vec = server_emission + let server_emission: Vec = server_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| e.saturating_to_num::().into()) .collect(); let validator_emission: Vec = normalized_validator_emission .iter() .map(|ve: &I32F32| I96F32::saturating_from_num(*ve).saturating_mul(float_rao_emission)) .collect(); - let validator_emission: Vec = validator_emission + let validator_emission: Vec = validator_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| e.saturating_to_num::().into()) .collect(); // Only used to track emission in storage. @@ -777,9 +830,9 @@ impl Pallet { .iter() .map(|ce: &I32F32| I96F32::saturating_from_num(*ce).saturating_mul(float_rao_emission)) .collect(); - let combined_emission: Vec = combined_emission + let combined_emission: Vec = combined_emission .iter() - .map(|e: &I96F32| e.saturating_to_num::()) + .map(|e: &I96F32| AlphaCurrency::from(e.saturating_to_num::())) .collect(); log::trace!( @@ -809,7 +862,7 @@ impl Pallet { .iter() .map(|xi| fixed_proportion_to_u16(*xi)) .collect::>(); - let cloned_emission: Vec = combined_emission.clone(); + let cloned_emission = combined_emission.clone(); let cloned_ranks: Vec = ranks .iter() .map(|xi| fixed_proportion_to_u16(*xi)) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index be89a1b82c..e61aae04e5 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -32,7 +32,7 @@ use sp_runtime::{ transaction_validity::{TransactionValidity, TransactionValidityError}, }; use sp_std::marker::PhantomData; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; // ============================ // ==== Benchmark Imports ===== @@ -85,14 +85,14 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; use pallet_drand::types::RoundNumber; - use sp_core::{ConstU32, ConstU64, H160, H256}; + use sp_core::{ConstU32, H160, H256}; use sp_runtime::traits::{Dispatchable, TrailingZeroInput}; use sp_std::collections::vec_deque::VecDeque; use sp_std::vec; use sp_std::vec::Vec; use substrate_fixed::types::{I96F32, U64F64}; use subtensor_macros::freeze_struct; - use subtensor_runtime_common::NetUid; + use subtensor_runtime_common::{AlphaCurrency, NetUid}; #[cfg(not(feature = "std"))] use alloc::boxed::Box; @@ -311,6 +311,11 @@ pub mod pallet { pub fn DefaultZeroU64() -> u64 { 0 } + /// Default value for Alpha cyrrency. + #[pallet::type_value] + pub fn DefaultZeroAlpha() -> AlphaCurrency { + 0.into() + } #[pallet::type_value] /// Default value for zero. pub fn DefaultZeroU128() -> u128 { @@ -555,8 +560,8 @@ pub mod pallet { } #[pallet::type_value] /// Default value for pending emission. - pub fn DefaultPendingEmission() -> u64 { - 0 + pub fn DefaultPendingEmission() -> AlphaCurrency { + 0.into() } #[pallet::type_value] /// Default value for blocks since last step. @@ -982,9 +987,9 @@ pub mod pallet { NetUid, Blake2_128Concat, T::AccountId, - u64, + AlphaCurrency, ValueQuery, - DefaultZeroU64, + DefaultZeroAlpha, >; #[pallet::storage] // --- DMAP ( netuid, hotkey ) --> u64 | Last total root dividend paid to this hotkey on this subnet. pub type TaoDividendsPerSubnet = StorageDoubleMap< @@ -1012,9 +1017,9 @@ pub mod pallet { T::AccountId, Identity, NetUid, - u64, + AlphaCurrency, ValueQuery, - DefaultZeroU64, + DefaultZeroAlpha, >; /// ========================== @@ -1049,23 +1054,23 @@ pub mod pallet { 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>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] // --- MAP ( netuid ) --> alpha_out_emission | Returns the amount of alpha out emission into the network per block. pub type SubnetAlphaOutEmission = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] // --- MAP ( netuid ) --> tao_in_emission | Returns the amount of tao emitted into this subent on the last block. pub type SubnetTaoInEmission = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. pub type SubnetAlphaIn = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[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>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. pub type SubnetAlphaOut = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] // --- MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it pub type StakingHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; @@ -1090,9 +1095,9 @@ pub mod pallet { T::AccountId, Identity, NetUid, - u64, + AlphaCurrency, ValueQuery, - DefaultZeroU64, + DefaultZeroAlpha, >; #[pallet::storage] // --- DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owned in the last epoch. pub type TotalHotkeyAlphaLastEpoch = StorageDoubleMap< @@ -1101,9 +1106,9 @@ pub mod pallet { T::AccountId, Identity, NetUid, - u64, + AlphaCurrency, ValueQuery, - DefaultZeroU64, + DefaultZeroAlpha, >; #[pallet::storage] /// DMAP ( hot, netuid ) --> total_alpha_shares | Returns the number of alpha shares for a hotkey on a subnet. @@ -1255,7 +1260,7 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( netuid ) --> pending_emission pub type PendingEmission = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultPendingEmission>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultPendingEmission>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_root_emission pub type PendingRootDivs = @@ -1263,11 +1268,11 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( netuid ) --> pending_alpha_swapped pub type PendingAlphaSwapped = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> pending_owner_cut pub type PendingOwnerCut = - StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; + StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; #[pallet::storage] /// --- MAP ( netuid ) --> blocks_since_last_step pub type BlocksSinceLastStep = @@ -1494,8 +1499,7 @@ pub mod pallet { StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] /// --- MAP ( netuid ) --> emission - pub type Emission = - StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU64Vec>; + pub type Emission = StorageMap<_, Identity, NetUid, Vec, ValueQuery>; #[pallet::storage] /// --- MAP ( netuid ) --> last_update pub type LastUpdate = @@ -1642,13 +1646,14 @@ pub mod pallet { OptionQuery, >; #[pallet::storage] - /// --- MAP (netuid, commit_epoch) --> VecDeque<(who, serialized_compressed_commit, reveal_round)> | Stores a queue of v3 commits for an account on a given netuid. + /// MAP (netuid, epoch) → VecDeque<(who, ciphertext, reveal_round)> + /// DEPRECATED for CRV3WeightCommitsV2 pub type CRV3WeightCommits = StorageDoubleMap< _, Twox64Concat, NetUid, Twox64Concat, - u64, + u64, // epoch key VecDeque<( T::AccountId, BoundedVec>, @@ -1657,6 +1662,23 @@ pub mod pallet { ValueQuery, >; #[pallet::storage] + /// MAP (netuid, epoch) → VecDeque<(who, commit_block, ciphertext, reveal_round)> + /// Stores a queue of v3 commits for an account on a given netuid. + pub type CRV3WeightCommitsV2 = StorageDoubleMap< + _, + Twox64Concat, + NetUid, + Twox64Concat, + u64, // epoch key + VecDeque<( + T::AccountId, + u64, // commit_block + BoundedVec>, + RoundNumber, + )>, + ValueQuery, + >; + #[pallet::storage] /// --- Map (netuid) --> Number of epochs allowed for commit reveal periods pub type RevealPeriodEpochs = StorageMap<_, Twox64Concat, NetUid, u64, ValueQuery, DefaultRevealPeriodEpochs>; @@ -1720,7 +1742,7 @@ pub mod pallet { #[pallet::storage] /// --- MAP ( lease_id ) --> accumulated_dividends | The accumulated dividends for a given lease that needs to be distributed. pub type AccumulatedLeaseDividends = - StorageMap<_, Twox64Concat, LeaseId, u64, ValueQuery, ConstU64<0>>; + StorageMap<_, Twox64Concat, LeaseId, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; /// ================== /// ==== Genesis ===== @@ -2158,7 +2180,7 @@ where *amount_unstaked, false, ), - Self::get_priority_staking(who, hotkey, *amount_unstaked), + Self::get_priority_staking(who, hotkey, (*amount_unstaked).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2185,7 +2207,7 @@ where max_amount, *allow_partial, ), - Self::get_priority_staking(who, hotkey, *amount_unstaked), + Self::get_priority_staking(who, hotkey, (*amount_unstaked).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2230,7 +2252,7 @@ where None, false, ), - Self::get_priority_staking(who, origin_hotkey, *alpha_amount), + Self::get_priority_staking(who, origin_hotkey, (*alpha_amount).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2259,7 +2281,7 @@ where None, true, ), - Self::get_priority_staking(who, hotkey, *alpha_amount), + Self::get_priority_staking(who, hotkey, (*alpha_amount).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2287,7 +2309,7 @@ where None, false, ), - Self::get_priority_staking(who, hotkey, *alpha_amount), + Self::get_priority_staking(who, hotkey, (*alpha_amount).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2326,7 +2348,7 @@ where Some(*allow_partial), false, ), - Self::get_priority_staking(who, hotkey, *alpha_amount), + Self::get_priority_staking(who, hotkey, (*alpha_amount).into()), ) .map(|validity| (validity, Some(who.clone()), origin.clone())) } @@ -2569,7 +2591,7 @@ impl> SubnetTAO::::get(netuid).saturating_add(SubnetTaoProvided::::get(netuid)) } - fn alpha_reserve(netuid: NetUid) -> u64 { + fn alpha_reserve(netuid: NetUid) -> AlphaCurrency { SubnetAlphaIn::::get(netuid).saturating_add(SubnetAlphaInProvided::::get(netuid)) } @@ -2593,7 +2615,11 @@ impl> pallet_balances::Pallet::::free_balance(account_id) } - fn alpha_balance(netuid: NetUid, coldkey: &T::AccountId, hotkey: &T::AccountId) -> u64 { + fn alpha_balance( + netuid: NetUid, + coldkey: &T::AccountId, + hotkey: &T::AccountId, + ) -> AlphaCurrency { Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) } @@ -2609,7 +2635,7 @@ impl> coldkey: &T::AccountId, hotkey: &T::AccountId, netuid: NetUid, - alpha: u64, + alpha: AlphaCurrency, ) -> Result<(), DispatchError> { ensure!( Self::hotkey_account_exists(hotkey), @@ -2630,8 +2656,8 @@ impl> coldkey: &T::AccountId, hotkey: &T::AccountId, netuid: NetUid, - alpha: u64, - ) -> Result { + alpha: AlphaCurrency, + ) -> Result { ensure!( Self::hotkey_account_exists(hotkey), Error::::HotKeyAccountNotExists @@ -2655,11 +2681,11 @@ impl> Self::decrease_provided_tao_reserve(netuid, tao); } - fn increase_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + fn increase_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency) { Self::increase_provided_alpha_reserve(netuid, alpha); } - fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency) { Self::decrease_provided_alpha_reserve(netuid, alpha); } } diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 95028a36d5..01ba58ef3b 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -456,7 +456,7 @@ mod dispatches { #[pallet::call_index(1)] #[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))] + .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Normal, Pays::Yes))] pub fn become_delegate(_origin: OriginFor, _hotkey: T::AccountId) -> DispatchResult { // DEPRECATED // Self::do_become_delegate(origin, hotkey, Self::get_default_delegate_take()) @@ -587,7 +587,7 @@ mod dispatches { #[pallet::call_index(2)] #[pallet::weight((Weight::from_parts(345_500_000, 0) .saturating_add(T::DbWeight::get().reads(26)) - .saturating_add(T::DbWeight::get().writes(15)), DispatchClass::Normal, Pays::No))] + .saturating_add(T::DbWeight::get().writes(15)), DispatchClass::Normal, Pays::Yes))] pub fn add_stake( origin: OriginFor, hotkey: T::AccountId, @@ -631,12 +631,12 @@ mod dispatches { #[pallet::call_index(3)] #[pallet::weight((Weight::from_parts(196_800_000, 0) .saturating_add(T::DbWeight::get().reads(19)) - .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::No))] + .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::Yes))] pub fn remove_stake( origin: OriginFor, hotkey: T::AccountId, netuid: NetUid, - amount_unstaked: u64, + amount_unstaked: AlphaCurrency, ) -> DispatchResult { Self::do_remove_stake(origin, hotkey, netuid, amount_unstaked) } @@ -1046,11 +1046,11 @@ mod dispatches { #[pallet::call_index(69)] #[pallet::weight(( Weight::from_parts(5_760_000, 0) - .saturating_add(T::DbWeight::get().reads(0)) - .saturating_add(T::DbWeight::get().writes(1)), - DispatchClass::Operational, - Pays::No -))] + .saturating_add(T::DbWeight::get().reads(0)) + .saturating_add(T::DbWeight::get().writes(1)), + DispatchClass::Operational, + Pays::No + ))] pub fn sudo_set_tx_childkey_take_rate_limit( origin: OriginFor, tx_rate_limit: u64, @@ -1577,7 +1577,7 @@ mod dispatches { #[pallet::call_index(83)] #[pallet::weight((Weight::from_parts(30_190_000, 0) .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Operational, Pays::No))] + .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Operational, Pays::Yes))] pub fn unstake_all(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_unstake_all(origin, hotkey) } @@ -1610,7 +1610,7 @@ mod dispatches { #[pallet::call_index(84)] #[pallet::weight((Weight::from_parts(369_500_000, 0) .saturating_add(T::DbWeight::get().reads(33)) - .saturating_add(T::DbWeight::get().writes(16)), DispatchClass::Operational, Pays::No))] + .saturating_add(T::DbWeight::get().writes(16)), DispatchClass::Operational, Pays::Yes))] pub fn unstake_all_alpha(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_unstake_all_alpha(origin, hotkey) } @@ -1637,16 +1637,16 @@ mod dispatches { /// - The alpha stake amount to move. /// #[pallet::call_index(85)] - #[pallet::weight((Weight::from_parts(419_500_000, 0) - .saturating_add(T::DbWeight::get().reads(32)) - .saturating_add(T::DbWeight::get().writes(20)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(157_100_000, 0) + .saturating_add(T::DbWeight::get().reads(15_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)), DispatchClass::Operational, Pays::Yes))] pub fn move_stake( origin: T::RuntimeOrigin, origin_hotkey: T::AccountId, destination_hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> DispatchResult { Self::do_move_stake( origin, @@ -1680,16 +1680,16 @@ mod dispatches { /// # Events /// May emit a `StakeTransferred` event on success. #[pallet::call_index(86)] - #[pallet::weight((Weight::from_parts(432_600_000, 0) - .saturating_add(T::DbWeight::get().reads(31)) - .saturating_add(T::DbWeight::get().writes(19)), DispatchClass::Operational, Pays::No))] + #[pallet::weight((Weight::from_parts(154_800_000, 0) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)), DispatchClass::Operational, Pays::Yes))] pub fn transfer_stake( origin: T::RuntimeOrigin, destination_coldkey: T::AccountId, hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> DispatchResult { Self::do_transfer_stake( origin, @@ -1726,14 +1726,14 @@ mod dispatches { .saturating_add(T::DbWeight::get().reads(32)) .saturating_add(T::DbWeight::get().writes(17)), DispatchClass::Operational, - Pays::No + Pays::Yes ))] pub fn swap_stake( origin: T::RuntimeOrigin, hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> DispatchResult { Self::do_swap_stake( origin, @@ -1789,7 +1789,7 @@ mod dispatches { #[pallet::call_index(88)] #[pallet::weight((Weight::from_parts(402_800_000, 0) .saturating_add(T::DbWeight::get().reads(26)) - .saturating_add(T::DbWeight::get().writes(15)), DispatchClass::Normal, Pays::No))] + .saturating_add(T::DbWeight::get().writes(15)), DispatchClass::Normal, Pays::Yes))] pub fn add_stake_limit( origin: OriginFor, hotkey: T::AccountId, @@ -1853,12 +1853,12 @@ mod dispatches { #[pallet::call_index(89)] #[pallet::weight((Weight::from_parts(403_800_000, 0) .saturating_add(T::DbWeight::get().reads(30)) - .saturating_add(T::DbWeight::get().writes(14)), DispatchClass::Normal, Pays::No))] + .saturating_add(T::DbWeight::get().writes(14)), DispatchClass::Normal, Pays::Yes))] pub fn remove_stake_limit( origin: OriginFor, hotkey: T::AccountId, netuid: NetUid, - amount_unstaked: u64, + amount_unstaked: AlphaCurrency, limit_price: u64, allow_partial: bool, ) -> DispatchResult { @@ -1899,14 +1899,14 @@ mod dispatches { .saturating_add(T::DbWeight::get().reads(32)) .saturating_add(T::DbWeight::get().writes(17)), DispatchClass::Operational, - Pays::No + Pays::Yes ))] pub fn swap_stake_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, limit_price: u64, allow_partial: bool, ) -> DispatchResult { @@ -1996,7 +1996,7 @@ mod dispatches { #[pallet::weight(( Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().reads_writes(2, 1)), DispatchClass::Operational, - Pays::No + Pays::Yes ))] pub fn associate_evm_key( origin: T::RuntimeOrigin, @@ -2027,7 +2027,7 @@ mod dispatches { pub fn recycle_alpha( origin: T::RuntimeOrigin, hotkey: T::AccountId, - amount: u64, + amount: AlphaCurrency, netuid: NetUid, ) -> DispatchResult { Self::do_recycle_alpha(origin, hotkey, amount, netuid) @@ -2052,7 +2052,7 @@ mod dispatches { pub fn burn_alpha( origin: T::RuntimeOrigin, hotkey: T::AccountId, - amount: u64, + amount: AlphaCurrency, netuid: NetUid, ) -> DispatchResult { Self::do_burn_alpha(origin, hotkey, amount, netuid) @@ -2077,7 +2077,7 @@ mod dispatches { #[pallet::call_index(103)] #[pallet::weight((Weight::from_parts(398_000_000, 10142) .saturating_add(T::DbWeight::get().reads(30_u64)) - .saturating_add(T::DbWeight::get().writes(14_u64)), DispatchClass::Normal, Pays::No))] + .saturating_add(T::DbWeight::get().writes(14_u64)), DispatchClass::Normal, Pays::Yes))] pub fn remove_stake_full_limit( origin: T::RuntimeOrigin, hotkey: T::AccountId, diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index 6add47d3be..949c56220d 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -14,9 +14,9 @@ mod events { /// a network is removed. NetworkRemoved(NetUid), /// stake has been transferred from the a coldkey account onto the hotkey staking account. - StakeAdded(T::AccountId, T::AccountId, u64, u64, NetUid, u64), + StakeAdded(T::AccountId, T::AccountId, u64, AlphaCurrency, NetUid, u64), /// stake has been removed from the hotkey staking account onto the coldkey account. - StakeRemoved(T::AccountId, T::AccountId, u64, u64, NetUid, u64), + StakeRemoved(T::AccountId, T::AccountId, u64, AlphaCurrency, NetUid, u64), /// stake has been moved from origin (hotkey, subnet ID) to destination (hotkey, subnet ID) of this amount (in TAO). StakeMoved( T::AccountId, @@ -304,13 +304,13 @@ mod events { /// /// Parameters: /// (coldkey, hotkey, amount, subnet_id) - AlphaRecycled(T::AccountId, T::AccountId, u64, NetUid), + AlphaRecycled(T::AccountId, T::AccountId, AlphaCurrency, NetUid), /// Alpha have been burned without reducing AlphaOut. /// /// Parameters: /// (coldkey, hotkey, amount, subnet_id) - AlphaBurned(T::AccountId, T::AccountId, u64, NetUid), + AlphaBurned(T::AccountId, T::AccountId, AlphaCurrency, NetUid), /// An EVM key has been associated with a hotkey. EvmKeyAssociated { diff --git a/pallets/subtensor/src/macros/genesis.rs b/pallets/subtensor/src/macros/genesis.rs index 2a82b63a35..db7c798fbc 100644 --- a/pallets/subtensor/src/macros/genesis.rs +++ b/pallets/subtensor/src/macros/genesis.rs @@ -51,7 +51,7 @@ mod genesis { let hotkey = DefaultAccount::::get(); SubnetMechanism::::insert(netuid, 1); // Make dynamic. Owner::::insert(hotkey.clone(), hotkey.clone()); - SubnetAlphaIn::::insert(netuid, 10_000_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(10_000_000_000)); SubnetTAO::::insert(netuid, 10_000_000_000); NetworksAdded::::insert(netuid, true); TotalNetworks::::mutate(|n| *n = n.saturating_add(1)); @@ -70,14 +70,18 @@ mod genesis { (hotkey.clone(), hotkey.clone(), netuid), U64F64::saturating_from_num(1_000_000_000), ); - TotalHotkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); + TotalHotkeyAlpha::::insert( + hotkey.clone(), + netuid, + AlphaCurrency::from(1_000_000_000), + ); TotalHotkeyShares::::insert( hotkey.clone(), netuid, U64F64::saturating_from_num(1_000_000_000), ); // TotalColdkeyAlpha::::insert(hotkey.clone(), netuid, 1_000_000_000); - SubnetAlphaOut::::insert(netuid, 1_000_000_000); + SubnetAlphaOut::::insert(netuid, AlphaCurrency::from(1_000_000_000)); let mut staking_hotkeys = StakingHotkeys::::get(hotkey.clone()); if !staking_hotkeys.contains(&hotkey) { staking_hotkeys.push(hotkey.clone()); @@ -90,7 +94,7 @@ mod genesis { Rank::::mutate(netuid, |v| v.push(0)); Trust::::mutate(netuid, |v| v.push(0)); Active::::mutate(netuid, |v| v.push(true)); - Emission::::mutate(netuid, |v| v.push(0)); + Emission::::mutate(netuid, |v| v.push(0.into())); Consensus::::mutate(netuid, |v| v.push(0)); Incentive::::mutate(netuid, |v| v.push(0)); Dividends::::mutate(netuid, |v| v.push(0)); diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 4b2a8e783b..7083c24e5d 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -125,7 +125,11 @@ mod hooks { // Fix the owner disable the registration .saturating_add(migrations::migrate_set_registration_enable::migrate_set_registration_enable::()) // Migrate Subnet Identities to V3 - .saturating_add(migrations::migrate_subnet_identities_to_v3::migrate_subnet_identities_to_v3::()); + .saturating_add(migrations::migrate_subnet_identities_to_v3::migrate_subnet_identities_to_v3::()) + // Migrate subnet symbols to fix the shift after subnet 81 + .saturating_add(migrations::migrate_subnet_symbols::migrate_subnet_symbols::()) + // Migrate CRV3 add commit_block + .saturating_add(migrations::migrate_crv3_commits_add_block::migrate_crv3_commits_add_block::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_crv3_commits_add_block.rs b/pallets/subtensor/src/migrations/migrate_crv3_commits_add_block.rs new file mode 100644 index 0000000000..27f2fe6d65 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_crv3_commits_add_block.rs @@ -0,0 +1,49 @@ +use super::*; +use frame_support::{traits::Get, weights::Weight}; +use log; +use scale_info::prelude::string::String; +use sp_std::collections::vec_deque::VecDeque; + +/// --------------- Migration ------------------------------------------ +/// Upgrades every entry to the new 4-tuple layout by inserting +/// `commit_block = first_block_of_epoch(netuid, epoch)`. +pub fn migrate_crv3_commits_add_block() -> Weight { + let mig_name: Vec = b"crv3_commits_add_block_v1".to_vec(); + let mut total_weight = T::DbWeight::get().reads(1); + + // run once + if HasMigrationRun::::get(&mig_name) { + log::info!( + "Migration '{}' already executed - skipping", + String::from_utf8_lossy(&mig_name) + ); + return total_weight; + } + log::info!("Running migration '{}'", String::from_utf8_lossy(&mig_name)); + + // iterate over *all* (netuid, epoch, queue) triples + for (netuid, epoch, old_q) in CRV3WeightCommits::::drain() { + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + + let commit_block = Pallet::::get_first_block_of_epoch(netuid, epoch); + + // convert VecDeque<(who,cipher,rnd)> → VecDeque<(who,cb,cipher,rnd)> + let new_q: VecDeque<_> = old_q + .into_iter() + .map(|(who, cipher, rnd)| (who, commit_block, cipher, rnd)) + .collect(); + + // write back under *new* storage definition + CRV3WeightCommitsV2::::insert(netuid, epoch, new_q); + } + + // mark as done + HasMigrationRun::::insert(&mig_name, true); + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{}' completed", + String::from_utf8_lossy(&mig_name) + ); + total_weight +} diff --git a/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs b/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs index f9c4b3c196..a30f0a84ea 100644 --- a/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs +++ b/pallets/subtensor/src/migrations/migrate_delete_subnet_3.rs @@ -6,6 +6,7 @@ use frame_support::{ }; use log::info; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; /// Constant for logging purposes const LOG_TARGET: &str = "migrate_delete_subnet_3"; diff --git a/pallets/subtensor/src/migrations/migrate_fix_root_subnet_tao.rs b/pallets/subtensor/src/migrations/migrate_fix_root_subnet_tao.rs index b7feea7546..96593b9e5c 100644 --- a/pallets/subtensor/src/migrations/migrate_fix_root_subnet_tao.rs +++ b/pallets/subtensor/src/migrations/migrate_fix_root_subnet_tao.rs @@ -24,7 +24,7 @@ pub fn migrate_fix_root_subnet_tao() -> Weight { // We accumulate the total stake for all hotkeys on the root subnet. for hotkey in Owner::::iter_keys() { let hotkey_stake = TotalHotkeyAlpha::::get(&hotkey, NetUid::ROOT); - total_stake = total_stake.saturating_add(hotkey_stake); + total_stake = total_stake.saturating_add(hotkey_stake.to_u64()); hotkey_count = hotkey_count.saturating_add(1); } diff --git a/pallets/subtensor/src/migrations/migrate_rao.rs b/pallets/subtensor/src/migrations/migrate_rao.rs index e9c631a0ba..d529e77098 100644 --- a/pallets/subtensor/src/migrations/migrate_rao.rs +++ b/pallets/subtensor/src/migrations/migrate_rao.rs @@ -2,6 +2,7 @@ use alloc::{format, string::String}; use frame_support::IterableStorageMap; use frame_support::{traits::Get, weights::Weight}; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; use super::*; @@ -64,7 +65,7 @@ pub fn migrate_rao() -> Weight { for netuid in netuids.iter() { if netuid.is_root() { // Give root a single RAO in pool to avoid any catestrophic division by zero. - SubnetAlphaIn::::insert(netuid, 1_000_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(1_000_000_000)); SubnetMechanism::::insert(netuid, 0); // Set to zero mechanism. TokenSymbol::::insert(netuid, Pallet::::get_symbol_for_subnet(NetUid::ROOT)); continue; @@ -96,8 +97,8 @@ pub fn migrate_rao() -> Weight { TotalStake::::mutate(|total| { *total = total.saturating_add(pool_initial_tao); }); // Increase total stake. - SubnetAlphaIn::::insert(netuid, pool_initial_tao); // Set initial alpha to pool initial tao. - SubnetAlphaOut::::insert(netuid, 0); // Set zero subnet alpha out. + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(pool_initial_tao)); // Set initial alpha to pool initial tao. + SubnetAlphaOut::::insert(netuid, AlphaCurrency::ZERO); // Set zero subnet alpha out. SubnetMechanism::::insert(netuid, 1); // Convert to dynamic immediately with initialization. // Set the token symbol for this subnet using Self instead of Pallet:: diff --git a/pallets/subtensor/src/migrations/migrate_remove_zero_total_hotkey_alpha.rs b/pallets/subtensor/src/migrations/migrate_remove_zero_total_hotkey_alpha.rs index df504c5453..b85ee78af6 100644 --- a/pallets/subtensor/src/migrations/migrate_remove_zero_total_hotkey_alpha.rs +++ b/pallets/subtensor/src/migrations/migrate_remove_zero_total_hotkey_alpha.rs @@ -31,7 +31,7 @@ pub fn migrate_remove_zero_total_hotkey_alpha() -> Weight { // For each (hotkey, netuid, alpha) entry, remove if alpha == 0 for (hotkey, netuid, alpha) in TotalHotkeyAlpha::::iter() { - if alpha == 0 { + if alpha == 0.into() { TotalHotkeyAlpha::::remove(&hotkey, netuid); removed_entries_count = removed_entries_count.saturating_add(1); } diff --git a/pallets/subtensor/src/migrations/migrate_set_min_burn.rs b/pallets/subtensor/src/migrations/migrate_set_min_burn.rs index 47e01dcfaf..505ea94a74 100644 --- a/pallets/subtensor/src/migrations/migrate_set_min_burn.rs +++ b/pallets/subtensor/src/migrations/migrate_set_min_burn.rs @@ -2,6 +2,7 @@ use alloc::string::String; use frame_support::IterableStorageMap; use frame_support::{traits::Get, weights::Weight}; +use subtensor_runtime_common::NetUid; use super::*; diff --git a/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs b/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs index 6b09502bcd..80a7d5faad 100644 --- a/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs +++ b/pallets/subtensor/src/migrations/migrate_set_min_difficulty.rs @@ -2,6 +2,7 @@ use alloc::string::String; use frame_support::IterableStorageMap; use frame_support::{traits::Get, weights::Weight}; +use subtensor_runtime_common::NetUid; 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 edea6a4c4b..84d8a681da 100644 --- a/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs +++ b/pallets/subtensor/src/migrations/migrate_to_v1_separate_emission.rs @@ -6,6 +6,7 @@ use frame_support::{ }; use log::{info, warn}; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; /// Constant for logging purposes const LOG_TARGET: &str = "loadedemissionmigration"; diff --git a/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs b/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs index 10a93784bb..25a11958f0 100644 --- a/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs +++ b/pallets/subtensor/src/migrations/migrate_transfer_ownership_to_foundation.rs @@ -8,6 +8,7 @@ use frame_support::{ use log::info; use sp_core::Get; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; /// Constant for logging purposes const LOG_TARGET: &str = "migrate_transfer_ownership"; diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 562a8d5e14..3acf7fafc9 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -8,6 +8,7 @@ pub mod migrate_chain_identity; pub mod migrate_coldkey_swap_scheduled; pub mod migrate_commit_reveal_v2; pub mod migrate_create_root_network; +pub mod migrate_crv3_commits_add_block; pub mod migrate_delete_subnet_21; pub mod migrate_delete_subnet_3; pub mod migrate_fix_is_network_member; diff --git a/pallets/subtensor/src/rpc_info/delegate_info.rs b/pallets/subtensor/src/rpc_info/delegate_info.rs index 94e4034b66..bf6dafd332 100644 --- a/pallets/subtensor/src/rpc_info/delegate_info.rs +++ b/pallets/subtensor/src/rpc_info/delegate_info.rs @@ -6,7 +6,7 @@ use substrate_fixed::types::U64F64; extern crate alloc; use alloc::collections::BTreeMap; use codec::Compact; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; #[freeze_struct("1fafc4fcf28cba7a")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] @@ -96,7 +96,7 @@ impl Pallet { validator_permits.push((*netuid).into()); } - let emission: U64F64 = Self::get_emission_for_uid(*netuid, uid).into(); + let emission: U64F64 = u64::from(Self::get_emission_for_uid(*netuid, uid)).into(); let tempo: U64F64 = Self::get_tempo(*netuid).into(); if tempo > U64F64::saturating_from_num(0) { let epochs_per_day: U64F64 = U64F64::saturating_from_num(7200).safe_div(tempo); @@ -109,8 +109,11 @@ impl Pallet { let owner = Self::get_owning_coldkey_for_hotkey(&delegate.clone()); let take: Compact = >::get(delegate.clone()).into(); - let total_stake: U64F64 = - Self::get_stake_for_hotkey_on_subnet(&delegate.clone(), NetUid::ROOT).into(); + let total_stake: U64F64 = u64::from(Self::get_stake_for_hotkey_on_subnet( + &delegate.clone(), + NetUid::ROOT, + )) + .into(); let return_per_1000: U64F64 = Self::return_per_1000_tao(take, total_stake, emissions_per_day); @@ -153,9 +156,14 @@ impl Pallet { /// pub fn get_delegated( delegatee: T::AccountId, - ) -> Vec<(DelegateInfo, (Compact, Compact))> { - let mut delegates: Vec<(DelegateInfo, (Compact, Compact))> = - Vec::new(); + ) -> Vec<( + DelegateInfo, + (Compact, Compact), + )> { + let mut delegates: Vec<( + DelegateInfo, + (Compact, Compact), + )> = Vec::new(); for delegate in as IterableStorageMap>::iter_keys() { // Staked to this delegate, so add to list for (netuid, _) in Alpha::::iter_prefix((delegate.clone(), delegatee.clone())) { diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index e4d83cb2c6..b4394bc68c 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -4,9 +4,9 @@ use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; -#[freeze_struct("ddf2c1fdd5bb7e7")] +#[freeze_struct("944ecd330621c61e")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct DynamicInfo { netuid: Compact, @@ -18,13 +18,13 @@ pub struct DynamicInfo { last_step: Compact, blocks_since_last_step: Compact, emission: Compact, - alpha_in: Compact, - alpha_out: Compact, + alpha_in: Compact, + alpha_out: Compact, tao_in: Compact, - alpha_out_emission: Compact, - alpha_in_emission: Compact, + alpha_out_emission: Compact, + alpha_in_emission: Compact, tao_in_emission: Compact, - pending_alpha_emission: Compact, + pending_alpha_emission: Compact, pending_root_emission: Compact, subnet_volume: Compact, network_registered_at: Compact, diff --git a/pallets/subtensor/src/rpc_info/metagraph.rs b/pallets/subtensor/src/rpc_info/metagraph.rs index 0cce4856f8..3f48c9ad45 100644 --- a/pallets/subtensor/src/rpc_info/metagraph.rs +++ b/pallets/subtensor/src/rpc_info/metagraph.rs @@ -7,9 +7,9 @@ use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; -#[freeze_struct("140374b562d8498b")] +#[freeze_struct("c25c5560ffd47ccb")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct Metagraph { // Subnet index @@ -32,17 +32,17 @@ pub struct Metagraph { blocks_since_last_step: Compact, // blocks since last epoch. // Subnet emission terms - subnet_emission: Compact, // subnet emission via stao - alpha_in: Compact, // amount of alpha in reserve - alpha_out: Compact, // amount of alpha outstanding - tao_in: Compact, // amount of tao injected per block - alpha_out_emission: Compact, // amount injected in alpha reserves per block - alpha_in_emission: Compact, // amount injected outstanding per block - tao_in_emission: Compact, // amount of tao injected per block - pending_alpha_emission: Compact, // pending alpha to be distributed - pending_root_emission: Compact, // panding tao for root divs to be distributed - subnet_volume: Compact, // volume of the subnet in TAO - moving_price: I96F32, // subnet moving price. + subnet_emission: Compact, // subnet emission via stao + alpha_in: Compact, // amount of alpha in reserve + alpha_out: Compact, // amount of alpha outstanding + tao_in: Compact, // amount of tao injected per block + alpha_out_emission: Compact, // amount injected in alpha reserves per block + alpha_in_emission: Compact, // amount injected outstanding per block + tao_in_emission: Compact, // amount of tao injected per block + pending_alpha_emission: Compact, // pending alpha to be distributed + pending_root_emission: Compact, // panding tao for root divs to be distributed + subnet_volume: Compact, // volume of the subnet in TAO + moving_price: I96F32, // subnet moving price. // Hparams for epoch rho: Compact, // subnet rho param @@ -93,7 +93,7 @@ pub struct Metagraph { validator_permit: Vec, // Val permit per UID pruning_score: Vec>, // Pruning per UID last_update: Vec>, // Last update per UID - emission: Vec>, // Emission per UID + emission: Vec>, // Emission per UID dividends: Vec>, // Dividends per UID incentives: Vec>, // Mining incentives per UID consensus: Vec>, // Consensus per UID @@ -106,10 +106,10 @@ pub struct Metagraph { // Dividend break down. tao_dividends_per_hotkey: Vec<(AccountId, Compact)>, // List of dividend payouts in tao via root. - alpha_dividends_per_hotkey: Vec<(AccountId, Compact)>, // List of dividend payout in alpha via subnet. + alpha_dividends_per_hotkey: Vec<(AccountId, Compact)>, // List of dividend payout in alpha via subnet. } -#[freeze_struct("55ca82be1558e748")] +#[freeze_struct("2fa92e896b40a104")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SelectiveMetagraph { // Subnet index @@ -133,16 +133,16 @@ pub struct SelectiveMetagraph { // Subnet emission terms subnet_emission: Option>, // subnet emission via stao - alpha_in: Option>, // amount of alpha in reserve - alpha_out: Option>, // amount of alpha outstanding + alpha_in: Option>, // amount of alpha in reserve + alpha_out: Option>, // amount of alpha outstanding tao_in: Option>, // amount of tao injected per block - alpha_out_emission: Option>, // amount injected in alpha reserves per block - alpha_in_emission: Option>, // amount injected outstanding per block - tao_in_emission: Option>, // amount of tao injected per block - pending_alpha_emission: Option>, // pending alpha to be distributed + alpha_out_emission: Option>, // amount injected in alpha reserves per block + alpha_in_emission: Option>, // amount injected outstanding per block + tao_in_emission: Option>, // amount of tao injected per block + pending_alpha_emission: Option>, // pending alpha to be distributed pending_root_emission: Option>, // panding tao for root divs to be distributed - subnet_volume: Option>, // volume of the subnet in TAO - moving_price: Option, // subnet moving price. + subnet_volume: Option>, // volume of the subnet in TAO + moving_price: Option, // subnet moving price. // Hparams for epoch rho: Option>, // subnet rho param @@ -193,7 +193,7 @@ pub struct SelectiveMetagraph { validator_permit: Option>, // Val permit per UID pruning_score: Option>>, // Pruning per UID last_update: Option>>, // Last update per UID - emission: Option>>, // Emission per UID + emission: Option>>, // Emission per UID dividends: Option>>, // Dividends per UID incentives: Option>>, // Mining incentives per UID consensus: Option>>, // Consensus per UID @@ -206,7 +206,7 @@ pub struct SelectiveMetagraph { // Dividend break down. tao_dividends_per_hotkey: Option)>>, // List of dividend payouts in tao via root. - alpha_dividends_per_hotkey: Option)>>, // List of dividend payout in alpha via subnet. + alpha_dividends_per_hotkey: Option)>>, // List of dividend payout in alpha via subnet. // validators validators: Option>>, // List of validators @@ -633,7 +633,7 @@ impl Pallet { axons.push(Self::get_axon_info(netuid, &hotkey)); } let mut tao_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = vec![]; - let mut alpha_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = vec![]; + let mut alpha_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = vec![]; for hotkey in hotkeys.clone() { let tao_divs = TaoDividendsPerSubnet::::get(netuid, hotkey.clone()); let alpha_divs = AlphaDividendsPerSubnet::::get(netuid, hotkey.clone()); @@ -1345,7 +1345,8 @@ impl Pallet { } } Some(SelectiveMetagraphIndex::AlphaDividendsPerHotkey) => { - let mut alpha_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = vec![]; + let mut alpha_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = + vec![]; let n: u16 = Self::get_subnetwork_n(netuid); let mut hotkeys: Vec = vec![]; diff --git a/pallets/subtensor/src/rpc_info/neuron_info.rs b/pallets/subtensor/src/rpc_info/neuron_info.rs index 337b89212d..8eae264c6e 100644 --- a/pallets/subtensor/src/rpc_info/neuron_info.rs +++ b/pallets/subtensor/src/rpc_info/neuron_info.rs @@ -2,9 +2,9 @@ use super::*; use frame_support::pallet_prelude::{Decode, Encode}; extern crate alloc; use codec::Compact; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; -#[freeze_struct("3bddc0abfa5445a6")] +#[freeze_struct("9e5a291e7e71482d")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct NeuronInfo { hotkey: AccountId, @@ -14,9 +14,9 @@ pub struct NeuronInfo { active: bool, axon_info: AxonInfo, prometheus_info: PrometheusInfo, - stake: Vec<(AccountId, Compact)>, // map of coldkey to stake on this neuron/hotkey (includes delegations) + stake: Vec<(AccountId, Compact)>, // map of coldkey to stake on this neuron/hotkey (includes delegations) rank: Compact, - emission: Compact, + emission: Compact, incentive: Compact, consensus: Compact, trust: Compact, @@ -29,7 +29,7 @@ pub struct NeuronInfo { pruning_score: Compact, } -#[freeze_struct("e2a6a95696a82c4f")] +#[freeze_struct("b9fdff7fc6e023c7")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct NeuronInfoLite { hotkey: AccountId, @@ -39,9 +39,9 @@ pub struct NeuronInfoLite { active: bool, axon_info: AxonInfo, prometheus_info: PrometheusInfo, - stake: Vec<(AccountId, Compact)>, // map of coldkey to stake on this neuron/hotkey (includes delegations) + stake: Vec<(AccountId, Compact)>, // map of coldkey to stake on this neuron/hotkey (includes delegations) rank: Compact, - emission: Compact, + emission: Compact, incentive: Compact, consensus: Compact, trust: Compact, @@ -117,7 +117,7 @@ impl Pallet { } }) .collect::, Compact)>>(); - let stake: Vec<(T::AccountId, Compact)> = vec![( + let stake: Vec<(T::AccountId, Compact)> = vec![( coldkey.clone(), Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid).into(), )]; @@ -182,7 +182,7 @@ impl Pallet { let last_update = Self::get_last_update_for_uid(netuid, uid); let validator_permit = Self::get_validator_permit_for_uid(netuid, uid); - let stake: Vec<(T::AccountId, Compact)> = vec![( + let stake: Vec<(T::AccountId, Compact)> = vec![( coldkey.clone(), Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid).into(), )]; diff --git a/pallets/subtensor/src/rpc_info/show_subnet.rs b/pallets/subtensor/src/rpc_info/show_subnet.rs index aa5b2f4d36..4c39542ace 100644 --- a/pallets/subtensor/src/rpc_info/show_subnet.rs +++ b/pallets/subtensor/src/rpc_info/show_subnet.rs @@ -4,9 +4,9 @@ use crate::epoch::math::*; use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; -#[freeze_struct("11f58860434dd863")] +#[freeze_struct("c990700ae235dee9")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SubnetState { netuid: Compact, @@ -16,7 +16,7 @@ pub struct SubnetState { validator_permit: Vec, pruning_score: Vec>, last_update: Vec>, - emission: Vec>, + emission: Vec>, dividends: Vec>, incentives: Vec>, consensus: Vec>, @@ -26,7 +26,7 @@ pub struct SubnetState { alpha_stake: Vec>, tao_stake: Vec>, total_stake: Vec>, - emission_history: Vec>>, + emission_history: Vec>>, // identities: Vec, // tao_stake: Compact, // incentive: Compact, @@ -51,12 +51,12 @@ impl Pallet { /// # Returns /// /// * `Vec>>` - A vector of vectors containing the emission history for each hotkey across all subnets. - pub fn get_emissions_history(hotkeys: Vec) -> Vec>> { - let mut result: Vec>> = vec![]; + pub fn get_emissions_history(hotkeys: Vec) -> Vec>> { + let mut result: Vec>> = vec![]; for netuid in Self::get_all_subnet_netuids() { - let mut hotkeys_emissions: Vec> = vec![]; + let mut hotkeys_emissions: Vec> = vec![]; for hotkey in hotkeys.clone() { - let last_emission: Compact = + let last_emission: Compact = LastHotkeyEmissionOnNetuid::::get(hotkey.clone(), netuid).into(); hotkeys_emissions.push(last_emission); } @@ -107,7 +107,7 @@ impl Pallet { .into_iter() .map(Compact::from) .collect(); - let emission: Vec> = Emission::::get(netuid) + let emission = Emission::::get(netuid) .into_iter() .map(Compact::from) .collect(); @@ -148,7 +148,7 @@ impl Pallet { .iter() .map(|xi| Compact::from(fixed64_to_u64(*xi))) .collect::>>(); - let emission_history: Vec>> = Self::get_emissions_history(hotkeys.clone()); + let emission_history = Self::get_emissions_history(hotkeys.clone()); Some(SubnetState { netuid: netuid.into(), hotkeys, diff --git a/pallets/subtensor/src/rpc_info/stake_info.rs b/pallets/subtensor/src/rpc_info/stake_info.rs index 5fd9f6f7b8..23c2a7df0e 100644 --- a/pallets/subtensor/src/rpc_info/stake_info.rs +++ b/pallets/subtensor/src/rpc_info/stake_info.rs @@ -2,20 +2,20 @@ extern crate alloc; use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; use subtensor_swap_interface::SwapHandler; use super::*; -#[freeze_struct("56f5e9f33e5ec9da")] +#[freeze_struct("cff08b08c64eb867")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct StakeInfo { hotkey: AccountId, coldkey: AccountId, netuid: Compact, - stake: Compact, + stake: Compact, locked: Compact, - emission: Compact, + emission: Compact, tao_emission: Compact, drain: Compact, is_registered: bool, @@ -36,13 +36,13 @@ impl Pallet { let mut stake_info_for_coldkey: Vec> = Vec::new(); for netuid_i in netuids.clone().iter() { for hotkey_i in staking_hotkeys.clone().iter() { - let alpha: u64 = Self::get_stake_for_hotkey_and_coldkey_on_subnet( + let alpha = Self::get_stake_for_hotkey_and_coldkey_on_subnet( hotkey_i, coldkey_i, *netuid_i, ); - if alpha == 0 { + if alpha.is_zero() { continue; } - let emission: u64 = AlphaDividendsPerSubnet::::get(*netuid_i, &hotkey_i); + let emission = AlphaDividendsPerSubnet::::get(*netuid_i, &hotkey_i); let tao_emission: u64 = TaoDividendsPerSubnet::::get(*netuid_i, &hotkey_i); let is_registered: bool = Self::is_hotkey_registered_on_network(*netuid_i, hotkey_i); @@ -95,12 +95,12 @@ impl Pallet { coldkey_account: T::AccountId, netuid: NetUid, ) -> Option> { - let alpha: u64 = Self::get_stake_for_hotkey_and_coldkey_on_subnet( + let alpha = Self::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account, &coldkey_account, netuid, ); - let emission: u64 = AlphaDividendsPerSubnet::::get(netuid, &hotkey_account); + let emission = AlphaDividendsPerSubnet::::get(netuid, &hotkey_account); let tao_emission: u64 = TaoDividendsPerSubnet::::get(netuid, &hotkey_account); let is_registered: bool = Self::is_hotkey_registered_on_network(netuid, &hotkey_account); @@ -124,7 +124,11 @@ impl Pallet { _destination_coldkey_account: T::AccountId, amount: u64, ) -> u64 { - let netuid = destination.or(origin).map(|v| v.1).unwrap_or_default(); - T::SwapInterface::approx_fee_amount(netuid.into(), amount) + if destination == origin { + 0_u64 + } else { + 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/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 422bcbc5d5..4b897fef96 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -72,16 +72,20 @@ impl Pallet { 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() + T::SwapInterface::sim_swap( + netuid.into(), + OrderType::Sell, + alpha_stake.into(), + ) + .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::() }) @@ -180,13 +184,13 @@ impl Pallet { if !Self::coldkey_owns_hotkey(coldkey, hotkey) { // If the stake is below the minimum required, it's considered a small nomination and needs to be cleared. // Log if the stake is below the minimum required - let alpha_stake: u64 = + let alpha_stake = Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); let min_alpha_stake = U96F32::saturating_from_num(Self::get_nominator_min_required_stake()) .safe_div(T::SwapInterface::current_alpha_price(netuid)) .saturating_to_num::(); - if alpha_stake < min_alpha_stake { + if alpha_stake < min_alpha_stake.into() { // Log the clearing of a small nomination // Remove the stake from the nominator account. (this is a more forceful unstake operation which ) // Actually deletes the staking account. diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index 9a4d515276..15f2dd511a 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -2,7 +2,7 @@ use super::*; use safe_math::*; use sp_core::Get; use substrate_fixed::types::U64F64; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; use subtensor_swap_interface::SwapHandler; impl Pallet { @@ -33,7 +33,7 @@ impl Pallet { destination_hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> dispatch::DispatchResult { // Check that the origin is signed by the origin_hotkey. let coldkey = ensure_signed(origin)?; @@ -128,7 +128,7 @@ impl Pallet { hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> dispatch::DispatchResult { // Ensure the extrinsic is signed by the origin_coldkey. let coldkey = ensure_signed(origin)?; @@ -199,7 +199,7 @@ impl Pallet { hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, ) -> dispatch::DispatchResult { // Ensure the extrinsic is signed by the coldkey. let coldkey = ensure_signed(origin)?; @@ -270,7 +270,7 @@ impl Pallet { hotkey: T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, limit_price: u64, allow_partial: bool, ) -> dispatch::DispatchResult { @@ -322,15 +322,19 @@ impl Pallet { destination_hotkey: &T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, + alpha_amount: AlphaCurrency, maybe_limit_price: Option, maybe_allow_partial: Option, check_transfer_toggle: bool, set_limit: bool, ) -> 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)? + let max_amount = if origin_netuid != destination_netuid { + if let Some(limit_price) = maybe_limit_price { + Self::get_max_amount_move(origin_netuid, destination_netuid, limit_price)? + } else { + alpha_amount + } } else { alpha_amount }; @@ -356,36 +360,47 @@ impl Pallet { max_amount }; - // do not pay fees to avoid double fees in moves transactions - let tao_unstaked = Self::unstake_from_subnet( - origin_hotkey, - origin_coldkey, - origin_netuid, - move_amount, - T::SwapInterface::min_price(), - true, - )?; + if origin_netuid != destination_netuid { + // do not pay remove fees to avoid double fees in moves transactions + let tao_unstaked = Self::unstake_from_subnet( + origin_hotkey, + origin_coldkey, + origin_netuid, + move_amount, + T::SwapInterface::min_price(), + true, + )?; - // 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() { - // 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); + // 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() { + // 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); + } + + Self::stake_into_subnet( + destination_hotkey, + destination_coldkey, + destination_netuid, + tao_unstaked, + T::SwapInterface::max_price(), + set_limit, + )?; } - Self::stake_into_subnet( - destination_hotkey, + Ok(tao_unstaked) + } else { + Self::transfer_stake_within_subnet( + origin_coldkey, + origin_hotkey, destination_coldkey, - destination_netuid, - tao_unstaked, - T::SwapInterface::max_price(), - set_limit, - )?; + destination_hotkey, + origin_netuid, + move_amount, + ) } - - Ok(tao_unstaked) } /// Returns the maximum amount of origin netuid Alpha that can be executed before we cross @@ -415,7 +430,7 @@ impl Pallet { origin_netuid: NetUid, destination_netuid: NetUid, limit_price: u64, - ) -> Result> { + ) -> Result> { let tao: U64F64 = U64F64::saturating_from_num(1_000_000_000); // Corner case: both subnet IDs are root or stao @@ -427,7 +442,7 @@ impl Pallet { if limit_price > tao.saturating_to_num::() { return Err(Error::ZeroMaxStakeAmount); } else { - return Ok(u64::MAX); + return Ok(AlphaCurrency::MAX); } } @@ -437,14 +452,15 @@ impl Pallet { && (SubnetMechanism::::get(destination_netuid) == 1) { if limit_price == 0 { - return Ok(u64::MAX); + return Ok(AlphaCurrency::MAX); } else { // The destination price is reverted because the limit_price is origin_price / destination_price let destination_subnet_price = tao .safe_div(U64F64::saturating_from_num(limit_price)) .saturating_mul(tao) .saturating_to_num::(); - return Self::get_max_amount_add(destination_netuid, destination_subnet_price); + return Self::get_max_amount_add(destination_netuid, destination_subnet_price) + .map(Into::into); } } @@ -472,7 +488,7 @@ impl Pallet { .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) { + if alpha_in_1.is_zero() || alpha_in_2.is_zero() { return Err(Error::ZeroMaxStakeAmount); } let alpha_in_1_float: U64F64 = U64F64::saturating_from_num(alpha_in_1); @@ -494,7 +510,7 @@ impl Pallet { // Corner case: limit_price is zero if limit_price == 0 { - return Ok(u64::MAX); + return Ok(AlphaCurrency::MAX); } // Main case @@ -513,7 +529,7 @@ impl Pallet { .saturating_to_num::(); if final_result != 0 { - Ok(final_result) + Ok(final_result.into()) } else { Err(Error::ZeroMaxStakeAmount) } diff --git a/pallets/subtensor/src/staking/recycle_alpha.rs b/pallets/subtensor/src/staking/recycle_alpha.rs index 7364618dff..2fbbfb3b06 100644 --- a/pallets/subtensor/src/staking/recycle_alpha.rs +++ b/pallets/subtensor/src/staking/recycle_alpha.rs @@ -1,6 +1,6 @@ use super::*; use crate::{Error, system::ensure_signed}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; impl Pallet { /// Recycles alpha from a cold/hot key pair, reducing AlphaOut on a subnet @@ -18,7 +18,7 @@ impl Pallet { pub(crate) fn do_recycle_alpha( origin: T::RuntimeOrigin, hotkey: T::AccountId, - amount: u64, + amount: AlphaCurrency, netuid: NetUid, ) -> DispatchResult { let coldkey: T::AccountId = ensure_signed(origin)?; @@ -84,7 +84,7 @@ impl Pallet { pub(crate) fn do_burn_alpha( origin: T::RuntimeOrigin, hotkey: T::AccountId, - amount: u64, + amount: AlphaCurrency, netuid: NetUid, ) -> DispatchResult { let coldkey = ensure_signed(origin)?; diff --git a/pallets/subtensor/src/staking/remove_stake.rs b/pallets/subtensor/src/staking/remove_stake.rs index f5b769b6ce..afe9d19308 100644 --- a/pallets/subtensor/src/staking/remove_stake.rs +++ b/pallets/subtensor/src/staking/remove_stake.rs @@ -1,7 +1,7 @@ use subtensor_swap_interface::{OrderType, SwapHandler}; use super::*; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; impl Pallet { /// ---- The implementation for the extrinsic remove_stake: Removes stake from a hotkey account and adds it onto a coldkey. @@ -16,8 +16,8 @@ impl Pallet { /// * 'netuid' (u16): /// - Subnetwork UID /// - /// * 'stake_to_be_added' (u64): - /// - The amount of stake to be added to the hotkey staking account. + /// * 'alpha_unstaked' (Alpha): + /// - The amount of stake to be removed from the staking account. /// /// # Event: /// * StakeRemoved; @@ -40,7 +40,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: T::AccountId, netuid: NetUid, - alpha_unstaked: u64, + alpha_unstaked: AlphaCurrency, ) -> dispatch::DispatchResult { // 1. We check the transaction is signed by the caller and retrieve the T::AccountId coldkey information. let coldkey = ensure_signed(origin)?; @@ -64,8 +64,8 @@ impl Pallet { false, )?; - // 3. Swap the alpha to tao and update counters for this subnet. - let tao_unstaked: u64 = Self::unstake_from_subnet( + // 3. Swap the alpba to tao and update counters for this subnet. + let tao_unstaked = Self::unstake_from_subnet( &hotkey, &coldkey, netuid, @@ -158,7 +158,7 @@ impl Pallet { continue; } - if alpha_unstaked > 0 { + if !alpha_unstaked.is_zero() { // Swap the alpha to tao and update counters for this subnet. let tao_unstaked: u64 = Self::unstake_from_subnet( &hotkey, @@ -251,7 +251,7 @@ impl Pallet { continue; } - if alpha_unstaked > 0 { + if !alpha_unstaked.is_zero() { // Swap the alpha to tao and update counters for this subnet. let tao_unstaked = Self::unstake_from_subnet( &hotkey, @@ -330,7 +330,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: T::AccountId, netuid: NetUid, - alpha_unstaked: u64, + alpha_unstaked: AlphaCurrency, limit_price: u64, allow_partial: bool, ) -> dispatch::DispatchResult { @@ -389,13 +389,16 @@ impl Pallet { } // Returns the maximum amount of RAO that can be executed with price limit - pub fn get_max_amount_remove(netuid: NetUid, limit_price: u64) -> Result> { + pub fn get_max_amount_remove( + netuid: NetUid, + limit_price: u64, + ) -> Result> { // Corner case: root and stao // There's no slippage for root or stable subnets, so if limit price is 1e9 rao or // lower, then max_amount equals u64::MAX, otherwise it is 0. if netuid.is_root() || SubnetMechanism::::get(netuid) == 0 { if limit_price <= 1_000_000_000 { - return Ok(u64::MAX); + return Ok(AlphaCurrency::MAX); } else { return Err(Error::ZeroMaxStakeAmount); } @@ -414,7 +417,7 @@ impl Pallet { .map_err(|_| Error::ZeroMaxStakeAmount)?; if result != 0 { - Ok(result) + Ok(result.into()) } else { Err(Error::ZeroMaxStakeAmount) } diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 8dce6f9f7c..38027f489f 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -3,7 +3,7 @@ use safe_math::*; use share_pool::{SharePool, SharePoolDataOperations}; use sp_std::ops::Neg; use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency, NetUid}; use subtensor_swap_interface::{OrderType, SwapHandler, SwapResult}; impl Pallet { @@ -17,7 +17,7 @@ impl Pallet { /// /// # Returns /// * `u64` - The total alpha issuance for the specified subnet. - pub fn get_alpha_issuance(netuid: NetUid) -> u64 { + pub fn get_alpha_issuance(netuid: NetUid) -> AlphaCurrency { SubnetAlphaIn::::get(netuid).saturating_add(SubnetAlphaOut::::get(netuid)) } @@ -322,7 +322,10 @@ impl Pallet { finalized_tao.saturating_to_num::() } - pub fn get_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> u64 { + pub fn get_inherited_for_hotkey_on_subnet( + hotkey: &T::AccountId, + netuid: NetUid, + ) -> AlphaCurrency { // Step 1: Retrieve the initial total stake (alpha) for the hotkey on the specified subnet. let initial_alpha: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); @@ -333,7 +336,7 @@ impl Pallet { initial_alpha ); if netuid.is_root() { - return initial_alpha.saturating_to_num::(); + return initial_alpha.saturating_to_num::().into(); } // Initialize variables to track alpha allocated to children and inherited from parents. @@ -424,7 +427,7 @@ impl Pallet { ); // Step 6: Return the final inherited alpha value. - finalized_alpha.saturating_to_num::() + finalized_alpha.saturating_to_num::().into() } /// Checks if a specific hotkey-coldkey pair has enough stake on a subnet to fulfill a given decrement. @@ -448,8 +451,8 @@ impl Pallet { hotkey: &T::AccountId, coldkey: &T::AccountId, netuid: NetUid, - decrement: u64, - ) -> Result> { + decrement: AlphaCurrency, + ) -> Result> { // Retrieve the current stake for this hotkey-coldkey pair on the subnet let current_stake = Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); @@ -484,9 +487,9 @@ impl Pallet { hotkey: &T::AccountId, coldkey: &T::AccountId, netuid: NetUid, - ) -> u64 { + ) -> AlphaCurrency { let alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); - alpha_share_pool.try_get_value(coldkey).unwrap_or(0) + alpha_share_pool.try_get_value(coldkey).unwrap_or(0).into() } /// Retrieves the total stake (alpha) for a given hotkey on a specific subnet. @@ -503,7 +506,7 @@ impl Pallet { /// /// # Note /// This function returns the cumulative stake across all coldkeys associated with this hotkey on the subnet. - pub fn get_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> u64 { + pub fn get_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid) -> AlphaCurrency { // Retrieve and return the total alpha this hotkey owns on this subnet. // This value represents the sum of stakes from all coldkeys associated with this hotkey. TotalHotkeyAlpha::::get(hotkey, netuid) @@ -518,9 +521,13 @@ impl Pallet { /// * `netuid` - The unique identifier of the subnet. /// * `amount` - The amount of alpha to be added. /// - pub fn increase_stake_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: NetUid, amount: u64) { + pub fn increase_stake_for_hotkey_on_subnet( + hotkey: &T::AccountId, + netuid: NetUid, + amount: AlphaCurrency, + ) { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); - alpha_share_pool.update_value_for_all(amount as i64); + alpha_share_pool.update_value_for_all(amount.to_u64() as i64); } /// Decrease hotkey stake on a subnet. @@ -551,9 +558,9 @@ impl Pallet { hotkey: &T::AccountId, coldkey: &T::AccountId, netuid: NetUid, - amount: u64, - ) -> u64 { - if amount > 0 { + amount: AlphaCurrency, + ) -> AlphaCurrency { + if !amount.is_zero() { let mut staking_hotkeys = StakingHotkeys::::get(coldkey); if !staking_hotkeys.contains(hotkey) { staking_hotkeys.push(hotkey.clone()); @@ -563,20 +570,22 @@ impl Pallet { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); // We expect to add a positive amount here. - let actual_alpha = alpha_share_pool.update_value_for_one(coldkey, amount as i64); + let amount = amount.to_u64() as i64; + let actual_alpha = alpha_share_pool.update_value_for_one(coldkey, amount); // We should return a positive amount, or 0 if the operation failed. // e.g. the stake was removed due to precision issues. - actual_alpha.max(0).unsigned_abs() + actual_alpha.max(0).unsigned_abs().into() } pub fn try_increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey: &T::AccountId, netuid: NetUid, - amount: u64, + amount: AlphaCurrency, ) -> bool { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); - alpha_share_pool.sim_update_value_for_one(amount as i64) + let amount = amount.to_u64() as i64; + alpha_share_pool.sim_update_value_for_one(amount) } /// Sell shares in the hotkey on a given subnet @@ -593,9 +602,10 @@ impl Pallet { hotkey: &T::AccountId, coldkey: &T::AccountId, netuid: NetUid, - amount: u64, - ) -> u64 { + amount: AlphaCurrency, + ) -> AlphaCurrency { let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid); + let amount = amount.to_u64(); // We expect a negative value here let mut actual_alpha = 0; @@ -609,7 +619,7 @@ impl Pallet { // Get the negation of the removed alpha, and clamp at 0. // This ensures we return a positive value, but only if // `actual_alpha` was negative (i.e. a decrease in stake). - actual_alpha.neg().max(0).unsigned_abs() + actual_alpha.neg().max(0).unsigned_abs().into() } /// Swaps TAO for the alpha token on the subnet. @@ -631,20 +641,15 @@ impl Pallet { false, false, )?; + let alpha_decrease = + AlphaCurrency::from(swap_result.alpha_reserve_delta.unsigned_abs()); // Decrease Alpha reserves. - Self::decrease_provided_alpha_reserve( - netuid.into(), - swap_result - .alpha_reserve_delta - .abs() - .try_into() - .unwrap_or(0), - ); + Self::decrease_provided_alpha_reserve(netuid.into(), alpha_decrease); // Increase Alpha outstanding. SubnetAlphaOut::::mutate(netuid, |total| { - *total = total.saturating_add(swap_result.amount_paid_out); + *total = total.saturating_add(swap_result.amount_paid_out.into()); }); // Increase only the protocol TAO reserve. We only use the sum of @@ -681,7 +686,7 @@ impl Pallet { /// Updates TaoIn, AlphaIn, and AlphaOut pub fn swap_alpha_for_tao( netuid: NetUid, - alpha: u64, + alpha: AlphaCurrency, price_limit: u64, drop_fees: bool, ) -> Result { @@ -692,7 +697,7 @@ impl Pallet { let swap_result = T::SwapInterface::swap( netuid.into(), OrderType::Sell, - alpha, + alpha.into(), price_limit, drop_fees, false, @@ -702,13 +707,13 @@ impl Pallet { // (SubnetAlphaIn + SubnetAlphaInProvided) in alpha_reserve(), so it is irrelevant // which one to increase. SubnetAlphaIn::::mutate(netuid, |total| { - *total = total.saturating_add(swap_result.alpha_reserve_delta as u64); + *total = total.saturating_add((swap_result.alpha_reserve_delta as u64).into()); }); // Decrease Alpha outstanding. // TODO: Deprecate, not accurate in v3 anymore SubnetAlphaOut::::mutate(netuid, |total| { - *total = total.saturating_sub(swap_result.alpha_reserve_delta as u64); + *total = total.saturating_sub((swap_result.alpha_reserve_delta as u64).into()); }); // Decrease tao reserves. @@ -732,8 +737,8 @@ impl Pallet { } else { // Step 3.b.1: Stable mechanism, just return the value 1:1 Ok(SwapResult { - amount_paid_in: alpha, - amount_paid_out: alpha, + amount_paid_in: alpha.into(), + amount_paid_out: alpha.into(), fee_paid: 0, tao_reserve_delta: 0, alpha_reserve_delta: 0, @@ -748,7 +753,7 @@ impl Pallet { hotkey: &T::AccountId, coldkey: &T::AccountId, netuid: NetUid, - alpha: u64, + alpha: AlphaCurrency, price_limit: u64, drop_fees: bool, ) -> Result { @@ -764,9 +769,10 @@ impl Pallet { let refund = actual_alpha_decrease.saturating_sub( swap_result .amount_paid_in - .saturating_add(swap_result.fee_paid), + .saturating_add(swap_result.fee_paid) + .into(), ); - if refund > 0 { + if !refund.is_zero() { Self::increase_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, refund); } @@ -813,7 +819,7 @@ impl Pallet { tao: u64, price_limit: u64, set_limit: bool, - ) -> Result { + ) -> Result { // Swap the tao to alpha. let swap_result = Self::swap_tao_for_alpha(netuid, tao, price_limit)?; @@ -823,7 +829,7 @@ impl Pallet { Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey, netuid, - swap_result.amount_paid_out, + swap_result.amount_paid_out.into(), ), Error::::InsufficientLiquidity ); @@ -833,11 +839,12 @@ impl Pallet { hotkey, coldkey, netuid, - swap_result.amount_paid_out, - ) == 0 + swap_result.amount_paid_out.into(), + ) + .is_zero() || swap_result.amount_paid_out == 0 { - return Ok(0); + return Ok(AlphaCurrency::ZERO); } // Step 4: Update the list of hotkeys staking for this coldkey @@ -858,7 +865,7 @@ impl Pallet { coldkey.clone(), hotkey.clone(), tao, - swap_result.amount_paid_out, + swap_result.amount_paid_out.into(), netuid, swap_result.fee_paid, )); @@ -873,7 +880,84 @@ impl Pallet { swap_result.fee_paid, ); - Ok(swap_result.amount_paid_out) + Ok(swap_result.amount_paid_out.into()) + } + + /// Transfers stake between coldkeys and/or hotkey within one subnet without running it + /// through swap. + /// + /// Does not incur any swapping nor fees + pub fn transfer_stake_within_subnet( + origin_coldkey: &T::AccountId, + origin_hotkey: &T::AccountId, + destination_coldkey: &T::AccountId, + destination_hotkey: &T::AccountId, + netuid: NetUid, + alpha: AlphaCurrency, + ) -> Result { + // Decrease alpha on origin keys + let actual_alpha_decrease = Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( + origin_hotkey, + origin_coldkey, + netuid, + alpha, + ); + + // Increase alpha on destination keys + let actual_alpha_moved = Self::increase_stake_for_hotkey_and_coldkey_on_subnet( + destination_hotkey, + destination_coldkey, + netuid, + actual_alpha_decrease, + ); + + // Calculate TAO equivalent based on current price (it is accurate because + // there's no slippage in this move) + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); + let tao_equivalent = current_price + .saturating_mul(U96F32::saturating_from_num(actual_alpha_moved)) + .saturating_to_num::(); + + // Ensure tao_equivalent is above DefaultMinStake + ensure!( + tao_equivalent >= DefaultMinStake::::get(), + Error::::AmountTooLow + ); + + // Step 3: Update StakingHotkeys if the hotkey's total alpha, across all subnets, is zero + // TODO: fix. + // if Self::get_stake(hotkey, coldkey) == 0 { + // StakingHotkeys::::mutate(coldkey, |hotkeys| { + // hotkeys.retain(|k| k != hotkey); + // }); + // } + + LastColdkeyHotkeyStakeBlock::::insert( + destination_coldkey, + destination_hotkey, + Self::get_current_block_as_u64(), + ); + + // Deposit and log the unstaking event. + Self::deposit_event(Event::StakeRemoved( + origin_coldkey.clone(), + origin_hotkey.clone(), + tao_equivalent, + actual_alpha_decrease, + netuid, + 0_u64, // 0 fee + )); + Self::deposit_event(Event::StakeAdded( + destination_coldkey.clone(), + destination_hotkey.clone(), + tao_equivalent, + actual_alpha_moved, + netuid, + 0_u64, // 0 fee + )); + + Ok(tao_equivalent) } pub fn get_alpha_share_pool( @@ -953,7 +1037,7 @@ impl Pallet { let try_stake_result = Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet( hotkey, netuid, - swap_result.amount_paid_out, + swap_result.amount_paid_out.into(), ); ensure!(try_stake_result, Error::::InsufficientLiquidity); @@ -966,8 +1050,8 @@ impl Pallet { coldkey: &T::AccountId, hotkey: &T::AccountId, netuid: NetUid, - alpha_unstaked: u64, - max_amount: u64, + alpha_unstaked: AlphaCurrency, + max_amount: AlphaCurrency, allow_partial: bool, ) -> Result<(), Error> { // Ensure that the subnet exists. @@ -979,15 +1063,15 @@ impl Pallet { // Self::ensure_subtoken_enabled(netuid)?; // Do not allow zero unstake amount - ensure!(alpha_unstaked > 0, Error::::AmountTooLow); + ensure!(!alpha_unstaked.is_zero(), Error::::AmountTooLow); // Ensure that the stake amount to be removed is above the minimum in tao equivalent. // Bypass this check if the user unstakes full amount let remaining_alpha_stake = Self::calculate_reduced_stake_on_subnet(hotkey, coldkey, netuid, alpha_unstaked)?; - match T::SwapInterface::sim_swap(netuid.into(), OrderType::Sell, alpha_unstaked) { + match T::SwapInterface::sim_swap(netuid.into(), OrderType::Sell, alpha_unstaked.into()) { Ok(res) => { - if remaining_alpha_stake > 0 { + if !remaining_alpha_stake.is_zero() { ensure!( res.amount_paid_out >= DefaultMinStake::::get(), Error::::AmountTooLow @@ -1058,8 +1142,8 @@ impl Pallet { destination_hotkey: &T::AccountId, origin_netuid: NetUid, destination_netuid: NetUid, - alpha_amount: u64, - max_amount: u64, + alpha_amount: AlphaCurrency, + max_amount: AlphaCurrency, maybe_allow_partial: Option, check_transfer_toggle: bool, ) -> Result<(), Error> { @@ -1119,21 +1203,27 @@ impl Pallet { Error::::NotEnoughStakeToWithdraw ); - // Ensure that the stake amount to be removed is above the minimum in tao equivalent. - 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 - ); + // If origin and destination netuid are different, do the swap-related checks + if origin_netuid != destination_netuid { + // Ensure that the stake amount to be removed is above the minimum in tao equivalent. + let tao_equivalent = T::SwapInterface::sim_swap( + origin_netuid.into(), + OrderType::Sell, + alpha_amount.into(), + ) + .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 - if let Some(allow_partial) = maybe_allow_partial { - if !allow_partial { - ensure!(alpha_amount <= max_amount, Error::::SlippageTooHigh); + // Ensure that if partial execution is not allowed, the amount will not cause + // slippage over desired + if let Some(allow_partial) = maybe_allow_partial { + if !allow_partial { + ensure!(alpha_amount <= max_amount, Error::::SlippageTooHigh); + } } } @@ -1143,10 +1233,12 @@ impl Pallet { TransferToggle::::get(origin_netuid), Error::::TransferDisallowed ); - ensure!( - TransferToggle::::get(destination_netuid), - Error::::TransferDisallowed - ); + if origin_netuid != destination_netuid { + ensure!( + TransferToggle::::get(destination_netuid), + Error::::TransferDisallowed + ); + } } Ok(()) @@ -1172,22 +1264,22 @@ impl Pallet { } } - pub fn increase_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + pub fn increase_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency) { SubnetAlphaInProvided::::mutate(netuid, |total| { *total = total.saturating_add(alpha); }); } - pub fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: u64) { + pub fn decrease_provided_alpha_reserve(netuid: NetUid, alpha: AlphaCurrency) { // 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 { + if carry_over.is_zero() { SubnetAlphaInProvided::::set(netuid, remainder); } else { - SubnetAlphaInProvided::::set(netuid, 0_u64); + SubnetAlphaInProvided::::set(netuid, AlphaCurrency::ZERO); SubnetAlphaIn::::set(netuid, subnet_alpha.saturating_sub(carry_over)); } } @@ -1261,7 +1353,7 @@ impl SharePoolDataOperations> crate::TotalHotkeyAlpha::::insert( &(self.hotkey), self.netuid, - value.saturating_to_num::(), + AlphaCurrency::from(value.saturating_to_num::()), ); } else { crate::TotalHotkeyAlpha::::remove(&(self.hotkey), self.netuid); diff --git a/pallets/subtensor/src/subnets/leasing.rs b/pallets/subtensor/src/subnets/leasing.rs index 967bed68f0..de4cbf3e5b 100644 --- a/pallets/subtensor/src/subnets/leasing.rs +++ b/pallets/subtensor/src/subnets/leasing.rs @@ -7,7 +7,7 @@ use frame_system::pallet_prelude::*; use sp_core::blake2_256; use sp_runtime::{Percent, traits::TrailingZeroInput}; use substrate_fixed::types::U64F64; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; use subtensor_swap_interface::SwapHandler; pub type LeaseId = u32; @@ -129,7 +129,7 @@ impl Pallet { let contributor_refund = share .saturating_mul(U64F64::from(leftover_cap)) .floor() - .to_num::(); + .saturating_to_num::(); ::Currency::transfer( &lease_coldkey, &contributor, @@ -235,7 +235,7 @@ impl Pallet { /// /// It will ensure the subnet has enough alpha in its liquidity pool before swapping it to tao to be distributed, /// and if not enough liquidity is available, it will accumulate the dividends for later distribution. - pub fn distribute_leased_network_dividends(lease_id: LeaseId, owner_cut_alpha: u64) { + pub fn distribute_leased_network_dividends(lease_id: LeaseId, owner_cut_alpha: AlphaCurrency) { // Ensure the lease exists let Some(lease) = SubnetLeases::::get(lease_id) else { log::debug!("Lease {lease_id} doesn't exists so we can't distribute dividends"); @@ -250,12 +250,13 @@ impl Pallet { // Get the actual amount of alpha to distribute from the owner's cut, // we voluntarily round up to favor the contributors - let current_contributors_cut_alpha = lease.emissions_share.mul_ceil(owner_cut_alpha); + let current_contributors_cut_alpha = + lease.emissions_share.mul_ceil(owner_cut_alpha.to_u64()); // Get the total amount of alpha to distribute from the contributors // including the dividends accumulated so far let total_contributors_cut_alpha = AccumulatedLeaseDividends::::get(lease_id) - .saturating_add(current_contributors_cut_alpha); + .saturating_add(current_contributors_cut_alpha.into()); // Ensure the distribution interval is not zero let rem = now @@ -310,7 +311,7 @@ impl Pallet { let tao_for_contributor = share .saturating_mul(U64F64::from(tao_unstaked)) .floor() - .to_num::(); + .saturating_to_num::(); Self::add_balance_to_coldkey_account(&contributor, tao_for_contributor); tao_distributed = tao_distributed.saturating_add(tao_for_contributor); } @@ -320,7 +321,7 @@ impl Pallet { Self::add_balance_to_coldkey_account(&lease.beneficiary, beneficiary_cut_tao); // Reset the accumulated dividends - AccumulatedLeaseDividends::::insert(lease_id, 0); + AccumulatedLeaseDividends::::insert(lease_id, AlphaCurrency::ZERO); } fn lease_coldkey(lease_id: LeaseId) -> T::AccountId { diff --git a/pallets/subtensor/src/subnets/registration.rs b/pallets/subtensor/src/subnets/registration.rs index a2eb180af1..d999c299e5 100644 --- a/pallets/subtensor/src/subnets/registration.rs +++ b/pallets/subtensor/src/subnets/registration.rs @@ -2,7 +2,7 @@ use super::*; use sp_core::{H256, U256}; use sp_io::hashing::{keccak_256, sha2_256}; use sp_runtime::Saturating; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{Currency, NetUid}; use subtensor_swap_interface::SwapHandler; use system::pallet_prelude::BlockNumberFor; @@ -141,10 +141,12 @@ impl Pallet { Self::remove_balance_from_coldkey_account(&coldkey, registration_cost)?; // Tokens are swapped and then burned. - let burned_alpha: u64 = + let burned_alpha = 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)); + SubnetAlphaOut::::mutate(netuid, |total| { + *total = total.saturating_sub(burned_alpha.into()) + }); // Actually perform the registration. let neuron_uid: u16 = Self::register_neuron(netuid, &hotkey); diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index dd8eeddcb0..1e9aaca229 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -193,10 +193,11 @@ impl Pallet { // Put initial TAO from lock into subnet TAO and produce numerically equal amount of Alpha // The initial TAO is the locked amount, with a minimum of 1 RAO and a cap of 100 TAO. let pool_initial_tao = Self::get_network_min_lock(); + let pool_initial_alpha = AlphaCurrency::from(Self::get_network_min_lock()); let actual_tao_lock_amount_less_pool_tao = actual_tao_lock_amount.saturating_sub(pool_initial_tao); SubnetTAO::::insert(netuid_to_register, pool_initial_tao); - SubnetAlphaIn::::insert(netuid_to_register, pool_initial_tao); + SubnetAlphaIn::::insert(netuid_to_register, pool_initial_alpha); SubnetOwner::::insert(netuid_to_register, coldkey.clone()); SubnetOwnerHotkey::::insert(netuid_to_register, hotkey.clone()); diff --git a/pallets/subtensor/src/subnets/uids.rs b/pallets/subtensor/src/subnets/uids.rs index c3028627e1..67c0a24c29 100644 --- a/pallets/subtensor/src/subnets/uids.rs +++ b/pallets/subtensor/src/subnets/uids.rs @@ -19,7 +19,7 @@ impl Pallet { /// Resets the trust, emission, consensus, incentive, dividends of the neuron to default pub fn clear_neuron(netuid: NetUid, neuron_uid: u16) { let neuron_index: usize = neuron_uid.into(); - Emission::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); + Emission::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0.into())); Trust::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); Consensus::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); Incentive::::mutate(netuid, |v| Self::set_element_at(v, neuron_index, 0)); @@ -101,7 +101,7 @@ impl Pallet { Rank::::mutate(netuid, |v| v.push(0)); Trust::::mutate(netuid, |v| v.push(0)); Active::::mutate(netuid, |v| v.push(true)); - Emission::::mutate(netuid, |v| v.push(0)); + Emission::::mutate(netuid, |v| v.push(0.into())); Consensus::::mutate(netuid, |v| v.push(0)); Incentive::::mutate(netuid, |v| v.push(0)); Dividends::::mutate(netuid, |v| v.push(0)); @@ -151,11 +151,11 @@ impl Pallet { /// Returns the stake of the uid on network or 0 if it doesnt exist. /// - pub fn get_stake_for_uid_and_subnetwork(netuid: NetUid, neuron_uid: u16) -> u64 { + pub fn get_stake_for_uid_and_subnetwork(netuid: NetUid, neuron_uid: u16) -> AlphaCurrency { if let Ok(hotkey) = Self::get_hotkey_for_net_and_uid(netuid, neuron_uid) { Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid) } else { - 0 + AlphaCurrency::ZERO } } diff --git a/pallets/subtensor/src/subnets/weights.rs b/pallets/subtensor/src/subnets/weights.rs index 427846938a..e234d62be4 100644 --- a/pallets/subtensor/src/subnets/weights.rs +++ b/pallets/subtensor/src/subnets/weights.rs @@ -269,12 +269,12 @@ impl Pallet { false => Self::get_epoch_index(netuid, cur_block), }; - CRV3WeightCommits::::try_mutate(netuid, cur_epoch, |commits| -> DispatchResult { + CRV3WeightCommitsV2::::try_mutate(netuid, cur_epoch, |commits| -> DispatchResult { // 6. Verify that the number of unrevealed commits is within the allowed limit. let unrevealed_commits_for_who = commits .iter() - .filter(|(account, _, _)| account == &who) + .filter(|(account, _, _, _)| account == &who) .count(); ensure!( unrevealed_commits_for_who < 10, @@ -284,7 +284,7 @@ impl Pallet { // 7. Append the new commit with calculated reveal blocks. // Hash the commit before it is moved, for the event let commit_hash = BlakeTwo256::hash(&commit); - commits.push_back((who.clone(), commit, reveal_round)); + commits.push_back((who.clone(), cur_block, commit, reveal_round)); // 8. Emit the WeightsCommitted event Self::deposit_event(Event::CRV3WeightsCommitted( @@ -1095,4 +1095,13 @@ impl Pallet { pub fn get_reveal_period(netuid: NetUid) -> u64 { RevealPeriodEpochs::::get(netuid) } + + pub fn get_first_block_of_epoch(netuid: NetUid, epoch: u64) -> u64 { + let tempo: u64 = Self::get_tempo(netuid) as u64; + let tempo_plus_one: u64 = tempo.saturating_add(1); + let netuid_plus_one: u64 = (u16::from(netuid) as u64).saturating_add(1); + epoch + .saturating_mul(tempo_plus_one) + .saturating_sub(netuid_plus_one) + } } diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index 9cb79a1002..1b6274db54 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -2,6 +2,8 @@ use super::*; use frame_support::weights::Weight; use sp_core::Get; use substrate_fixed::types::U64F64; +use subtensor_runtime_common::{Currency, NetUid}; + impl Pallet { /// Swaps the hotkey of a coldkey account. /// diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 90f0549f7c..12991094e5 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -6,6 +6,7 @@ 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_runtime_common::AlphaCurrency; use subtensor_swap_interface::SwapHandler; use crate::{utils::rate_limiting::TransactionType, *}; @@ -385,29 +386,41 @@ fn test_get_stake_for_hotkey_on_subnet() { mock_set_children(&coldkey1, &parent, netuid, &[(u64::MAX, child)]); // Stake 1000 to parent from coldkey1 SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent, &coldkey1, netuid, 1000, + &parent, + &coldkey1, + netuid, + 1000.into(), ); // Stake 1000 to parent from coldkey2 SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent, &coldkey2, netuid, 1000, + &parent, + &coldkey2, + netuid, + 1000.into(), ); // Stake 1000 to child from coldkey1 SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &child, &coldkey1, netuid, 1000, + &child, + &coldkey1, + netuid, + 1000.into(), ); // Stake 1000 to child from coldkey2 SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &child, &coldkey2, netuid, 1000, + &child, + &coldkey2, + netuid, + 1000.into(), ); let parent_stake = SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid); let child_stake = SubtensorModule::get_inherited_for_hotkey_on_subnet(&child, netuid); // The parent should have 0 stake as it's all allocated to the child - assert_eq!(parent_stake, 0); + assert_eq!(parent_stake, 0.into()); // The child should have its original stake (2000) plus the parent's stake (2000) - assert_eq!(child_stake, 4000); + assert_eq!(child_stake, 4000.into()); // Ensure total stake is preserved - assert_eq!(parent_stake + child_stake, 4000); + assert_eq!(parent_stake + child_stake, 4000.into()); }); } @@ -1463,7 +1476,7 @@ fn test_children_stake_values() { &hotkey, &coldkey, netuid, - 100_000_000_000_000, + 100_000_000_000_000.into(), ); // Set multiple children with proportions. @@ -1479,26 +1492,26 @@ fn test_children_stake_values() { assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid), - 25_000_000_069_849 + 25_000_000_069_849.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child1, netuid), - 24_999_999_976_716 + 24_999_999_976_716.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child2, netuid), - 24_999_999_976_716 + 24_999_999_976_716.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child3, netuid), - 24_999_999_976_716 + 24_999_999_976_716.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child3, netuid) + SubtensorModule::get_inherited_for_hotkey_on_subnet(&child2, netuid) + SubtensorModule::get_inherited_for_hotkey_on_subnet(&child1, netuid) + SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid), - 99999999999997 + 99999999999997.into() ); }); } @@ -1665,11 +1678,14 @@ fn test_get_stake_for_hotkey_on_subnet_basic() { add_network(netuid, 1, 0); register_ok_neuron(netuid, hotkey, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1000, + &hotkey, + &coldkey, + netuid, + 1000.into(), ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid), - 1000 + 1000.into() ); }); } @@ -1692,15 +1708,21 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_coldkeys() { register_ok_neuron(netuid, hotkey, coldkey1, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey1, netuid, 1000, + &hotkey, + &coldkey1, + netuid, + 1000.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey2, netuid, 2000, + &hotkey, + &coldkey2, + netuid, + 2000.into(), ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid), - 3000 + 3000.into() ); }); } @@ -1729,18 +1751,18 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { &parent, &coldkey, netuid, - 1_000_000_000, + 1_000_000_000.into(), ); mock_set_children_no_epochs(netuid, &parent, &[(u64::MAX, child)]); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid), - 0 + 0.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child, netuid), - 1_000_000_000 + 1_000_000_000.into() ); }); } @@ -1770,29 +1792,35 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_parents_single_child() { register_ok_neuron(netuid, child, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent1, &coldkey, netuid, 1000, + &parent1, + &coldkey, + netuid, + 1000.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent2, &coldkey, netuid, 2000, + &parent2, + &coldkey, + netuid, + 2000.into(), ); mock_set_children_no_epochs(netuid, &parent1, &[(u64::MAX / 2, child)]); mock_set_children_no_epochs(netuid, &parent2, &[(u64::MAX / 2, child)]); close( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent1, netuid), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent1, netuid).into(), 500, 10, "Incorrect inherited stake for parent1", ); close( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent2, netuid), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent2, netuid).into(), 1000, 10, "Incorrect inherited stake for parent2", ); close( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&child, netuid), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&child, netuid).into(), 1499, 10, "Incorrect inherited stake for child", @@ -1824,7 +1852,7 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { register_ok_neuron(netuid, child1, coldkey, 0); register_ok_neuron(netuid, child2, coldkey, 0); - let total_stake = 3000; + let total_stake = 3000.into(); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &parent, &coldkey, @@ -1844,18 +1872,18 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { // Check that the total stake is preserved close( - parent_stake + child1_stake + child2_stake, - total_stake, + (parent_stake + child1_stake + child2_stake).into(), + total_stake.into(), 10, "Total stake not preserved", ); // Check that the parent stake is slightly higher due to rounding - close(parent_stake, 1000, 10, "Parent stake incorrect"); + close(parent_stake.into(), 1000, 10, "Parent stake incorrect"); // Check that each child gets an equal share of the remaining stake - close(child1_stake, 1000, 10, "Child1 stake incorrect"); - close(child2_stake, 1000, 10, "Child2 stake incorrect"); + close(child1_stake.into(), 1000, 10, "Child1 stake incorrect"); + close(child2_stake.into(), 1000, 10, "Child2 stake incorrect"); // Log the actual stake values log::info!("Parent stake: {}", parent_stake); @@ -1889,7 +1917,7 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { register_ok_neuron(netuid, child2, coldkey, 0); // Set above old value of network max stake - let network_max_stake: u64 = 600_000_000_000_000; + let network_max_stake = 600_000_000_000_000.into(); // Increase stake to the network max SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -1910,8 +1938,8 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { log::info!("Child1 stake: {}", child1_stake); log::info!("Child2 stake: {}", child2_stake); - assert_eq!(parent_stake, 0, "Parent should have 0 stake"); - assert_eq!(child1_stake, 0, "Child1 should have 0 stake"); + assert_eq!(parent_stake, 0.into(), "Parent should have 0 stake"); + assert_eq!(child1_stake, 0.into(), "Child1 should have 0 stake"); assert_eq!( child2_stake, network_max_stake, "Child2 should have all the stake" @@ -1919,8 +1947,8 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { // Check that the total stake is preserved and equal to the network max stake close( - parent_stake + child1_stake + child2_stake, - network_max_stake, + (parent_stake + child1_stake + child2_stake).into(), + network_max_stake.into(), 10, "Total stake should equal network max stake", ); @@ -1959,7 +1987,7 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { register_ok_neuron(netuid, child2, coldkey_child2, 0); register_ok_neuron(netuid, grandchild, coldkey_grandchild, 0); - let total_stake = 1000; + let total_stake = 1000.into(); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &parent, &coldkey_parent, @@ -2015,11 +2043,22 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { log::info!("Child2 stake: {}", child2_stake_1); assert_eq!( - parent_stake_1, 0, + parent_stake_1, + 0.into(), "Parent should have 0 stake after distributing all stake to children" ); - close(child1_stake_1, 499, 10, "Child1 should have 499 stake"); - close(child2_stake_1, 499, 10, "Child2 should have 499 stake"); + close( + child1_stake_1.into(), + 499, + 10, + "Child1 should have 499 stake", + ); + close( + child2_stake_1.into(), + 499, + 10, + "Child2 should have 499 stake", + ); // Step 2: Set children for child1 mock_set_children_no_epochs(netuid, &child1, &[(u64::MAX, grandchild)]); @@ -2045,21 +2084,21 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { log::info!("Child2 stake: {}", child2_stake_2); log::info!("Grandchild stake: {}", grandchild_stake); - close(parent_stake_2, 0, 10, "Parent stake should remain 2"); + close(parent_stake_2.into(), 0, 10, "Parent stake should remain 2"); close( - child1_stake_2, + child1_stake_2.into(), 499, 10, "Child1 should still have 499 stake", ); close( - child2_stake_2, + child2_stake_2.into(), 499, 10, "Child2 should still have 499 stake", ); close( - grandchild_stake, + grandchild_stake.into(), 0, 10, "Grandchild should have 0 stake, as child1 doesn't have any owned stake", @@ -2067,8 +2106,8 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { // Check that the total stake is preserved close( - parent_stake_2 + child1_stake_2 + child2_stake_2 + grandchild_stake, - total_stake, + (parent_stake_2 + child1_stake_2 + child2_stake_2 + grandchild_stake).into(), + total_stake.into(), 10, "Total stake should equal the initial stake", ); @@ -2146,17 +2185,20 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_networks() { register_ok_neuron(netuid2, hotkey, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid1, 1000, + &hotkey, + &coldkey, + netuid1, + 1000.into(), ); close( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid1), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid1).into(), 1000, 10, "Stake on network 1 incorrect", ); close( - SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid2), + SubtensorModule::get_inherited_for_hotkey_on_subnet(&hotkey, netuid2).into(), 0, 10, "Stake on network 2 incorrect", @@ -2216,7 +2258,7 @@ fn test_do_remove_stake_clears_pending_childkeys() { 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Set non-default value for childkey stake threshold StakeThreshold::::set(1_000_000_000_000); @@ -2225,7 +2267,7 @@ fn test_do_remove_stake_clears_pending_childkeys() { RuntimeOrigin::signed(coldkey), hotkey, netuid, - StakeThreshold::::get() * 2 + (StakeThreshold::::get() * 2).into() )); let alpha = @@ -2293,7 +2335,7 @@ fn test_do_set_child_cooldown_period() { &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get().into(), ); // Schedule parent-child relationship @@ -2318,7 +2360,7 @@ fn test_do_set_child_cooldown_period() { &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get().into(), ); // Verify child assignment @@ -2366,7 +2408,7 @@ fn test_do_set_pending_children_runs_in_epoch() { &parent, &coldkey, netuid, - StakeThreshold::::get(), + StakeThreshold::::get().into(), ); // Schedule parent-child relationship @@ -2428,8 +2470,8 @@ fn test_revoke_child_no_min_stake_check() { 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); + mock::setup_reserves(netuid, reserve, reserve.into()); + mock::setup_reserves(NetUid::ROOT, reserve, reserve.into()); // Set minimum stake for setting children StakeThreshold::::put(1_000_000_000_000); @@ -2439,7 +2481,7 @@ fn test_revoke_child_no_min_stake_check() { &parent, &coldkey, NetUid::ROOT, - StakeThreshold::::get() + fee, + (StakeThreshold::::get() + fee).into(), ); // Schedule parent-child relationship @@ -2459,7 +2501,7 @@ fn test_revoke_child_no_min_stake_check() { &parent, &coldkey, NetUid::ROOT, - StakeThreshold::::get() + fee, + (StakeThreshold::::get() + fee).into(), ); // Ensure the childkeys are applied @@ -2506,7 +2548,7 @@ fn test_do_set_child_registration_disabled() { 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, reserve, reserve.into()); // Set minimum stake for setting children StakeThreshold::::put(1_000_000_000_000); @@ -2515,7 +2557,7 @@ fn test_do_set_child_registration_disabled() { &parent, &coldkey, netuid, - StakeThreshold::::get() + fee, + (StakeThreshold::::get() + fee).into(), ); // Disable subnet registrations @@ -2534,7 +2576,7 @@ fn test_do_set_child_registration_disabled() { &parent, &coldkey, netuid, - StakeThreshold::::get() + fee, + (StakeThreshold::::get() + fee).into(), ); // Ensure the childkeys are applied @@ -2644,13 +2686,13 @@ fn test_childkey_set_weights_single_parent() { &parent, &coldkey_parent, netuid, - stake_to_give_child, + stake_to_give_child.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &weight_setter, &coldkey_weight_setter, netuid, - 1_000_000, + 1_000_000.into(), ); SubtensorModule::set_weights_set_rate_limit(netuid, 0); @@ -2745,7 +2787,7 @@ fn test_set_weights_no_parent() { &hotkey, &coldkey, netuid, - stake_to_give_child, + stake_to_give_child.into(), ); SubtensorModule::set_weights_set_rate_limit(netuid, 0); @@ -2841,7 +2883,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); + mock::setup_reserves(netuid, stake * 10_000, (stake * 10_000).into()); 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); @@ -2956,7 +2998,7 @@ fn test_parent_child_chain_emission() { // Setup large LPs to prevent slippage SubnetTAO::::insert(netuid, 1_000_000_000_000_000); - SubnetAlphaIn::::insert(netuid, 1_000_000_000_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(1_000_000_000_000_000)); // Set owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); @@ -3000,19 +3042,25 @@ fn test_parent_child_chain_emission() { &hotkey_a, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(stake_a) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_a) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_b, &coldkey_b, netuid, - (total_alpha * I96F32::from_num(stake_b) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_b) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_c, &coldkey_c, netuid, - (total_alpha * I96F32::from_num(stake_c) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_c) / total_tao) + .saturating_to_num::() + .into(), ); // Get old stakes @@ -3064,7 +3112,7 @@ fn test_parent_child_chain_emission() { let emission: U96F32 = U96F32::from_num(SubtensorModule::get_block_emission().unwrap_or(0)); // Set pending emission to 0 - PendingEmission::::insert(netuid, 0); + PendingEmission::::insert(netuid, AlphaCurrency::ZERO); // Run epoch with emission value SubtensorModule::run_coinbase(emission); @@ -3127,7 +3175,7 @@ fn test_parent_child_chain_emission() { ); let hotkeys = [hotkey_a, hotkey_b, hotkey_c]; - let mut total_stake_now = 0; + let mut total_stake_now = AlphaCurrency::ZERO; for (hotkey, netuid, stake) in TotalHotkeyAlpha::::iter() { if hotkeys.contains(&hotkey) { total_stake_now += stake; @@ -3188,7 +3236,7 @@ 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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); // Swap to alpha let total_tao = I96F32::from_num(300_000 + 100_000 + 50_000); @@ -3201,19 +3249,25 @@ fn test_parent_child_chain_epoch() { &hotkey_a, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(300_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_b, &coldkey_b, netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(100_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_c, &coldkey_c, netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(50_000) / total_tao) + .saturating_to_num::() + .into(), ); // Get old stakes @@ -3259,7 +3313,7 @@ fn test_parent_child_chain_epoch() { let hardcoded_emission = I96F32::from_num(1_000_000); // 1 million (adjust as needed) let hotkey_emission = - SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::()); + SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::().into()); log::info!("hotkey_emission: {:?}", hotkey_emission); let total_emission: I96F32 = hotkey_emission .iter() @@ -3305,7 +3359,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); + mock::setup_reserves(netuid, 1_000_000_000_000_000, 1_000_000_000_000_000.into()); // Set owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); @@ -3338,19 +3392,25 @@ fn test_dividend_distribution_with_children() { &hotkey_a, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(300_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_b, &coldkey_b, netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(100_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_c, &coldkey_c, netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(50_000) / total_tao) + .saturating_to_num::() + .into(), ); // Get old stakes @@ -3389,8 +3449,8 @@ fn test_dividend_distribution_with_children() { let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed) - let hotkey_emission: Vec<(U256, u64, u64)> = - SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::()); + let hotkey_emission = + SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::().into()); log::info!("hotkey_emission: {:?}", hotkey_emission); let total_emission: I96F32 = hotkey_emission .iter() @@ -3424,17 +3484,17 @@ fn test_dividend_distribution_with_children() { let dividends_a = SubtensorModule::get_parent_child_dividends_distribution( &hotkey_a, netuid, - hardcoded_emission.saturating_to_num::(), + hardcoded_emission.saturating_to_num::().into(), ); let dividends_b = SubtensorModule::get_parent_child_dividends_distribution( &hotkey_b, netuid, - hardcoded_emission.saturating_to_num::(), + hardcoded_emission.saturating_to_num::().into(), ); let dividends_c = SubtensorModule::get_parent_child_dividends_distribution( &hotkey_c, netuid, - hardcoded_emission.saturating_to_num::(), + hardcoded_emission.saturating_to_num::().into(), ); log::info!("dividends_a: {:?}", dividends_a); log::info!("dividends_b: {:?}", dividends_b); @@ -3445,12 +3505,12 @@ fn test_dividend_distribution_with_children() { assert_eq!(dividends_a[0].0, hotkey_a); assert_eq!( dividends_a[0].1, - hardcoded_emission.saturating_to_num::() + hardcoded_emission.saturating_to_num::().into() ); assert_abs_diff_eq!( dividends_a .iter() - .map(|(_, emission)| *emission) + .map(|(_, emission)| u64::from(*emission)) .sum::(), hardcoded_emission.saturating_to_num::(), epsilon = (hardcoded_emission / 1000).saturating_to_num::() @@ -3465,21 +3525,21 @@ fn test_dividend_distribution_with_children() { assert_eq!(dividends_b.len(), 2); // A and B assert_eq!(dividends_b[1].0, hotkey_b); assert_abs_diff_eq!( - dividends_b[1].1, + u64::from(dividends_b[1].1), expected_b_b, epsilon = (hardcoded_emission / 1000).saturating_to_num::() ); let expected_b_a: u64 = hardcoded_emission.saturating_to_num::() - expected_b_b; assert_eq!(dividends_b[0].0, hotkey_a); assert_abs_diff_eq!( - dividends_b[0].1, + u64::from(dividends_b[0].1), expected_b_a, epsilon = (hardcoded_emission / 1000).saturating_to_num::() ); assert_abs_diff_eq!( dividends_b .iter() - .map(|(_, emission)| *emission) + .map(|(_, emission)| u64::from(*emission)) .sum::(), hardcoded_emission.saturating_to_num::(), epsilon = (hardcoded_emission / 1000).saturating_to_num::() @@ -3493,21 +3553,21 @@ fn test_dividend_distribution_with_children() { assert_eq!(dividends_c.len(), 2); // B and C assert_eq!(dividends_c[1].0, hotkey_c); assert_abs_diff_eq!( - dividends_c[1].1, + u64::from(dividends_c[1].1), expected_c_c, epsilon = (hardcoded_emission / 1000).saturating_to_num::() ); let expected_c_b: u64 = hardcoded_emission.saturating_to_num::() - expected_c_c; assert_eq!(dividends_c[0].0, hotkey_b); assert_abs_diff_eq!( - dividends_c[0].1, + u64::from(dividends_c[0].1), expected_c_b, epsilon = (hardcoded_emission / 1000).saturating_to_num::() ); assert_abs_diff_eq!( dividends_c .iter() - .map(|(_, emission)| *emission) + .map(|(_, emission)| u64::from(*emission)) .sum::(), hardcoded_emission.saturating_to_num::(), epsilon = (hardcoded_emission / 1000).saturating_to_num::() @@ -3555,7 +3615,7 @@ fn test_dynamic_parent_child_relationships() { 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Swap to alpha let total_tao = I96F32::from_num(500_000 + 50_000 + 30_000); @@ -3569,30 +3629,36 @@ fn test_dynamic_parent_child_relationships() { &parent, &coldkey_parent, netuid, - (total_alpha * I96F32::from_num(500_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(500_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &child1, &coldkey_child1, netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(50_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &child2, &coldkey_child2, netuid, - (total_alpha * I96F32::from_num(30_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(30_000) / total_tao) + .saturating_to_num::() + .into(), ); // Get old stakes - let stake_parent_0: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&parent, netuid); - let stake_child1_0: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&child1, netuid); - let stake_child2_0: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&child2, netuid); + let stake_parent_0 = SubtensorModule::get_stake_for_hotkey_on_subnet(&parent, netuid); + let stake_child1_0 = SubtensorModule::get_stake_for_hotkey_on_subnet(&child1, netuid); + let stake_child2_0 = SubtensorModule::get_stake_for_hotkey_on_subnet(&child2, netuid); log::info!("stake_parent_0: {:?}", stake_parent_0); log::info!("stake_child1_0: {:?}", stake_child1_0); log::info!("stake_child2_0: {:?}", stake_child2_0); - let total_stake_0: u64 = stake_parent_0 + stake_child1_0 + stake_child2_0; + let total_stake_0 = 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_alpha; @@ -3656,12 +3722,9 @@ fn test_dynamic_parent_child_relationships() { log::info!("total_stake_2: {:?}", total_stake_2); // Check final emission distribution - let stake_parent_2: u64 = - SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid); - let stake_child1_2: u64 = - SubtensorModule::get_inherited_for_hotkey_on_subnet(&child1, netuid); - let stake_child2_2: u64 = - SubtensorModule::get_inherited_for_hotkey_on_subnet(&child2, netuid); + let stake_parent_2 = SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid); + let stake_child1_2 = SubtensorModule::get_inherited_for_hotkey_on_subnet(&child1, netuid); + let stake_child2_2 = SubtensorModule::get_inherited_for_hotkey_on_subnet(&child2, netuid); let total_parent_stake = SubtensorModule::get_stake_for_hotkey_on_subnet(&parent, netuid); let _total_child1_stake = SubtensorModule::get_stake_for_hotkey_on_subnet(&child1, netuid); let _total_child2_stake = SubtensorModule::get_stake_for_hotkey_on_subnet(&child2, netuid); @@ -3679,14 +3742,14 @@ fn test_dynamic_parent_child_relationships() { let payout_2 = total_stake_2 - total_stake_1; log::info!("payout_2: {:?}", payout_2); - let total_emission: I96F32 = I96F32::from_num(payout_1 + payout_2); + let total_emission = I96F32::from_num(payout_1 + payout_2); #[allow(non_snake_case)] - let TOLERANCE: I96F32 = I96F32::from_num(0.001); // Allow for a small discrepancy due to potential rounding + let TOLERANCE = I96F32::from_num(0.001); // Allow for a small discrepancy due to potential rounding // Precise assertions with tolerance log::info!("total_emission: {:?}", total_emission); - let expected_parent_stake = ((I96F32::from_num(stake_parent_0) + let expected_parent_stake = ((I96F32::from_num(u64::from(stake_parent_0)) + total_emission * rel_stake_parent_0) * I96F32::from_num(5)) / I96F32::from_num(12); @@ -3704,7 +3767,7 @@ fn test_dynamic_parent_child_relationships() { // Second epoch: 5/12 parent_stake let expected_child1_stake = total_emission * rel_stake_child1_0 - + I96F32::from_num(stake_child1_0 + (total_parent_stake) / 4); + + I96F32::from_num(stake_child1_0 + total_parent_stake / 4.into()); assert!( (I96F32::from_num(stake_child1_2) - expected_child1_stake).abs() / expected_child1_stake @@ -3719,7 +3782,7 @@ fn test_dynamic_parent_child_relationships() { // Second epoch: 1/4 parent_stake + child1_stake let expected_child2_stake = total_emission * rel_stake_child2_0 - + I96F32::from_num(stake_child2_0 + (total_parent_stake) / 3); + + I96F32::from_num(u64::from(stake_child2_0 + total_parent_stake / 3.into())); assert!( (I96F32::from_num(stake_child2_2) - expected_child2_stake).abs() / expected_child2_stake @@ -3834,7 +3897,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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); // Define hotkeys and coldkeys let hotkey_a: U256 = U256::from(1); @@ -3860,18 +3923,22 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { &hotkey_a, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(300_000) / total_tao) + .saturating_to_num::() + .into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_b, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(100_000) / total_tao) + .saturating_to_num::() + .into(), ); // 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_a = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); + let stake_b = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b); // Assert initial stake is correct let rel_stake_a = I96F32::from_num(stake_a) / total_alpha; @@ -3897,8 +3964,8 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed) - let hotkey_emission: Vec<(U256, u64, u64)> = - SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::()); + let hotkey_emission = + SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::().into()); log::info!("hotkey_emission: {:?}", hotkey_emission); let total_emission: I96F32 = hotkey_emission .iter() @@ -3927,12 +3994,12 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { let dividends_a = SubtensorModule::get_parent_child_dividends_distribution( &hotkey_a, netuid, - hardcoded_emission.saturating_to_num::(), + hardcoded_emission.saturating_to_num::().into(), ); let dividends_b = SubtensorModule::get_parent_child_dividends_distribution( &hotkey_b, netuid, - hardcoded_emission.saturating_to_num::(), + hardcoded_emission.saturating_to_num::().into(), ); log::info!("dividends_a: {:?}", dividends_a); log::info!("dividends_b: {:?}", dividends_b); @@ -3942,12 +4009,12 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { assert_eq!(dividends_a[0].0, hotkey_a); assert_eq!( dividends_a[0].1, - hardcoded_emission.saturating_to_num::() + hardcoded_emission.saturating_to_num::().into() ); assert_abs_diff_eq!( dividends_a .iter() - .map(|(_, emission)| *emission) + .map(|(_, emission)| u64::from(*emission)) .sum::(), hardcoded_emission.saturating_to_num::(), epsilon = (hardcoded_emission / 1000).saturating_to_num::() @@ -3967,7 +4034,7 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { (rel_stake_b / total_stake_b * hardcoded_emission).saturating_to_num::(); assert_abs_diff_eq!( - dividends_b[1].1, + u64::from(dividends_b[1].1), expected_b_b, epsilon = (hardcoded_emission / 1000).saturating_to_num::(), ); @@ -3976,14 +4043,14 @@ fn test_dividend_distribution_with_children_same_coldkey_owner() { ((rel_stake_a * 1 / 2) / total_stake_b * hardcoded_emission).saturating_to_num::(); assert_eq!(dividends_b[0].0, hotkey_a); assert_abs_diff_eq!( - dividends_b[0].1, + u64::from(dividends_b[0].1), expected_b_a, epsilon = (hardcoded_emission / 1000).saturating_to_num::() ); assert_abs_diff_eq!( dividends_b .iter() - .map(|(_, emission)| *emission) + .map(|(_, emission)| u64::from(*emission)) .sum::(), hardcoded_emission.saturating_to_num::(), epsilon = (hardcoded_emission / 1000).saturating_to_num::() diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 5bcd7ed668..03fdf4227e 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -9,6 +9,7 @@ use frame_support::assert_ok; use pallet_subtensor_swap::position::PositionId; use sp_core::U256; use substrate_fixed::types::{I64F64, I96F32, U96F32}; +use subtensor_runtime_common::AlphaCurrency; #[allow(clippy::arithmetic_side_effects)] fn close(value: u64, target: u64, eps: u64) { @@ -52,7 +53,7 @@ fn test_dynamic_function_various_values() { // Set the price. SubnetMechanism::::insert(NetUid::from(1), 1); SubnetTAO::::insert(NetUid::from(1), (price * 1_000_000_000.0) as u64); - SubnetAlphaIn::::insert(NetUid::from(1), 1_000_000_000); + SubnetAlphaIn::::insert(NetUid::from(1), AlphaCurrency::from(1_000_000_000)); let (tao_in_emission, alpha_in_emission, alpha_out_emission) = SubtensorModule::get_dynamic_tao_emission(1.into(), tao_in, alpha_emission); assert!(tao_in_emission <= tao_in, "tao_in_emission is greater than tao_in"); assert!(alpha_in_emission <= alpha_emission, "alpha_in_emission is greater than alpha_emission"); @@ -189,7 +190,7 @@ fn test_coinbase_moving_prices() { add_network(netuid, 1, 0); // Set price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); - SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(1_000_000)); SubnetMechanism::::insert(netuid, 1); SubnetMovingPrice::::insert(netuid, I96F32::from_num(1)); FirstEmissionBlockNumber::::insert(netuid, 1); @@ -245,7 +246,7 @@ fn test_update_moving_price_initial() { add_network(netuid, 1, 0); // Set current price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); - SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(1_000_000)); SubnetMechanism::::insert(netuid, 1); SubnetMovingAlpha::::set(I96F32::from_num(0.5)); SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); @@ -270,7 +271,7 @@ fn test_update_moving_price_after_time() { add_network(netuid, 1, 0); // Set current price to 1.0 SubnetTAO::::insert(netuid, 1_000_000); - SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(1_000_000)); SubnetMechanism::::insert(netuid, 1); SubnetMovingAlpha::::set(I96F32::from_num(0.5)); SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); @@ -303,15 +304,21 @@ fn test_coinbase_alpha_issuance_base() { // Set up prices 1 and 1 let initial: u64 = 1_000_000; SubnetTAO::::insert(netuid1, initial); - SubnetAlphaIn::::insert(netuid1, initial); + SubnetAlphaIn::::insert(netuid1, AlphaCurrency::from(initial)); SubnetTAO::::insert(netuid2, initial); - SubnetAlphaIn::::insert(netuid2, initial); + SubnetAlphaIn::::insert(netuid2, AlphaCurrency::from(initial)); // Check initial SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 500_000 // alpha_in = 500_000/price = 500_000 - assert_eq!(SubnetAlphaIn::::get(netuid1), initial + emission / 2); - assert_eq!(SubnetAlphaIn::::get(netuid2), initial + emission / 2); + assert_eq!( + SubnetAlphaIn::::get(netuid1), + (initial + emission / 2).into() + ); + assert_eq!( + SubnetAlphaIn::::get(netuid2), + (initial + emission / 2).into() + ); }); } @@ -335,9 +342,9 @@ fn test_coinbase_alpha_issuance_different() { // Setup prices 1 and 1 let initial: u64 = 1_000_000; SubnetTAO::::insert(netuid1, initial); - SubnetAlphaIn::::insert(netuid1, initial); + SubnetAlphaIn::::insert(netuid1, AlphaCurrency::from(initial)); SubnetTAO::::insert(netuid2, initial); - SubnetAlphaIn::::insert(netuid2, initial); + SubnetAlphaIn::::insert(netuid2, AlphaCurrency::from(initial)); // Set subnet prices. SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); @@ -345,12 +352,15 @@ fn test_coinbase_alpha_issuance_different() { SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price = 333_333 + initial - assert_eq!(SubnetAlphaIn::::get(netuid1), initial + emission / 3); + assert_eq!( + SubnetAlphaIn::::get(netuid1), + (initial + emission / 3).into() + ); // tao_in = 666_666 // alpha_in = 666_666/price = 666_666 + initial assert_eq!( SubnetAlphaIn::::get(netuid2), - initial + emission / 3 + emission / 3 + (initial + emission / 3 + emission / 3).into() ); }); } @@ -371,9 +381,9 @@ fn test_coinbase_alpha_issuance_with_cap_trigger() { let initial: u64 = 1_000; let initial_alpha: u64 = initial * 1000000; SubnetTAO::::insert(netuid1, initial); - SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. + SubnetAlphaIn::::insert(netuid1, AlphaCurrency::from(initial_alpha)); // Make price extremely low. SubnetTAO::::insert(netuid2, initial); - SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. + SubnetAlphaIn::::insert(netuid2, AlphaCurrency::from(initial_alpha)); // Make price extremely low. // Set subnet prices. SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); @@ -383,16 +393,16 @@ fn test_coinbase_alpha_issuance_with_cap_trigger() { // alpha_in = 333_333/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha assert_eq!( SubnetAlphaIn::::get(netuid1), - initial_alpha + 1_000_000_000 + (initial_alpha + 1_000_000_000).into() ); - assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000); + assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000.into()); // tao_in = 666_666 // alpha_in = 666_666/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha assert_eq!( SubnetAlphaIn::::get(netuid2), - initial_alpha + 1_000_000_000 + (initial_alpha + 1_000_000_000).into() ); - assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000); // Gets full block emission. + assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000.into()); // Gets full block emission. }); } @@ -410,14 +420,14 @@ fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { SubnetMechanism::::insert(netuid2, 1); // Setup prices 1000000 let initial: u64 = 1_000; - let initial_alpha: u64 = initial * 1000000; + let initial_alpha = AlphaCurrency::from(initial * 1000000); SubnetTAO::::insert(netuid1, initial); SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. SubnetTAO::::insert(netuid2, initial); SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. // Set issuance to greater than 21M - SubnetAlphaOut::::insert(netuid1, 22_000_000_000_000_000); // Set issuance above 21M - SubnetAlphaOut::::insert(netuid2, 22_000_000_000_000_000); // Set issuance above 21M + SubnetAlphaOut::::insert(netuid1, AlphaCurrency::from(22_000_000_000_000_000)); // Set issuance above 21M + SubnetAlphaOut::::insert(netuid2, AlphaCurrency::from(22_000_000_000_000_000)); // Set issuance above 21M // Set subnet prices. SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); @@ -426,11 +436,17 @@ fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { // tao_in = 333_333 // alpha_in = 333_333/price > 1_000_000_000 --> 0 + initial_alpha assert_eq!(SubnetAlphaIn::::get(netuid1), initial_alpha); - assert_eq!(SubnetAlphaOut::::get(netuid2), 22_000_000_000_000_000); + assert_eq!( + SubnetAlphaOut::::get(netuid2), + 22_000_000_000_000_000.into() + ); // tao_in = 666_666 // alpha_in = 666_666/price > 1_000_000_000 --> 0 + initial_alpha assert_eq!(SubnetAlphaIn::::get(netuid2), initial_alpha); - assert_eq!(SubnetAlphaOut::::get(netuid2), 22_000_000_000_000_000); + assert_eq!( + SubnetAlphaOut::::get(netuid2), + 22_000_000_000_000_000.into() + ); // No emission. }); } @@ -441,14 +457,14 @@ 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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_subnet_owner_cut(0); SubtensorModule::run_coinbase(U96F32::from_num(0)); - assert_eq!(PendingOwnerCut::::get(netuid), 0); // No cut + assert_eq!(PendingOwnerCut::::get(netuid), 0.into()); // No cut SubtensorModule::set_subnet_owner_cut(u16::MAX); SubtensorModule::run_coinbase(U96F32::from_num(0)); - assert_eq!(PendingOwnerCut::::get(netuid), 1_000_000_000); // Full cut. + assert_eq!(PendingOwnerCut::::get(netuid), 1_000_000_000.into()); // Full cut. }); } @@ -459,34 +475,40 @@ 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); + mock::setup_reserves(netuid, 1_000_000, 1.into()); SubtensorModule::run_coinbase(U96F32::from_num(0)); - assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight and no root. + assert_eq!(PendingAlphaSwapped::::get(netuid), 0.into()); // Zero tao weight and no root. SubnetTAO::::insert(NetUid::ROOT, 1_000_000_000); // Add root weight. SubtensorModule::run_coinbase(U96F32::from_num(0)); - assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight with 1 root. + assert_eq!(PendingAlphaSwapped::::get(netuid), 0.into()); // Zero tao weight with 1 root. SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 SubtensorModule::run_coinbase(U96F32::from_num(0)); // 1 TAO / ( 1 + 3 ) = 0.25 * 1 / 2 = 125000000 assert_abs_diff_eq!( - PendingAlphaSwapped::::get(netuid), + u64::from(PendingAlphaSwapped::::get(netuid)), 125000000, epsilon = 1 ); assert_abs_diff_eq!( - PendingEmission::::get(netuid), + u64::from(PendingEmission::::get(netuid)), 1_000_000_000 - 125000000, epsilon = 1 ); // 1 - swapped. - assert_abs_diff_eq!(PendingRootDivs::::get(netuid), 125000000, epsilon = 1); // swapped * (price = 1) + assert_abs_diff_eq!( + u64::from(PendingRootDivs::::get(netuid)), + 125000000, + epsilon = 1 + ); // swapped * (price = 1) }); } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_drain_base --exact --show-output --nocapture #[test] fn test_drain_base() { - new_test_ext(1).execute_with(|| SubtensorModule::drain_pending_emission(0.into(), 0, 0, 0, 0)); + new_test_ext(1).execute_with(|| { + SubtensorModule::drain_pending_emission(0.into(), 0.into(), 0, 0.into(), 0.into()) + }); } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_drain_base_with_subnet --exact --show-output --nocapture @@ -495,7 +517,7 @@ fn test_drain_base_with_subnet() { new_test_ext(1).execute_with(|| { let netuid = NetUid::from(1); add_network(netuid, 1, 0); - SubtensorModule::drain_pending_emission(netuid, 0, 0, 0, 0) + SubtensorModule::drain_pending_emission(netuid, 0.into(), 0, 0.into(), 0.into()) }); } @@ -507,15 +529,21 @@ fn test_drain_base_with_subnet_with_single_staker_not_registered() { add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, stake_before, ); - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission( + netuid, + pending_alpha.into(), + 0, + 0.into(), + 0.into(), + ); let stake_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); assert_eq!(stake_before, stake_after); // Not registered. @@ -530,7 +558,7 @@ fn test_drain_base_with_subnet_with_single_staker_registered() { add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); register_ok_neuron(netuid, hotkey, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -538,11 +566,15 @@ fn test_drain_base_with_subnet_with_single_staker_registered() { netuid, stake_before, ); - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0.into(), 0.into()); let stake_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - close(stake_before + pending_alpha, stake_after, 10); // Registered gets all emission. + close( + (stake_before + pending_alpha).into(), + stake_after.into(), + 10, + ); // Registered gets all emission. }); } @@ -554,7 +586,7 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { add_network(netuid, 1, 0); let hotkey = U256::from(1); let coldkey = U256::from(2); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); // register_ok_neuron(root, hotkey, coldkey, 0); register_ok_neuron(netuid, hotkey, coldkey, 0); Delegates::::insert(hotkey, 0); @@ -571,10 +603,16 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { netuid, stake_before, ); - let pending_tao: u64 = 1_000_000_000; - let pending_alpha: u64 = 1_000_000_000; + let pending_tao = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); assert_eq!(SubnetTAO::::get(NetUid::ROOT), 0); - SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); + SubtensorModule::drain_pending_emission( + netuid, + pending_alpha, + pending_tao, + 0.into(), + 0.into(), + ); let stake_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); let root_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -582,8 +620,12 @@ fn test_drain_base_with_subnet_with_single_staker_registered_root_weight() { &coldkey, NetUid::ROOT, ); - close(stake_before + pending_alpha, stake_after, 10); // Registered gets all alpha emission. - close(stake_before + pending_tao, root_after, 10); // Registered gets all tao emission + close( + (stake_before + pending_alpha).into(), + stake_after.into(), + 10, + ); // Registered gets all alpha emission. + close(u64::from(stake_before) + pending_tao, root_after.into(), 10); // Registered gets all tao emission assert_eq!(SubnetTAO::::get(NetUid::ROOT), pending_tao); }); } @@ -597,7 +639,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered() { let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); let coldkey = U256::from(3); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); register_ok_neuron(netuid, hotkey1, coldkey, 0); register_ok_neuron(netuid, hotkey2, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -612,14 +654,22 @@ fn test_drain_base_with_subnet_with_two_stakers_registered() { netuid, stake_before, ); - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0.into(), 0.into()); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); let stake_after2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid); - close(stake_before + pending_alpha / 2, stake_after1, 10); // Registered gets 1/2 emission - close(stake_before + pending_alpha / 2, stake_after2, 10); // Registered gets 1/2 emission. + close( + (stake_before + pending_alpha / 2.into()).into(), + stake_after1.into(), + 10, + ); // Registered gets 1/2 emission + close( + (stake_before + pending_alpha / 2.into()).into(), + stake_after2.into(), + 10, + ); // Registered gets 1/2 emission. }); } @@ -632,7 +682,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); let coldkey = U256::from(3); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); register_ok_neuron(netuid, hotkey1, coldkey, 0); register_ok_neuron(netuid, hotkey2, coldkey, 0); Delegates::::insert(hotkey1, 0); @@ -663,9 +713,15 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { stake_before, ); let pending_tao: u64 = 1_000_000_000; - let pending_alpha: u64 = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); assert_eq!(SubnetTAO::::get(NetUid::ROOT), 0); - SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); + SubtensorModule::drain_pending_emission( + netuid, + pending_alpha, + pending_tao, + 0.into(), + 0.into(), + ); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -680,10 +736,26 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root() { &coldkey, NetUid::ROOT, ); - close(stake_before + pending_alpha / 2, stake_after1, 10); // Registered gets 1/2 emission - close(stake_before + pending_alpha / 2, stake_after2, 10); // Registered gets 1/2 emission. - close(stake_before + pending_tao / 2, root_after1, 10); // Registered gets 1/2 tao emission - close(stake_before + pending_tao / 2, root_after2, 10); // Registered gets 1/2 tao emission + close( + (stake_before + pending_alpha / 2.into()).into(), + stake_after1.into(), + 10, + ); // Registered gets 1/2 emission + close( + (stake_before + pending_alpha / 2.into()).into(), + stake_after2.into(), + 10, + ); // Registered gets 1/2 emission. + close( + u64::from(stake_before) + pending_tao / 2, + root_after1.into(), + 10, + ); // Registered gets 1/2 tao emission + close( + u64::from(stake_before) + pending_tao / 2, + root_after2.into(), + 10, + ); // Registered gets 1/2 tao emission assert_eq!(SubnetTAO::::get(NetUid::ROOT), pending_tao); }); } @@ -697,7 +769,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); let coldkey = U256::from(3); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); Delegates::::insert(hotkey1, 0); Delegates::::insert(hotkey2, 0); register_ok_neuron(netuid, hotkey1, coldkey, 0); @@ -713,7 +785,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am &hotkey1, &coldkey, NetUid::ROOT, - 2 * stake_before, // Hotkey 1 has twice as much root weight. + stake_before * 2.into(), // Hotkey 1 has twice as much root weight. ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, @@ -728,9 +800,15 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am stake_before, ); let pending_tao: u64 = 1_000_000_000; - let pending_alpha: u64 = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); assert_eq!(SubnetTAO::::get(NetUid::ROOT), 0); - SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); + SubtensorModule::drain_pending_emission( + netuid, + pending_alpha, + pending_tao, + 0.into(), + 0.into(), + ); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -747,16 +825,32 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am ); let expected_stake = I96F32::from_num(stake_before) + (I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0)); - assert_abs_diff_eq!(expected_stake.to_num::(), stake_after1, epsilon = 10); // Registered gets 50% of alpha emission + assert_abs_diff_eq!( + expected_stake.to_num::(), + stake_after1.into(), + epsilon = 10 + ); // Registered gets 50% of alpha emission let expected_stake2 = I96F32::from_num(stake_before) + I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0); - assert_abs_diff_eq!(expected_stake2.to_num::(), stake_after2, epsilon = 10); // Registered gets 50% emission - let expected_root1 = I96F32::from_num(2 * stake_before) + assert_abs_diff_eq!( + expected_stake2.to_num::(), + stake_after2.into(), + epsilon = 10 + ); // Registered gets 50% emission + let expected_root1 = I96F32::from_num(2 * u64::from(stake_before)) + I96F32::from_num(pending_tao) * I96F32::from_num(2.0 / 3.0); - assert_abs_diff_eq!(expected_root1.to_num::(), root_after1, epsilon = 10); // Registered gets 2/3 tao emission - let expected_root2 = I96F32::from_num(stake_before) + assert_abs_diff_eq!( + expected_root1.to_num::(), + root_after1.into(), + epsilon = 10 + ); // Registered gets 2/3 tao emission + let expected_root2 = I96F32::from_num(u64::from(stake_before)) + I96F32::from_num(pending_tao) * I96F32::from_num(1.0 / 3.0); - assert_abs_diff_eq!(expected_root2.to_num::(), root_after2, epsilon = 10); // Registered gets 1/3 tao emission + assert_abs_diff_eq!( + expected_root2.to_num::(), + root_after2.into(), + epsilon = 10 + ); // Registered gets 1/3 tao emission assert_abs_diff_eq!( SubnetTAO::::get(NetUid::ROOT), pending_tao, @@ -775,7 +869,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am let hotkey1 = U256::from(1); let hotkey2 = U256::from(2); let coldkey = U256::from(3); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); Delegates::::insert(hotkey1, 0); Delegates::::insert(hotkey2, 0); register_ok_neuron(netuid, hotkey1, coldkey, 0); @@ -791,7 +885,7 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am &hotkey1, &coldkey, NetUid::ROOT, - 2 * stake_before, // Hotkey 1 has twice as much root weight. + stake_before * 2.into(), // Hotkey 1 has twice as much root weight. ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, @@ -806,9 +900,15 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am stake_before, ); let pending_tao: u64 = 1_000_000_000; - let pending_alpha: u64 = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); assert_eq!(SubnetTAO::::get(NetUid::ROOT), 0); - SubtensorModule::drain_pending_emission(netuid, pending_alpha, pending_tao, 0, 0); + SubtensorModule::drain_pending_emission( + netuid, + pending_alpha, + pending_tao, + 0.into(), + 0.into(), + ); let stake_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); let root_after1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -825,18 +925,34 @@ fn test_drain_base_with_subnet_with_two_stakers_registered_and_root_different_am ); let expected_stake = I96F32::from_num(stake_before) + I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0); - assert_abs_diff_eq!(expected_stake.to_num::(), stake_after1, epsilon = 10); + assert_abs_diff_eq!( + expected_stake.to_num::(), + u64::from(stake_after1), + epsilon = 10 + ); let expected_stake2 = I96F32::from_num(stake_before) + I96F32::from_num(pending_alpha) * I96F32::from_num(1.0 / 2.0); - assert_abs_diff_eq!(expected_stake2.to_num::(), stake_after2, epsilon = 10); + assert_abs_diff_eq!( + expected_stake2.to_num::(), + u64::from(stake_after2), + epsilon = 10 + ); // hotkey 1 has 2 / 3 root tao - let expected_root1 = I96F32::from_num(2 * stake_before) + let expected_root1 = I96F32::from_num(2 * u64::from(stake_before)) + I96F32::from_num(pending_tao) * I96F32::from_num(2.0 / 3.0); - assert_abs_diff_eq!(expected_root1.to_num::(), root_after1, epsilon = 10); + assert_abs_diff_eq!( + expected_root1.to_num::(), + u64::from(root_after1), + epsilon = 10 + ); // hotkey 1 has 1 / 3 root tao - let expected_root2 = I96F32::from_num(stake_before) + let expected_root2 = I96F32::from_num(u64::from(stake_before)) + I96F32::from_num(pending_tao) * I96F32::from_num(1.0 / 3.0); - assert_abs_diff_eq!(expected_root2.to_num::(), root_after2, epsilon = 10); + assert_abs_diff_eq!( + expected_root2.to_num::(), + u64::from(root_after2), + epsilon = 10 + ); assert_abs_diff_eq!( SubnetTAO::::get(NetUid::ROOT), pending_tao, @@ -854,7 +970,7 @@ fn test_drain_alpha_childkey_parentkey() { let parent = U256::from(1); let child = U256::from(2); let coldkey = U256::from(3); - let stake_before: u64 = 1_000_000_000; + let stake_before = AlphaCurrency::from(1_000_000_000); register_ok_neuron(netuid, child, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &parent, @@ -867,8 +983,8 @@ fn test_drain_alpha_childkey_parentkey() { // Childkey take is 10% ChildkeyTake::::insert(child, netuid, u16::MAX / 10); - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(netuid, pending_alpha, 0, 0.into(), 0.into()); let parent_stake_after = SubtensorModule::get_stake_for_hotkey_on_subnet(&parent, netuid); let child_stake_after = SubtensorModule::get_stake_for_hotkey_on_subnet(&child, netuid); @@ -880,9 +996,9 @@ fn test_drain_alpha_childkey_parentkey() { expected.to_num::(), parent_stake_after ); - close(expected.to_num::(), parent_stake_after, 10_000); - let expected = I96F32::from_num(pending_alpha) / I96F32::from_num(10); - close(expected.to_num::(), child_stake_after, 10_000); + close(expected.to_num::(), parent_stake_after.into(), 10_000); + let expected = I96F32::from_num(u64::from(pending_alpha)) / I96F32::from_num(10); + close(expected.to_num::(), child_stake_after.into(), 10_000); }); } @@ -916,14 +1032,14 @@ fn test_get_root_children() { )); // Add stake for Alice and Bob on root. - let alice_root_stake: u64 = 1_000_000_000; + let alice_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold, NetUid::ROOT, alice_root_stake, ); - let bob_root_stake: u64 = 1_000_000_000; + let bob_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold, @@ -932,14 +1048,14 @@ fn test_get_root_children() { ); // Add stake for Alice and Bob on netuid. - let alice_alpha_stake: u64 = 1_000_000_000; + let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold, alpha, alice_alpha_stake, ); - let bob_alpha_stake: u64 = 1_000_000_000; + let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold, @@ -976,7 +1092,7 @@ fn test_get_root_children() { ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&alice, alpha), - 0 + 0.into() ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&bob, NetUid::ROOT), @@ -994,7 +1110,7 @@ fn test_get_root_children() { ); assert_eq!( SubtensorModule::get_tao_inherited_for_hotkey_on_subnet(&bob, alpha), - bob_root_stake + alice_root_stake + u64::from(bob_root_stake + alice_root_stake) ); // Get Alice stake amounts on subnet alpha. @@ -1005,7 +1121,10 @@ fn test_get_root_children() { // Get Bob stake amounts on subnet alpha. let (bob_total, bob_alpha, bob_tao): (I64F64, I64F64, I64F64) = SubtensorModule::get_stake_weights_for_hotkey_on_subnet(&bob, alpha); - assert_eq!(bob_total, I64F64::from_num(4 * bob_root_stake)); + assert_eq!( + bob_total, + I64F64::from_num(u64::from(bob_root_stake * 4.into())) + ); }); } @@ -1036,29 +1155,29 @@ fn test_get_root_children_drain() { bob, )); // Add stake for Alice and Bob on root. - let alice_root_stake: u64 = 1_000_000_000; + let alice_root_stake = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, NetUid::ROOT, - alice_root_stake, + alice_root_stake.into(), ); - let bob_root_stake: u64 = 1_000_000_000; + let bob_root_stake = 1_000_000_000; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, NetUid::ROOT, - alice_root_stake, + bob_root_stake.into(), ); // Add stake for Alice and Bob on netuid. - let alice_alpha_stake: u64 = 1_000_000_000; + let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, alpha, alice_alpha_stake, ); - let bob_alpha_stake: u64 = 1_000_000_000; + let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1083,35 +1202,47 @@ fn test_get_root_children_drain() { assert_eq!(bob_total, I64F64::from_num(4 * bob_root_stake)); // Lets drain - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission( + alpha, + pending_alpha, + 0, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + ); // Alice and Bob both made half of the dividends. assert_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, alpha), - alice_alpha_stake + pending_alpha / 2 + alice_alpha_stake + pending_alpha / 2.into() ); assert_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, alpha), - bob_alpha_stake + pending_alpha / 2 + bob_alpha_stake + pending_alpha / 2.into() ); // There should be no TAO on the root subnet. assert_eq!(SubnetTAO::::get(NetUid::ROOT), 0); // Lets drain - let pending_alpha: u64 = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); let pending_root1: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, pending_root1, 0, 0); + SubtensorModule::drain_pending_emission( + alpha, + pending_alpha, + pending_root1, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + ); // Alice and Bob both made half of the dividends. assert_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&alice, NetUid::ROOT), - alice_root_stake + pending_root1 / 2 + AlphaCurrency::from(alice_root_stake + pending_root1 / 2) ); assert_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&bob, NetUid::ROOT), - bob_root_stake + pending_root1 / 2 + AlphaCurrency::from(bob_root_stake + pending_root1 / 2) ); // The pending root dividends should be present in root subnet. @@ -1121,18 +1252,27 @@ fn test_get_root_children_drain() { ChildkeyTake::::insert(bob, alpha, u16::MAX); // Lets drain - let pending_alpha: u64 = 1_000_000_000; + let pending_alpha = AlphaCurrency::from(1_000_000_000); let pending_root2: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, pending_root2, 0, 0); + SubtensorModule::drain_pending_emission( + alpha, + pending_alpha, + pending_root2, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + ); // Alice makes nothing - assert_eq!(AlphaDividendsPerSubnet::::get(alpha, alice), 0); + assert_eq!( + AlphaDividendsPerSubnet::::get(alpha, alice), + AlphaCurrency::ZERO + ); assert_eq!(TaoDividendsPerSubnet::::get(alpha, alice), 0); // Bob makes it all. assert_abs_diff_eq!( AlphaDividendsPerSubnet::::get(alpha, bob), pending_alpha, - epsilon = 1 + epsilon = 1.into() ); assert_eq!( TaoDividendsPerSubnet::::get(alpha, bob), @@ -1173,14 +1313,14 @@ fn test_get_root_children_drain_half_proportion() { bob, )); // Add stake for Alice and Bob on root. - let alice_root_stake: u64 = 1_000_000_000; + let alice_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, NetUid::ROOT, alice_root_stake, ); - let bob_root_stake: u64 = 1_000_000_000; + let bob_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1188,14 +1328,14 @@ fn test_get_root_children_drain_half_proportion() { alice_root_stake, ); // Add stake for Alice and Bob on netuid. - let alice_alpha_stake: u64 = 1_000_000_000; + let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, alpha, alice_alpha_stake, ); - let bob_alpha_stake: u64 = 1_000_000_000; + let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1211,18 +1351,18 @@ fn test_get_root_children_drain_half_proportion() { Delegates::::insert(bob, 0); // Lets drain! - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0.into(), 0.into()); // Alice and Bob make the same amount. close( - AlphaDividendsPerSubnet::::get(alpha, alice), - pending_alpha / 2, + AlphaDividendsPerSubnet::::get(alpha, alice).into(), + (pending_alpha / 2.into()).into(), 10, ); close( - AlphaDividendsPerSubnet::::get(alpha, bob), - pending_alpha / 2, + AlphaDividendsPerSubnet::::get(alpha, bob).into(), + (pending_alpha / 2.into()).into(), 10, ); }); @@ -1255,14 +1395,14 @@ fn test_get_root_children_drain_with_take() { bob, )); // Add stake for Alice and Bob on root. - let alice_root_stake: u64 = 1_000_000_000; + let alice_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, NetUid::ROOT, alice_root_stake, ); - let bob_root_stake: u64 = 1_000_000_000; + let bob_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1270,14 +1410,14 @@ fn test_get_root_children_drain_with_take() { alice_root_stake, ); // Add stake for Alice and Bob on netuid. - let alice_alpha_stake: u64 = 1_000_000_000; + let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, alpha, alice_alpha_stake, ); - let bob_alpha_stake: u64 = 1_000_000_000; + let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1292,14 +1432,18 @@ fn test_get_root_children_drain_with_take() { Delegates::::insert(bob, 0); // Lets drain! - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0.into(), 0.into()); // Bob makes it all. - close(AlphaDividendsPerSubnet::::get(alpha, alice), 0, 10); close( - AlphaDividendsPerSubnet::::get(alpha, bob), - pending_alpha, + AlphaDividendsPerSubnet::::get(alpha, alice).into(), + 0, + 10, + ); + close( + AlphaDividendsPerSubnet::::get(alpha, bob).into(), + pending_alpha.into(), 10, ); }); @@ -1332,14 +1476,14 @@ fn test_get_root_children_drain_with_half_take() { bob, )); // Add stake for Alice and Bob on root. - let alice_root_stake: u64 = 1_000_000_000; + let alice_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, NetUid::ROOT, alice_root_stake, ); - let bob_root_stake: u64 = 1_000_000_000; + let bob_root_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1347,14 +1491,14 @@ fn test_get_root_children_drain_with_half_take() { alice_root_stake, ); // Add stake for Alice and Bob on netuid. - let alice_alpha_stake: u64 = 1_000_000_000; + let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &alice, &cold_alice, alpha, alice_alpha_stake, ); - let bob_alpha_stake: u64 = 1_000_000_000; + let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &bob, &cold_bob, @@ -1369,18 +1513,18 @@ fn test_get_root_children_drain_with_half_take() { Delegates::::insert(bob, 0); // Lets drain! - let pending_alpha: u64 = 1_000_000_000; - SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0, 0); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0.into(), 0.into()); // Alice and Bob make the same amount. close( - AlphaDividendsPerSubnet::::get(alpha, alice), - pending_alpha / 4, + AlphaDividendsPerSubnet::::get(alpha, alice).into(), + (pending_alpha / 4.into()).into(), 10000, ); close( - AlphaDividendsPerSubnet::::get(alpha, bob), - 3 * (pending_alpha / 4), + AlphaDividendsPerSubnet::::get(alpha, bob).into(), + 3 * u64::from(pending_alpha / 4.into()), 10000, ); }); @@ -1412,14 +1556,14 @@ fn test_get_root_children_drain_with_half_take() { // bob, // )); // // Add stake for Alice and Bob on root. -// let alice_root_stake: u64 = 1_000_000_000; +// let alice_root_stake = AlphaCurrency::from(1_000_000_000); // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &alice, // &cold, // NetUid::ROOT, // alice_root_stake, // ); -// let bob_root_stake: u64 = 1_000_000_000; +// let bob_root_stake = AlphaCurrency::from(1_000_000_000); // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &bob, // &cold, @@ -1427,14 +1571,14 @@ fn test_get_root_children_drain_with_half_take() { // alice_root_stake, // ); // // Add stake for Alice and Bob on netuid. -// let alice_alpha_stake: u64 = 1_000_000_000; +// let alice_alpha_stake = AlphaCurrency::from(1_000_000_000); // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &alice, // &cold, // alpha, // alice_alpha_stake, // ); -// let bob_alpha_stake: u64 = 1_000_000_000; +// let bob_alpha_stake = AlphaCurrency::from(1_000_000_000); // SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( // &bob, // &cold, @@ -1466,8 +1610,8 @@ fn test_get_root_children_drain_with_half_take() { // )); // // Lets drain! -// let pending_alpha: u64 = 1_000_000_000; -// SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0, 0); +// let pending_alpha = AlphaCurrency::from(1_000_000_000); +// SubtensorModule::drain_pending_emission(alpha, pending_alpha, 0, 0.into(), 0.into()); // // Alice and Bob make the same amount. // close( @@ -1496,22 +1640,22 @@ fn test_incentive_to_subnet_owner_is_burned() { let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); let pending_tao: u64 = 1_000_000_000; - let pending_alpha: u64 = 0; // None to valis - let owner_cut: u64 = 0; - let mut incentives: BTreeMap = BTreeMap::new(); + let pending_alpha = AlphaCurrency::ZERO; // None to valis + let owner_cut = AlphaCurrency::ZERO; + let mut incentives: BTreeMap = BTreeMap::new(); // Give incentive to other_hk - incentives.insert(other_hk, 10_000_000); + incentives.insert(other_hk, 10_000_000.into()); // Give incentives to subnet_owner_hk - incentives.insert(subnet_owner_hk, 10_000_000); + incentives.insert(subnet_owner_hk, 10_000_000.into()); // Verify stake before let subnet_owner_stake_before = SubtensorModule::get_stake_for_hotkey_on_subnet(&subnet_owner_hk, netuid); - assert_eq!(subnet_owner_stake_before, 0); + assert_eq!(subnet_owner_stake_before, 0.into()); let other_stake_before = SubtensorModule::get_stake_for_hotkey_on_subnet(&other_hk, netuid); - assert_eq!(other_stake_before, 0); + assert_eq!(other_stake_before, 0.into()); // Distribute dividends and incentives SubtensorModule::distribute_dividends_and_incentives( @@ -1525,27 +1669,27 @@ fn test_incentive_to_subnet_owner_is_burned() { // Verify stake after let subnet_owner_stake_after = SubtensorModule::get_stake_for_hotkey_on_subnet(&subnet_owner_hk, netuid); - assert_eq!(subnet_owner_stake_after, 0); + assert_eq!(subnet_owner_stake_after, 0.into()); let other_stake_after = SubtensorModule::get_stake_for_hotkey_on_subnet(&other_hk, netuid); - assert!(other_stake_after > 0); + assert!(other_stake_after > 0.into()); }); } #[test] fn test_calculate_dividend_distribution_totals() { new_test_ext(1).execute_with(|| { - let mut stake_map: BTreeMap = BTreeMap::new(); + let mut stake_map: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); - let pending_validator_alpha: u64 = 183_123_567_452; + let pending_validator_alpha = AlphaCurrency::from(183_123_567_452); let pending_tao: u64 = 837_120_949_872; let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. - stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); - stake_map.insert(hotkeys[1], (23_423, 859_273)); + stake_map.insert(hotkeys[0], (4_859_302.into(), 2_342_352.into())); + stake_map.insert(hotkeys[1], (23_423.into(), 859_273.into())); dividends.insert(hotkeys[0], 77_783_738_u64.into()); dividends.insert(hotkeys[1], 19_283_940_u64.into()); @@ -1563,7 +1707,7 @@ fn test_calculate_dividend_distribution_totals() { assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), - pending_validator_alpha, + u64::from(pending_validator_alpha), epsilon = 1_000 ); assert_abs_diff_eq!( @@ -1577,18 +1721,18 @@ fn test_calculate_dividend_distribution_totals() { #[test] fn test_calculate_dividend_distribution_total_only_tao() { new_test_ext(1).execute_with(|| { - let mut stake_map: BTreeMap = BTreeMap::new(); + let mut stake_map: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); - let pending_validator_alpha: u64 = 0; + let pending_validator_alpha = AlphaCurrency::ZERO; let pending_tao: u64 = 837_120_949_872; let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. - stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); - stake_map.insert(hotkeys[1], (23_423, 859_273)); + stake_map.insert(hotkeys[0], (4_859_302.into(), 2_342_352.into())); + stake_map.insert(hotkeys[1], (23_423.into(), 859_273.into())); dividends.insert(hotkeys[0], 77_783_738_u64.into()); dividends.insert(hotkeys[1], 19_283_940_u64.into()); @@ -1606,7 +1750,7 @@ fn test_calculate_dividend_distribution_total_only_tao() { assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), - pending_validator_alpha, + u64::from(pending_validator_alpha), epsilon = 1_000 ); assert_abs_diff_eq!( @@ -1620,18 +1764,18 @@ fn test_calculate_dividend_distribution_total_only_tao() { #[test] fn test_calculate_dividend_distribution_total_no_tao_weight() { new_test_ext(1).execute_with(|| { - let mut stake_map: BTreeMap = BTreeMap::new(); + let mut stake_map: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); - let pending_validator_alpha: u64 = 183_123_567_452; + let pending_validator_alpha = AlphaCurrency::from(183_123_567_452); let pending_tao: u64 = 0; // If tao weight is 0, then only alpha dividends should be input. let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. - stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); - stake_map.insert(hotkeys[1], (23_423, 859_273)); + stake_map.insert(hotkeys[0], (4_859_302.into(), 2_342_352.into())); + stake_map.insert(hotkeys[1], (23_423.into(), 859_273.into())); dividends.insert(hotkeys[0], 77_783_738_u64.into()); dividends.insert(hotkeys[1], 19_283_940_u64.into()); @@ -1649,7 +1793,7 @@ fn test_calculate_dividend_distribution_total_no_tao_weight() { assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), - pending_validator_alpha, + u64::from(pending_validator_alpha), epsilon = 1_000 ); assert_abs_diff_eq!( @@ -1663,18 +1807,18 @@ fn test_calculate_dividend_distribution_total_no_tao_weight() { #[test] fn test_calculate_dividend_distribution_total_only_alpha() { new_test_ext(1).execute_with(|| { - let mut stake_map: BTreeMap = BTreeMap::new(); + let mut stake_map: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); - let pending_validator_alpha: u64 = 183_123_567_452; + let pending_validator_alpha = AlphaCurrency::from(183_123_567_452); let pending_tao: u64 = 0; let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. - stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); - stake_map.insert(hotkeys[1], (23_423, 859_273)); + stake_map.insert(hotkeys[0], (4_859_302.into(), 2_342_352.into())); + stake_map.insert(hotkeys[1], (23_423.into(), 859_273.into())); dividends.insert(hotkeys[0], 77_783_738_u64.into()); dividends.insert(hotkeys[1], 19_283_940_u64.into()); @@ -1692,7 +1836,7 @@ fn test_calculate_dividend_distribution_total_only_alpha() { assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), - pending_validator_alpha, + u64::from(pending_validator_alpha), epsilon = 1_000 ); assert_abs_diff_eq!( @@ -1716,17 +1860,20 @@ fn test_calculate_dividend_and_incentive_distribution() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let pending_alpha = 123_456_789; - let pending_validator_alpha = pending_alpha / 2; // Pay half to validators. + let pending_alpha = AlphaCurrency::from(123_456_789); + let pending_validator_alpha = pending_alpha / 2.into(); // Pay half to validators. let pending_tao: u64 = 0; let pending_swapped = 0; // Only alpha output. let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% // Hotkey, Incentive, Dividend - let hotkey_emission = vec![(hotkey, pending_alpha / 2, pending_alpha / 2)]; + let hotkey_emission = vec![(hotkey, pending_alpha / 2.into(), pending_alpha / 2.into())]; let (incentives, (alpha_dividends, tao_dividends)) = SubtensorModule::calculate_dividend_and_incentive_distribution( @@ -1737,7 +1884,7 @@ fn test_calculate_dividend_and_incentive_distribution() { tao_weight, ); - let incentives_total = incentives.values().sum::(); + let incentives_total = incentives.values().copied().map(u64::from).sum::(); let dividends_total = alpha_dividends .values() .sum::() @@ -1745,7 +1892,7 @@ fn test_calculate_dividend_and_incentive_distribution() { assert_abs_diff_eq!( dividends_total.saturating_add(incentives_total), - pending_alpha, + u64::from(pending_alpha), epsilon = 2 ); }); @@ -1764,16 +1911,19 @@ fn test_calculate_dividend_and_incentive_distribution_all_to_validators() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let pending_alpha = 123_456_789; + let pending_alpha = AlphaCurrency::from(123_456_789); let pending_validator_alpha = pending_alpha; // Pay all to validators. let pending_tao: u64 = 0; let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% // Hotkey, Incentive, Dividend - let hotkey_emission = vec![(hotkey, 0, pending_alpha)]; + let hotkey_emission = vec![(hotkey, 0.into(), pending_alpha)]; let (incentives, (alpha_dividends, tao_dividends)) = SubtensorModule::calculate_dividend_and_incentive_distribution( @@ -1784,14 +1934,14 @@ fn test_calculate_dividend_and_incentive_distribution_all_to_validators() { tao_weight, ); - let incentives_total = incentives.values().sum::(); + let incentives_total = incentives.values().copied().map(u64::from).sum::(); let dividends_total = alpha_dividends .values() .sum::() .saturating_to_num::(); assert_eq!( - dividends_total.saturating_add(incentives_total), + AlphaCurrency::from(dividends_total.saturating_add(incentives_total)), pending_alpha ); }); @@ -1810,12 +1960,15 @@ fn test_calculate_dividends_and_incentives() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let divdends: u64 = 123_456_789; - let incentive: u64 = 683_051_923; - let total_emission: u64 = divdends.saturating_add(incentive); + let divdends = AlphaCurrency::from(123_456_789); + let incentive = AlphaCurrency::from(683_051_923); + let total_emission = divdends.saturating_add(incentive); // Hotkey, Incentive, Dividend let hotkey_emission = vec![(hotkey, incentive, divdends)]; @@ -1823,11 +1976,16 @@ fn test_calculate_dividends_and_incentives() { let (incentives, dividends) = SubtensorModule::calculate_dividends_and_incentives(netuid, hotkey_emission); - let incentives_total = incentives.values().sum::(); - let dividends_total = dividends + let incentives_total = incentives .values() - .sum::() - .saturating_to_num::(); + .copied() + .fold(AlphaCurrency::ZERO, |acc, x| acc + x); + let dividends_total = AlphaCurrency::from( + dividends + .values() + .sum::() + .saturating_to_num::(), + ); assert_eq!( dividends_total.saturating_add(incentives_total), @@ -1849,11 +2007,14 @@ fn test_calculate_dividends_and_incentives_only_validators() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let divdends: u64 = 123_456_789; - let incentive: u64 = 0; + let divdends = AlphaCurrency::from(123_456_789); + let incentive = AlphaCurrency::ZERO; // Hotkey, Incentive, Dividend let hotkey_emission = vec![(hotkey, incentive, divdends)]; @@ -1861,14 +2022,19 @@ fn test_calculate_dividends_and_incentives_only_validators() { let (incentives, dividends) = SubtensorModule::calculate_dividends_and_incentives(netuid, hotkey_emission); - let incentives_total = incentives.values().sum::(); - let dividends_total = dividends + let incentives_total = incentives .values() - .sum::() - .saturating_to_num::(); + .copied() + .fold(AlphaCurrency::ZERO, |acc, x| acc + x); + let dividends_total = AlphaCurrency::from( + dividends + .values() + .sum::() + .saturating_to_num::(), + ); assert_eq!(dividends_total, divdends); - assert_eq!(incentives_total, 0); + assert_eq!(incentives_total, AlphaCurrency::ZERO); }); } @@ -1885,11 +2051,14 @@ fn test_calculate_dividends_and_incentives_only_miners() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let divdends: u64 = 0; - let incentive: u64 = 123_456_789; + let divdends = AlphaCurrency::ZERO; + let incentive = AlphaCurrency::from(123_456_789); // Hotkey, Incentive, Dividend let hotkey_emission = vec![(hotkey, incentive, divdends)]; @@ -1897,11 +2066,16 @@ fn test_calculate_dividends_and_incentives_only_miners() { let (incentives, dividends) = SubtensorModule::calculate_dividends_and_incentives(netuid, hotkey_emission); - let incentives_total = incentives.values().sum::(); - let dividends_total = dividends + let incentives_total = incentives .values() - .sum::() - .saturating_to_num::(); + .copied() + .fold(AlphaCurrency::ZERO, |acc, x| acc + x); + let dividends_total = AlphaCurrency::from( + dividends + .values() + .sum::() + .saturating_to_num::(), + ); assert_eq!(incentives_total, incentive); assert_eq!(dividends_total, divdends); @@ -1914,11 +2088,14 @@ fn test_drain_pending_emission_no_miners_all_drained() { let netuid = add_dynamic_network(&U256::from(1), &U256::from(2)); let hotkey = U256::from(3); let coldkey = U256::from(4); - let init_stake: u64 = 1; + let init_stake = 1; register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero stake SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, init_stake, + &hotkey, + &coldkey, + netuid, + init_stake.into(), ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey), @@ -1929,15 +2106,19 @@ fn test_drain_pending_emission_no_miners_all_drained() { SubtensorModule::set_tao_weight(0); // Set the emission to be 1 million. - let emission: u64 = 1_000_000; + let emission = AlphaCurrency::from(1_000_000); // Run drain pending without any miners. - SubtensorModule::drain_pending_emission(netuid, emission, 0, 0, 0); + SubtensorModule::drain_pending_emission(netuid, emission, 0, 0.into(), 0.into()); // Get the new stake of the hotkey. let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey); // We expect this neuron to get *all* the emission. // Slight epsilon due to rounding (hotkey_take). - assert_abs_diff_eq!(new_stake, emission.saturating_add(init_stake), epsilon = 1); + assert_abs_diff_eq!( + new_stake, + u64::from(emission.saturating_add(init_stake.into())), + epsilon = 1 + ); }); } @@ -1959,7 +2140,10 @@ fn test_drain_pending_emission_zero_emission() { register_ok_neuron(netuid, miner_hk, miner_ck, 0); // Give non-zero stake SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, init_stake, + &hotkey, + &coldkey, + netuid, + init_stake.into(), ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey), @@ -1972,7 +2156,7 @@ fn test_drain_pending_emission_zero_emission() { run_to_block_no_epoch(netuid, 50); // Run epoch for initial setup. - SubtensorModule::epoch(netuid, 0); + SubtensorModule::epoch(netuid, AlphaCurrency::ZERO); // Set weights on miner assert_ok!(SubtensorModule::set_weights( @@ -1990,7 +2174,7 @@ fn test_drain_pending_emission_zero_emission() { Dividends::::remove(netuid); // Set the emission to be ZERO. - SubtensorModule::drain_pending_emission(netuid, 0, 0, 0, 0); + SubtensorModule::drain_pending_emission(netuid, 0.into(), 0, 0.into(), 0.into()); // Get the new stake of the hotkey. let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey); @@ -2029,14 +2213,17 @@ fn test_run_coinbase_not_started() { SubtensorModule::set_weights_set_rate_limit(netuid, 0); let reserve = init_stake * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); 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); // Give non-zero stake SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, init_stake, + &hotkey, + &coldkey, + netuid, + init_stake.into(), ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey), @@ -2049,7 +2236,7 @@ fn test_run_coinbase_not_started() { run_to_block_no_epoch(netuid, 30); // Run epoch for initial setup. - SubtensorModule::epoch(netuid, 0); + SubtensorModule::epoch(netuid, AlphaCurrency::ZERO); // Set weights on miner assert_ok!(SubtensorModule::set_weights( @@ -2118,7 +2305,10 @@ fn test_run_coinbase_not_started_start_after() { register_ok_neuron(netuid, sn_owner_hk, sn_owner_ck, 0); // Give non-zero stake SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, init_stake, + &hotkey, + &coldkey, + netuid, + init_stake.into(), ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey), @@ -2131,7 +2321,7 @@ fn test_run_coinbase_not_started_start_after() { run_to_block_no_epoch(netuid, 30); // Run epoch for initial setup. - SubtensorModule::epoch(netuid, 0); + SubtensorModule::epoch(netuid, AlphaCurrency::ZERO); // Set weights on miner assert_ok!(SubtensorModule::set_weights( diff --git a/pallets/subtensor/src/tests/consensus.rs b/pallets/subtensor/src/tests/consensus.rs index b11cd44e06..0afca99445 100644 --- a/pallets/subtensor/src/tests/consensus.rs +++ b/pallets/subtensor/src/tests/consensus.rs @@ -189,7 +189,7 @@ fn init_run_epochs( &U256::from(key), &U256::from(key), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); @@ -200,7 +200,7 @@ fn init_run_epochs( SubtensorModule::get_max_allowed_validators(netuid), validators.len() as u16 ); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators run_to_block(1); // run to next block to ensure weights are set on nodes after their registration block // === Set weights @@ -251,9 +251,9 @@ fn init_run_epochs( let start = Instant::now(); for _ in 0..epochs { if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } } let duration = start.elapsed(); diff --git a/pallets/subtensor/src/tests/delegate_info.rs b/pallets/subtensor/src/tests/delegate_info.rs index 8168755439..22b2aab2bf 100644 --- a/pallets/subtensor/src/tests/delegate_info.rs +++ b/pallets/subtensor/src/tests/delegate_info.rs @@ -135,7 +135,7 @@ fn test_get_delegated() { .or_default() .entry(*delegate) .or_default(); - stakes.insert(*netuid, expected_stake); + stakes.insert(*netuid, expected_stake.into()); } } @@ -149,7 +149,7 @@ fn test_get_delegated() { coldkey_stakes_map.get(&delegate_info.delegate_ss58) { if let Some(expected_stake) = expected_under_delegate.get(&netuid.0) { - assert_eq!(u64::from(*staked), *expected_stake); + assert_eq!(u64::from(staked.0), *expected_stake); } else { panic!("Netuid {} not found in expected stake map", netuid.0); }; diff --git a/pallets/subtensor/src/tests/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index dc36173da4..c682417bab 100644 --- a/pallets/subtensor/src/tests/epoch.rs +++ b/pallets/subtensor/src/tests/epoch.rs @@ -11,6 +11,7 @@ use frame_support::{assert_err, assert_ok}; use rand::{Rng, SeedableRng, distributions::Uniform, rngs::StdRng, seq::SliceRandom, thread_rng}; use sp_core::{Get, U256}; use substrate_fixed::types::I32F32; +use subtensor_runtime_common::AlphaCurrency; use subtensor_swap_interface::SwapHandler; use super::mock::*; @@ -182,7 +183,7 @@ fn init_run_epochs( &U256::from(key), &U256::from(key), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); @@ -193,7 +194,7 @@ fn init_run_epochs( SubtensorModule::get_max_allowed_validators(netuid), validators.len() as u16 ); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators run_to_block(1); // run to next block to ensure weights are set on nodes after their registration block // === Set weights @@ -244,9 +245,9 @@ fn init_run_epochs( let start = Instant::now(); for _ in 0..epochs { if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } } let duration = start.elapsed(); @@ -589,7 +590,7 @@ fn test_1_graph() { )); // SubtensorModule::set_weights_for_testing( netuid, i as u16, vec![ ( 0, u16::MAX )]); // doesn't set update status // SubtensorModule::set_bonds_for_testing( netuid, uid, vec![ ( 0, u16::MAX )]); // rather, bonds are calculated in epoch - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); assert_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey), stake_amount @@ -623,7 +624,7 @@ fn test_10_graph() { &hotkey, &coldkey, netuid, - stake_amount, + stake_amount.into(), ); SubtensorModule::append_neuron(netuid, &hotkey, 0); assert_eq!(SubtensorModule::get_subnetwork_n(netuid) - 1, uid); @@ -649,7 +650,7 @@ fn test_10_graph() { )); } // Run the epoch. - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // Check return values. for i in 0..n { assert_eq!( @@ -663,7 +664,7 @@ fn test_10_graph() { assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, i as u16), 0); assert_eq!( SubtensorModule::get_emission_for_uid(netuid, i as u16), - 99999999 + 99999999.into() ); } }); @@ -718,7 +719,10 @@ fn test_512_graph() { assert_eq!(SubtensorModule::get_consensus_for_uid(netuid, uid), 0); assert_eq!(SubtensorModule::get_incentive_for_uid(netuid, uid), 0); assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, uid), 1023); // Note D = floor(1 / 64 * 65_535) = 1023 - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, uid), 7812500); // Note E = 0.5 / 200 * 1_000_000_000 = 7_812_500 + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, uid), + 7812500.into() + ); // Note E = 0.5 / 200 * 1_000_000_000 = 7_812_500 assert_eq!(bonds[uid as usize][validator], 0.0); assert_eq!(bonds[uid as usize][server], I32F32::from_num(65_535)); // Note B_ij = floor(1 / 64 * 65_535) / 65_535 = 1023 / 65_535, then max-upscaled to 65_535 @@ -733,7 +737,10 @@ fn test_512_graph() { assert_eq!(SubtensorModule::get_consensus_for_uid(netuid, uid), 146); // Note C = floor(1 / (512 - 64) * 65_535) = 146 assert_eq!(SubtensorModule::get_incentive_for_uid(netuid, uid), 146); // Note I = floor(1 / (512 - 64) * 65_535) = 146 assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, uid), 0); - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, uid), 1116071); // Note E = floor(0.5 / (512 - 64) * 1_000_000_000) = 1_116_071 + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, uid), + 1116071.into() + ); // Note E = floor(0.5 / (512 - 64) * 1_000_000_000) = 1_116_071 assert_eq!(bonds[uid as usize][validator], 0.0); assert_eq!(bonds[uid as usize][server], 0.0); } @@ -766,7 +773,7 @@ fn test_512_graph_random_weights() { Vec, Vec, Vec, - Vec, + Vec, Vec, Vec, ) = (vec![], vec![], vec![], vec![], vec![], vec![]); @@ -1016,7 +1023,7 @@ fn test_bonds() { SubtensorModule::add_balance_to_coldkey_account( &U256::from(key), max_stake ); let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, block_number, key * 1_000_000, &U256::from(key)); assert_ok!(SubtensorModule::register(<::RuntimeOrigin>::signed(U256::from(key)), netuid, block_number, nonce, work, U256::from(key), U256::from(key))); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(key), &U256::from(key), netuid, stakes[key as usize] ); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &U256::from(key), &U256::from(key), netuid, stakes[key as usize].into() ); } assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), n); assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); @@ -1024,15 +1031,15 @@ fn test_bonds() { // === Issue validator permits SubtensorModule::set_max_allowed_validators(netuid, n); assert_eq!( SubtensorModule::get_max_allowed_validators(netuid), n); - SubtensorModule::epoch( netuid, 1_000_000_000 ); // run first epoch to set allowed validators + SubtensorModule::epoch( netuid, 1_000_000_000 .into()); // run first epoch to set allowed validators next_block_no_epoch(netuid); // run to next block to ensure weights are set on nodes after their registration block // === Set weights [val->srv1: 0.1, val->srv2: 0.2, val->srv3: 0.3, val->srv4: 0.4] for uid in 0..(n/2) as u64 { assert_ok!(SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(uid)), netuid, ((n/2)..n).collect(), vec![ u16::MAX/4, u16::MAX/2, (u16::MAX/4)*3, u16::MAX], 0)); } - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 .into()); } /* n: 8 current_block: 1; activity_cutoff: 5000; Last update: [1, 1, 1, 1, 0, 0, 0, 0] Inactive: [false, false, false, false, false, false, false, false] @@ -1077,8 +1084,8 @@ fn test_bonds() { assert_ok!(SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(uid)), netuid, vec![uid], vec![u16::MAX], 0)); next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* n: 8 current_block: 2 activity_cutoff: 5000 @@ -1125,8 +1132,8 @@ fn test_bonds() { assert_ok!(SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(uid)), netuid, vec![uid], vec![u16::MAX], 0)); next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 3 W: [[(0, 65535)], [(1, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] W (permit): [[(0, 65535)], [(1, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] @@ -1162,8 +1169,8 @@ fn test_bonds() { assert_ok!(SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(uid)), netuid, vec![uid], vec![u16::MAX], 0)); next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 4 W: [[(0, 65535)], [(1, 65535)], [(2, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] W (permit): [[(0, 65535)], [(1, 65535)], [(2, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] @@ -1198,8 +1205,8 @@ fn test_bonds() { assert_ok!(SubtensorModule::set_weights(RuntimeOrigin::signed(U256::from(2)), netuid, vec![7], vec![u16::MAX], 0)); next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 5 W: [[(0, 65535)], [(1, 65535)], [(7, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] W (permit): [[(0, 65535)], [(1, 65535)], [(7, 65535)], [(4, 16383), (5, 32767), (6, 49149), (7, 65535)], [], [], [], []] @@ -1232,8 +1239,8 @@ fn test_bonds() { next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 6 B: [[(4, 12601), (5, 12601), (6, 12601), (7, 10951)], [(4, 28319), (5, 28319), (6, 28319), (7, 24609)], [(4, 49149), (5, 49149), (6, 49149), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] B (outdatedmask): [[(4, 12601), (5, 12601), (6, 12601), (7, 10951)], [(4, 28319), (5, 28319), (6, 28319), (7, 24609)], [(4, 49149), (5, 49149), (6, 49149), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] @@ -1254,8 +1261,8 @@ fn test_bonds() { next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 7 B: [[(4, 12600), (5, 12600), (6, 12600), (7, 9559)], [(4, 28318), (5, 28318), (6, 28318), (7, 21482)], [(4, 49148), (5, 49148), (6, 49148), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] B (outdatedmask): [[(4, 12600), (5, 12600), (6, 12600), (7, 9559)], [(4, 28318), (5, 28318), (6, 28318), (7, 21482)], [(4, 49148), (5, 49148), (6, 49148), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] @@ -1276,8 +1283,8 @@ fn test_bonds() { next_block_no_epoch(netuid); - if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 ); } - else { SubtensorModule::epoch_dense( netuid, 1_000_000_000 ); } + if sparse { SubtensorModule::epoch( netuid, 1_000_000_000 .into()); } + else { SubtensorModule::epoch_dense( netuid, 1_000_000_000.into() ); } /* current_block: 8 B: [[(4, 12599), (5, 12599), (6, 12599), (7, 8376)], [(4, 28317), (5, 28317), (6, 28317), (7, 18824)], [(4, 49147), (5, 49147), (6, 49147), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] B (outdatedmask): [[(4, 12599), (5, 12599), (6, 12599), (7, 8376)], [(4, 28317), (5, 28317), (6, 28317), (7, 18824)], [(4, 49147), (5, 49147), (6, 49147), (7, 49150)], [(4, 65535), (5, 65535), (6, 65535), (7, 65535)], [], [], [], []] @@ -1377,7 +1384,7 @@ fn test_active_stake() { &U256::from(key), &U256::from(key), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), n); @@ -1386,7 +1393,7 @@ fn test_active_stake() { // === Issue validator permits SubtensorModule::set_max_allowed_validators(netuid, n); assert_eq!(SubtensorModule::get_max_allowed_validators(netuid), n); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators next_block_no_epoch(netuid); // run to next block to ensure weights are set on nodes after their registration block // === Set weights [val1->srv1: 0.5, val1->srv2: 0.5, val2->srv1: 0.5, val2->srv2: 0.5] @@ -1400,9 +1407,9 @@ fn test_active_stake() { )); } if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } let bonds = SubtensorModule::get_bonds(netuid); for uid in 0..n { @@ -1415,7 +1422,7 @@ fn test_active_stake() { } assert_eq!( SubtensorModule::get_emission_for_uid(netuid, uid), - 250000000 + 250000000.into() ); // Note E = 0.5 / (n/2) * 1_000_000_000 = 250_000_000 } for bond in bonds.iter().take((n / 2) as usize) { @@ -1439,9 +1446,9 @@ fn test_active_stake() { 0 )); if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 5002; activity_cutoff: 5000 Last update: [5002, 1, 0, 0]; Inactive: [false, true, true, true]; Block at registration: [0, 0, 0, 0] @@ -1471,7 +1478,10 @@ fn test_active_stake() { P (u16): [65535, 53619, 59577, 59577] */ let bonds = SubtensorModule::get_bonds(netuid); assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, 0), 36044); // Note D = floor((0.5 * 0.9 + 0.1) * 65_535) - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, 0), 274999999); // Note E = 0.5 * 0.55 * 1_000_000_000 = 275_000_000 (discrepancy) + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, 0), + 274999999.into() + ); // Note E = 0.5 * 0.55 * 1_000_000_000 = 275_000_000 (discrepancy) for server in ((n / 2) as usize)..n as usize { assert_eq!(bonds[0][server], I32F32::from_num(65_535)); // floor(0.55*(2^16-1))/(2^16-1), then max-upscale } @@ -1482,7 +1492,7 @@ fn test_active_stake() { ); // Note D = floor((0.5 * 0.9) * 65_535) assert_eq!( SubtensorModule::get_emission_for_uid(netuid, validator), - 224999999 + 224999999.into() ); // Note E = 0.5 * 0.45 * 1_000_000_000 = 225_000_000 (discrepancy) for server in ((n / 2) as usize)..n as usize { assert_eq!(bonds[validator as usize][server], I32F32::from_num(53619)); @@ -1500,9 +1510,9 @@ fn test_active_stake() { )); run_to_block_no_epoch(netuid, activity_cutoff + 3); // run to block where validator (uid 0, 1) weights become outdated if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 5003; activity_cutoff: 5000 Last update: [5002, 5002, 0, 0]; Inactive: [false, false, true, true]; Block at registration: [0, 0, 0, 0] @@ -1532,12 +1542,18 @@ fn test_active_stake() { P (u16): [65535, 54711, 60123, 60123] */ let bonds = SubtensorModule::get_bonds(netuid); assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, 0), 35716); // Note D = floor((0.55 * 0.9 + 0.5 * 0.1) * 65_535) - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, 0), 272501132); // Note E = 0.5 * (0.55 * 0.9 + 0.5 * 0.1) * 1_000_000_000 = 272_500_000 (discrepancy) + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, 0), + 272501132.into() + ); // Note E = 0.5 * (0.55 * 0.9 + 0.5 * 0.1) * 1_000_000_000 = 272_500_000 (discrepancy) for server in ((n / 2) as usize)..n as usize { assert_eq!(bonds[0][server], I32F32::from_num(65_535)); // floor((0.55 * 0.9 + 0.5 * 0.1)*(2^16-1))/(2^16-1), then max-upscale } assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, 1), 29818); // Note D = floor((0.45 * 0.9 + 0.5 * 0.1) * 65_535) - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, 1), 227498866); // Note E = 0.5 * (0.45 * 0.9 + 0.5 * 0.1) * 1_000_000_000 = 227_500_000 (discrepancy) + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, 1), + 227498866.into() + ); // Note E = 0.5 * (0.45 * 0.9 + 0.5 * 0.1) * 1_000_000_000 = 227_500_000 (discrepancy) for server in ((n / 2) as usize)..n as usize { assert_eq!(bonds[1][server], I32F32::from_num(54712)); // floor((0.45 * 0.9 + 0.5 * 0.1)/(0.55 * 0.9 + 0.5 * 0.1)*(2^16-1)) } @@ -1586,7 +1602,7 @@ fn test_outdated_weights() { &U256::from(key), &U256::from(key), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); @@ -1595,7 +1611,7 @@ fn test_outdated_weights() { // === Issue validator permits SubtensorModule::set_max_allowed_validators(netuid, n); assert_eq!(SubtensorModule::get_max_allowed_validators(netuid), n); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators assert_eq!(SubtensorModule::get_registrations_this_block(netuid), 4); block_number = next_block_no_epoch(netuid); // run to next block to ensure weights are set on nodes after their registration block assert_eq!(SubtensorModule::get_registrations_this_block(netuid), 0); @@ -1620,9 +1636,9 @@ fn test_outdated_weights() { )); // server self-weight } if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 1; activity_cutoff: 5000 Last update: [1, 1, 1, 1]; Inactive: [false, false, false, false]; Block at registration: [0, 0, 0, 0] @@ -1689,9 +1705,9 @@ fn test_outdated_weights() { 0 )); if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 2; activity_cutoff: 5000 Last update: [2, 1, 1, 1]; Inactive: [false, false, false, false]; Block at registration: [0, 0, 0, 1] @@ -1725,7 +1741,10 @@ fn test_outdated_weights() { P (u16): [32767, 32767, 65535, 0] */ let bonds = SubtensorModule::get_bonds(netuid); assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, 0), 32767); // Note D = floor(0.5 * 65_535) - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, 0), 250000000); // Note E = 0.5 * 0.5 * 1_000_000_000 = 249311245 + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, 0), + 250000000.into() + ); // Note E = 0.5 * 0.5 * 1_000_000_000 = 249311245 assert_eq!(bonds[0][2], I32F32::from_num(65_535)); // floor(0.5*(2^16-1))/(2^16-1), then max-upscale assert_eq!(bonds[0][3], I32F32::from_num(65_535)); // only uid0 has updated weights for new reg }); @@ -1773,16 +1792,16 @@ fn test_zero_weights() { &U256::from(validator), &U256::from(validator), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); // === No weights if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 0; activity_cutoff: 5000; Last update: [0, 0]; Inactive: [false, false] S: [1, 0]; S (mask): [1, 0]; S (mask+norm): [1, 0]; Block at registration: [0, 0] @@ -1794,11 +1813,14 @@ fn test_zero_weights() { for validator in 0..(n / 2) { assert_eq!( SubtensorModule::get_emission_for_uid(netuid, validator), - 1000000000 + 1000000000.into() ); // Note E = 1 * 1_000_000_000 } for server in (n / 2)..n { - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, server), 0); + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, server), + 0.into() + ); // no stake } run_to_block(1); @@ -1815,9 +1837,9 @@ fn test_zero_weights() { )); // server self-weight } if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 1; activity_cutoff: 5000; Last update: [0, 1]; Inactive: [false, false] S: [1, 0]; S (mask): [1, 0]; S (mask+norm): [1, 0]; Block at registration: [0, 0] @@ -1830,11 +1852,14 @@ fn test_zero_weights() { for validator in 0..(n / 2) { assert_eq!( SubtensorModule::get_emission_for_uid(netuid, validator), - 1000000000 + 1000000000.into() ); // Note E = 1 * 1_000_000_000 } for server in (n / 2)..n { - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, server), 0); + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, server), + 0.into() + ); // no stake } run_to_block(2); @@ -1871,9 +1896,9 @@ fn test_zero_weights() { )); } if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 2; activity_cutoff: 5000; Last update: [2, 1]; Inactive: [false, false]; S: [1, 0]; S (mask): [1, 0]; S (mask+norm): [1, 0]; Block at registration: [0, 2]; @@ -1885,11 +1910,14 @@ fn test_zero_weights() { for validator in 0..(n / 2) { assert_eq!( SubtensorModule::get_emission_for_uid(netuid, validator), - 1000000000 + 1000000000.into() ); // Note E = 1 * 1_000_000_000 } for server in (n / 2)..n { - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, server), 0); + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, server), + 0.into() + ); // no stake } run_to_block(3); @@ -1905,9 +1933,9 @@ fn test_zero_weights() { )); } if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } /* current_block: 3; activity_cutoff: 5000; Last update: [3, 1]; Inactive: [false, false]; S: [1, 0]; S (mask): [1, 0]; S (mask+norm): [1, 0]; Block at registration: [0, 2]; @@ -1919,7 +1947,7 @@ fn test_zero_weights() { for validator in 0..n { assert_eq!( SubtensorModule::get_emission_for_uid(netuid, validator), - 1000000000 / (n as u64) + (1000000000 / (n as u64)).into() ); // Note E = 1/2 * 1_000_000_000 } }); @@ -1968,7 +1996,7 @@ fn test_deregistered_miner_bonds() { &U256::from(key), &U256::from(key), netuid, - stake, + stake.into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), n); @@ -1977,7 +2005,7 @@ fn test_deregistered_miner_bonds() { // === Issue validator permits SubtensorModule::set_max_allowed_validators(netuid, n); assert_eq!(SubtensorModule::get_max_allowed_validators(netuid), n); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators assert_eq!(SubtensorModule::get_registrations_this_block(netuid), 4); next_block(); // run to next block to ensure weights are set on nodes after their registration block assert_eq!(SubtensorModule::get_registrations_this_block(netuid), 0); @@ -2004,9 +2032,9 @@ fn test_deregistered_miner_bonds() { SubtensorModule::set_tempo(netuid, 2); // Run epoch if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } // Check the bond values for the servers @@ -2078,9 +2106,9 @@ fn test_deregistered_miner_bonds() { SubtensorModule::set_tempo(netuid, 2); // Run epoch again. if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } // Check the bond values for the servers @@ -2171,7 +2199,7 @@ fn test_validator_permits() { &U256::from(key), &U256::from(key), netuid, - stake[key as usize], + stake[key as usize].into(), ); } assert_eq!(SubtensorModule::get_subnetwork_n(netuid), network_n as u16); @@ -2182,7 +2210,7 @@ fn test_validator_permits() { SubtensorModule::get_max_allowed_validators(netuid), validators_n as u16 ); - SubtensorModule::epoch(netuid, 1_000_000_000); // run first epoch to set allowed validators + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // run first epoch to set allowed validators for validator in &validators { assert_eq!( stake[*validator as usize] >= min_stake, @@ -2206,13 +2234,13 @@ fn test_validator_permits() { &(U256::from(*server as u64)), &(U256::from(*server as u64)), netuid, - 2 * network_n as u64, + (2 * network_n as u64).into(), ); } // === Update validator permits run_to_block(1); - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); // === Check that servers now own permits instead of the validator uids for validator in &validators { @@ -2459,7 +2487,7 @@ fn test_can_set_self_weight_as_subnet_owner() { &subnet_owner_hotkey, &subnet_owner_coldkey, netuid, - stake, + stake.into(), ); // Give vpermits to owner hotkey ONLY @@ -2475,7 +2503,7 @@ fn test_can_set_self_weight_as_subnet_owner() { LastUpdate::::insert(netuid, vec![2, 0]); // Run epoch - let hotkey_emission: Vec<(U256, u64, u64)> = SubtensorModule::epoch(netuid, to_emit); + let hotkey_emission = SubtensorModule::epoch(netuid, to_emit.into()); // hotkey_emission is [(hotkey, incentive, dividend)] assert_eq!(hotkey_emission.len(), 2); @@ -2484,8 +2512,8 @@ fn test_can_set_self_weight_as_subnet_owner() { log::debug!("hotkey_emission: {:?}", hotkey_emission); // Both should have received incentive emission - assert!(hotkey_emission[0].1 > 0); - assert!(hotkey_emission[1].1 > 0); + assert!(hotkey_emission[0].1 > 0.into()); + assert!(hotkey_emission[1].1 > 0.into()); // Their incentive should be equal assert_eq!(hotkey_emission[0].1, hotkey_emission[1].1); @@ -2504,25 +2532,30 @@ fn test_epoch_outputs_single_staker_registered_no_weights() { register_ok_neuron(netuid, hotkey, coldkey, 0); // Give non-zero alpha SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey, &coldkey, netuid, 1, + &hotkey, + &coldkey, + netuid, + 1.into(), ); - let pending_alpha: u64 = 1_000_000_000; - let hotkey_emission: Vec<(U256, u64, u64)> = SubtensorModule::epoch(netuid, pending_alpha); + let pending_alpha = AlphaCurrency::from(1_000_000_000); + let hotkey_emission = SubtensorModule::epoch(netuid, pending_alpha); - let sum_incentives: u64 = hotkey_emission + let sum_incentives = hotkey_emission .iter() .map(|(_, incentive, _)| incentive) - .sum(); - let sum_dividends: u64 = hotkey_emission + .copied() + .fold(AlphaCurrency::ZERO, |acc, x| acc + x); + let sum_dividends: AlphaCurrency = hotkey_emission .iter() .map(|(_, _, dividend)| dividend) - .sum(); + .copied() + .fold(AlphaCurrency::ZERO, |acc, x| acc + x); assert_abs_diff_eq!( sum_incentives.saturating_add(sum_dividends), pending_alpha, - epsilon = 1_000 + epsilon = 1_000.into() ); }); } @@ -2685,7 +2718,7 @@ fn setup_yuma_3_scenario(netuid: NetUid, n: u16, sparse: bool, max_stake: u64, s &U256::from(key), &U256::from(key), netuid, - stakes[key as usize], + stakes[key as usize].into(), ); } assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), n); @@ -2710,9 +2743,9 @@ fn setup_yuma_3_scenario(netuid: NetUid, n: u16, sparse: bool, max_stake: u64, s fn run_epoch(netuid: NetUid, sparse: bool) { next_block_no_epoch(netuid); if sparse { - SubtensorModule::epoch(netuid, 1_000_000_000); + SubtensorModule::epoch(netuid, 1_000_000_000.into()); } else { - SubtensorModule::epoch_dense(netuid, 1_000_000_000); + SubtensorModule::epoch_dense(netuid, 1_000_000_000.into()); } } @@ -3539,3 +3572,247 @@ fn test_liquid_alpha_equal_values_against_itself() { ); }); } + +#[test] +fn test_epoch_masks_incoming_to_sniped_uid_prevents_inheritance() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(40); + let tempo: u16 = 10; + let reveal: u64 = 2; + + add_network(netuid, tempo, 0); + SubtensorModule::set_reveal_period(netuid, reveal); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_max_allowed_uids(netuid, 3); + SubtensorModule::set_target_registrations_per_interval(netuid, u16::MAX); + + /* Validator uid‑0 */ + let (val_hot, val_cold) = (U256::from(100), U256::from(200)); + register_ok_neuron(netuid, val_hot, val_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &val_hot, + &val_cold, + netuid, + 10_000.into(), + ); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + + /* Miner uid‑1 (to be sniped later) */ + let (old_hot, old_cold) = (U256::from(101), U256::from(201)); + register_ok_neuron(netuid, old_hot, old_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &old_hot, + &old_cold, + netuid, + 100.into(), + ); + + /* filler uid‑2 */ + let (fill_hot, fill_cold) = (U256::from(102), U256::from(202)); + register_ok_neuron(netuid, fill_hot, fill_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &fill_hot, + &fill_cold, + netuid, + 5_000.into(), + ); + SubtensorModule::set_max_allowed_validators(netuid, 3); + + run_to_block(tempo as u64 * 2 + 1); + + /* commit, then move one block ahead so reg_block > commit_block */ + commit_dummy(val_hot, netuid); + run_to_block(System::block_number() + 1); + + /* validator weights uid‑1 */ + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(val_hot), + netuid, + vec![1], + vec![u16::MAX], + 0 + )); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::epoch(netuid, 1_000.into()); + + /* register new miner (snipes) */ + let (new_hot, new_cold) = (U256::from(103), U256::from(203)); + register_ok_neuron(netuid, new_hot, new_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &new_hot, + &new_cold, + netuid, + 10_000.into(), + ); + let new_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &new_hot) + .expect("new miner gets UID"); + + run_to_block(System::block_number() + 1); + + /* validator refreshes vote (still inside window) */ + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(val_hot), + netuid, + vec![0, new_uid], + vec![u16::MAX / 2, u16::MAX / 2], + 0 + )); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + SubtensorModule::epoch(netuid, 1_000.into()); + assert_eq!(SubtensorModule::get_rank_for_uid(netuid, new_uid), 0); + assert_eq!(SubtensorModule::get_incentive_for_uid(netuid, new_uid), 0); + }); +} + +#[test] +fn test_epoch_no_mask_when_commit_reveal_disabled() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(32); + let tempo: u16 = 5; + add_network(netuid, tempo, 0); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + + let (hot, cold) = (U256::from(1000), U256::from(1100)); + register_ok_neuron(netuid, hot, cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hot, + &cold, + netuid, + 1_000.into(), + ); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + + let (hot1, cold1) = (U256::from(1001), U256::from(1101)); + register_ok_neuron(netuid, hot1, cold1, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hot1, + &cold1, + netuid, + 1_000.into(), + ); + + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(hot), + netuid, + vec![1], + vec![u16::MAX], + 0 + )); + + for _ in 0..3 { + SubtensorModule::epoch(netuid, 1.into()); + assert!( + !SubtensorModule::get_weights_sparse(netuid)[0].is_empty(), + "row visible when CR disabled" + ); + run_to_block(System::block_number() + tempo as u64 + 1); + } + }); +} + +#[test] +fn test_epoch_does_not_mask_outside_window_but_masks_inside() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(50); + let tempo: u16 = 8; + let reveal: u16 = 2; + + add_network(netuid, tempo, 0); + SubtensorModule::set_reveal_period(netuid, reveal as u64); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + SubtensorModule::set_target_registrations_per_interval(netuid, u16::MAX); + + /* validator uid‑0 */ + let (v_hot, v_cold) = (U256::from(2000), U256::from(2100)); + register_ok_neuron(netuid, v_hot, v_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &v_hot, + &v_cold, + netuid, + 10_000.into(), + ); + SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); + SubtensorModule::set_max_allowed_validators(netuid, 1); + + run_to_block(tempo as u64 + 1); + + /* first commit */ + commit_dummy(v_hot, netuid); + + /* UID‑1 — outside window */ + let (old_hot, old_cold) = (U256::from(2001), U256::from(2101)); + register_ok_neuron(netuid, old_hot, old_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &old_hot, + &old_cold, + netuid, + 1_000.into(), + ); + + /* let first commit expire for UID‑1 */ + for _ in 0..(reveal + 1) { + run_to_block(System::block_number() + tempo as u64 + 1); + } + + /* second commit — will mask UID‑2 & UID‑3 */ + commit_dummy(v_hot, netuid); + + /* ensure commit_block < reg_block for the new registrations */ + run_to_block(System::block_number() + 1); + + /* UID‑2, UID‑3 — inside window */ + let (mid_hot, mid_cold) = (U256::from(2002), U256::from(2102)); + register_ok_neuron(netuid, mid_hot, mid_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &mid_hot, + &mid_cold, + netuid, + 1_000.into(), + ); + + let (new_hot, new_cold) = (U256::from(2003), U256::from(2103)); + register_ok_neuron(netuid, new_hot, new_cold, 0); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &new_hot, + &new_cold, + netuid, + 1_000.into(), + ); + + run_to_block(System::block_number() + 1); // avoid out‑dated + + /* vote */ + SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + assert_ok!(SubtensorModule::set_weights( + RuntimeOrigin::signed(v_hot), + netuid, + vec![1, 2, 3], + vec![u16::MAX / 3, u16::MAX / 3, u16::MAX / 3], + 0 + )); + SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); + + SubtensorModule::epoch(netuid, 1_000.into()); + + assert!( + SubtensorModule::get_rank_for_uid(netuid, 1) > 0, + "UID-1 (old) unmasked" + ); + assert_eq!( + SubtensorModule::get_rank_for_uid(netuid, 2), + 0, + "UID-2 (inside window) masked" + ); + assert_eq!( + SubtensorModule::get_rank_for_uid(netuid, 3), + 0, + "UID-3 (inside window) masked" + ); + }); +} diff --git a/pallets/subtensor/src/tests/leasing.rs b/pallets/subtensor/src/tests/leasing.rs index 89e4ca296d..ac27347055 100644 --- a/pallets/subtensor/src/tests/leasing.rs +++ b/pallets/subtensor/src/tests/leasing.rs @@ -9,6 +9,7 @@ use frame_support::{StorageDoubleMap, assert_err, assert_ok}; use sp_core::U256; use sp_runtime::Percent; use substrate_fixed::types::U64F64; +use subtensor_runtime_common::AlphaCurrency; #[test] fn test_register_leased_network_works() { @@ -509,11 +510,11 @@ fn test_distribute_lease_network_dividends_multiple_contributors_works() { let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); // Setup some previously accumulated dividends - let accumulated_dividends = 5_000_000; + let accumulated_dividends = AlphaCurrency::from(5_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were distributed correctly relative to their shares @@ -550,7 +551,10 @@ fn test_distribute_lease_network_dividends_multiple_contributors_works() { assert_eq!(beneficiary_balance_delta, expected_beneficiary_balance); // Ensure nothing was accumulated for later distribution - assert_eq!(AccumulatedLeaseDividends::::get(lease_id), 0); + assert_eq!( + AccumulatedLeaseDividends::::get(lease_id), + AlphaCurrency::ZERO + ); }); } @@ -584,11 +588,11 @@ fn test_distribute_lease_network_dividends_only_beneficiary_works() { let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); // Setup some previously accumulated dividends - let accumulated_dividends = 5_000_000; + let accumulated_dividends = AlphaCurrency::from(5_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were distributed correctly relative to their shares @@ -598,7 +602,10 @@ fn test_distribute_lease_network_dividends_only_beneficiary_works() { assert_eq!(distributed_tao, beneficiary_balance_delta); // Ensure nothing was accumulated for later distribution - assert_eq!(AccumulatedLeaseDividends::::get(lease_id), 0); + assert_eq!( + AccumulatedLeaseDividends::::get(lease_id), + AlphaCurrency::ZERO + ); }); } @@ -636,11 +643,11 @@ fn test_distribute_lease_network_dividends_accumulates_if_not_the_correct_block( let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); // Setup some previously accumulated dividends - let accumulated_dividends = 5_000_000; + let accumulated_dividends = AlphaCurrency::from(5_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed @@ -660,7 +667,8 @@ fn test_distribute_lease_network_dividends_accumulates_if_not_the_correct_block( // Ensure we correctly accumulated the dividends assert_eq!( AccumulatedLeaseDividends::::get(lease_id), - accumulated_dividends + emissions_share.mul_ceil(owner_cut_alpha) + (accumulated_dividends + emissions_share.mul_ceil(owner_cut_alpha.to_u64()).into()) + .into() ); }); } @@ -669,7 +677,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_not_the_correct_block( fn test_distribute_lease_network_dividends_does_nothing_if_lease_does_not_exist() { new_test_ext(1).execute_with(|| { let lease_id = 0; - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); }); } @@ -709,7 +717,7 @@ fn test_distribute_lease_network_dividends_does_nothing_if_lease_has_ended() { let accumulated_dividends_before = AccumulatedLeaseDividends::::get(lease_id); // Try to distribute the dividends - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed @@ -765,7 +773,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_amount_is_too_low() { let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); // Try to distribute the dividends - let owner_cut_alpha = 5_000; + let owner_cut_alpha = AlphaCurrency::from(5_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed @@ -785,7 +793,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_amount_is_too_low() { // Ensure the correct amount of alpha was accumulated for later dividends distribution assert_eq!( AccumulatedLeaseDividends::::get(lease_id), - emissions_share.mul_ceil(owner_cut_alpha) + emissions_share.mul_ceil(owner_cut_alpha.to_u64()).into() ); }); } @@ -821,7 +829,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_insufficient_liquidity let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); // Try to distribute the dividends - let owner_cut_alpha = 5_000_000; + let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed @@ -841,7 +849,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_insufficient_liquidity // Ensure the correct amount of alpha was accumulated for later dividends distribution assert_eq!( AccumulatedLeaseDividends::::get(lease_id), - emissions_share.mul_ceil(owner_cut_alpha) + emissions_share.mul_ceil(owner_cut_alpha.to_u64()).into() ); }); } diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 720875d6b6..895d48b2eb 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -8,12 +8,15 @@ use codec::{Decode, Encode}; use frame_support::{ StorageHasher, Twox64Concat, assert_ok, storage::unhashed::{get, get_raw, put, put_raw}, + storage_alias, traits::{StorageInstance, StoredMap}, weights::Weight, }; use crate::migrations::migrate_storage; use frame_system::Config; +use pallet_drand::types::RoundNumber; +use scale_info::prelude::collections::VecDeque; use sp_core::{H256, U256, crypto::Ss58Codec}; use sp_io::hashing::twox_128; use sp_runtime::traits::Zero; @@ -476,11 +479,11 @@ fn test_migrate_remove_zero_total_hotkey_alpha() { let hotkey_nonzero = U256::from(101u64); // Insert one zero-alpha entry and one non-zero entry - TotalHotkeyAlpha::::insert(hotkey_zero, netuid, 0u64); - TotalHotkeyAlpha::::insert(hotkey_nonzero, netuid, 123u64); + TotalHotkeyAlpha::::insert(hotkey_zero, netuid, AlphaCurrency::ZERO); + TotalHotkeyAlpha::::insert(hotkey_nonzero, netuid, AlphaCurrency::from(123)); - assert_eq!(TotalHotkeyAlpha::::get(hotkey_zero, netuid), 0u64); - assert_eq!(TotalHotkeyAlpha::::get(hotkey_nonzero, netuid), 123u64); + assert_eq!(TotalHotkeyAlpha::::get(hotkey_zero, netuid), AlphaCurrency::ZERO); + assert_eq!(TotalHotkeyAlpha::::get(hotkey_nonzero, netuid), AlphaCurrency::from(123)); assert!( !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), @@ -499,7 +502,7 @@ fn test_migrate_remove_zero_total_hotkey_alpha() { "Zero-alpha entry should have been removed." ); - assert_eq!(TotalHotkeyAlpha::::get(hotkey_nonzero, netuid), 123u64); + assert_eq!(TotalHotkeyAlpha::::get(hotkey_nonzero, netuid), AlphaCurrency::from(123)); assert!( !weight.is_zero(), @@ -831,7 +834,11 @@ fn test_migrate_fix_root_subnet_tao() { for i in 0..100_000 { Owner::::insert(U256::from(U256::from(i)), U256::from(i + 1_000_000)); let stake = i + 1_000_000; - TotalHotkeyAlpha::::insert(U256::from(U256::from(i)), NetUid::ROOT, stake); + TotalHotkeyAlpha::::insert( + U256::from(U256::from(i)), + NetUid::ROOT, + AlphaCurrency::from(stake), + ); expected_total_stake += stake; } @@ -990,3 +997,77 @@ fn test_migrate_set_nominator_min_stake() { ); }); } + +#[test] +fn test_migrate_crv3_commits_add_block() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // 0. Constants / helpers + // ------------------------------ + const MIG_NAME: &[u8] = b"crv3_commits_add_block_v1"; + let netuid = NetUid::from(99); + let epoch: u64 = 7; + let tempo: u16 = 360; + + // ------------------------------ + // 1. Create a network so helper can compute first‑block + // ------------------------------ + add_network(netuid, tempo, 0); + + // ------------------------------ + // 2. Simulate OLD storage (3‑tuple) + // ------------------------------ + let who: U256 = U256::from(0xdeadbeef_u64); + let ciphertext: BoundedVec> = + vec![1u8, 2, 3].try_into().unwrap(); + let round: RoundNumber = 42; + + let old_queue: VecDeque<_> = VecDeque::from(vec![(who, ciphertext.clone(), round)]); + + CRV3WeightCommits::::insert(netuid, epoch, old_queue.clone()); + + // Sanity: entry decodes under old alias + assert_eq!(CRV3WeightCommits::::get(netuid, epoch), old_queue); + + assert!( + !HasMigrationRun::::get(MIG_NAME.to_vec()), + "migration flag should be false before run" + ); + + // ------------------------------ + // 3. Run migration + // ------------------------------ + let w = crate::migrations::migrate_crv3_commits_add_block::migrate_crv3_commits_add_block::< + Test, + >(); + assert!(!w.is_zero(), "weight must be non-zero"); + + // ------------------------------ + // 4. Verify results + // ------------------------------ + assert!( + HasMigrationRun::::get(MIG_NAME.to_vec()), + "migration flag not set" + ); + + // Old storage must be empty (drained) + assert!( + CRV3WeightCommits::::get(netuid, epoch).is_empty(), + "old queue should have been drained" + ); + + let new_q = CRV3WeightCommitsV2::::get(netuid, epoch); + assert_eq!(new_q.len(), 1, "exactly one migrated element expected"); + + let (who2, commit_block, cipher2, round2) = new_q.front().cloned().unwrap(); + assert_eq!(who2, who); + assert_eq!(cipher2, ciphertext); + assert_eq!(round2, round); + + let expected_block = Pallet::::get_first_block_of_epoch(netuid, epoch); + assert_eq!( + commit_block, expected_block, + "commit_block should equal first block of epoch key" + ); + }); +} diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index daaa2a6579..86b2c458af 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -977,14 +977,14 @@ pub(crate) fn remove_stake_rate_limit_for_tests(hotkey: &U256, coldkey: &U256, n StakingOperationRateLimiter::::remove((hotkey, coldkey, netuid)); } -pub(crate) fn setup_reserves(netuid: NetUid, tao: u64, alpha: u64) { +pub(crate) fn setup_reserves(netuid: NetUid, tao: u64, alpha: AlphaCurrency) { SubnetTAO::::set(netuid, tao); SubnetAlphaIn::::set(netuid, alpha); } -pub(crate) fn swap_tao_to_alpha(netuid: NetUid, tao: u64) -> (u64, u64) { +pub(crate) fn swap_tao_to_alpha(netuid: NetUid, tao: u64) -> (AlphaCurrency, u64) { if netuid.is_root() { - return (tao, 0); + return (tao.into(), 0); } let result = ::SwapInterface::swap( @@ -1003,12 +1003,16 @@ pub(crate) fn swap_tao_to_alpha(netuid: NetUid, tao: u64) -> (u64, u64) { // we don't want to have silent 0 comparissons in tests assert!(result.amount_paid_out > 0); - (result.amount_paid_out, result.fee_paid) + (result.amount_paid_out.into(), result.fee_paid) } -pub(crate) fn swap_alpha_to_tao_ext(netuid: NetUid, alpha: u64, drop_fees: bool) -> (u64, u64) { +pub(crate) fn swap_alpha_to_tao_ext( + netuid: NetUid, + alpha: AlphaCurrency, + drop_fees: bool, +) -> (u64, u64) { if netuid.is_root() { - return (alpha, 0); + return (alpha.into(), 0); } println!( @@ -1019,7 +1023,7 @@ pub(crate) fn swap_alpha_to_tao_ext(netuid: NetUid, alpha: u64, drop_fees: bool) let result = ::SwapInterface::swap( netuid.into(), OrderType::Sell, - alpha, + alpha.into(), ::SwapInterface::min_price(), drop_fees, true, @@ -1035,7 +1039,7 @@ pub(crate) fn swap_alpha_to_tao_ext(netuid: NetUid, alpha: u64, drop_fees: bool) (result.amount_paid_out, result.fee_paid) } -pub(crate) fn swap_alpha_to_tao(netuid: NetUid, alpha: u64) -> (u64, u64) { +pub(crate) fn swap_alpha_to_tao(netuid: NetUid, alpha: AlphaCurrency) -> (u64, u64) { swap_alpha_to_tao_ext(netuid, alpha, false) } @@ -1047,3 +1051,16 @@ pub(crate) fn last_event() -> RuntimeEvent { pub fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } + +#[allow(dead_code)] +pub fn commit_dummy(who: U256, netuid: NetUid) { + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + // any 32‑byte value is fine; hash is never opened + let hash = sp_core::H256::from_low_u64_be(0xDEAD_BEEF); + assert_ok!(SubtensorModule::do_commit_weights( + RuntimeOrigin::signed(who), + netuid, + hash + )); +} diff --git a/pallets/subtensor/src/tests/move_stake.rs b/pallets/subtensor/src/tests/move_stake.rs index 375f43e345..d80571c594 100644 --- a/pallets/subtensor/src/tests/move_stake.rs +++ b/pallets/subtensor/src/tests/move_stake.rs @@ -45,7 +45,7 @@ fn test_do_move_success() { ); // Perform the move - let expected_alpha = alpha * 997 / 1000; + let expected_alpha = alpha; assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -62,7 +62,7 @@ fn test_do_move_success() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -71,7 +71,7 @@ fn test_do_move_success() { netuid ), expected_alpha, - epsilon = expected_alpha / 1000 + epsilon = expected_alpha / 1000.into() ); }); } @@ -91,8 +91,16 @@ fn test_do_move_different_subnets() { let destination_hotkey = U256::from(3); let stake_amount = DefaultMinStake::::get() * 10; - mock::setup_reserves(origin_netuid, stake_amount * 100, stake_amount * 100); - mock::setup_reserves(destination_netuid, stake_amount * 100, stake_amount * 100); + mock::setup_reserves( + origin_netuid, + stake_amount * 100, + (stake_amount * 100).into(), + ); + mock::setup_reserves( + destination_netuid, + stake_amount * 100, + (stake_amount * 100).into(), + ); // Set up initial stake and subnets SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); @@ -129,18 +137,20 @@ fn test_do_move_different_subnets() { &coldkey, origin_netuid ), - 0 + AlphaCurrency::ZERO + ); + let fee = ::SwapInterface::approx_fee_amount( + destination_netuid.into(), + alpha.into(), ); - 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 ), - alpha - fee, - epsilon = alpha / 1000 + alpha - fee.into(), + epsilon = alpha / 1000.into() ); }); } @@ -161,7 +171,7 @@ fn test_do_move_nonexistent_subnet() { let stake_amount = 1_000_000; let reserve = stake_amount * 1000; - mock::setup_reserves(origin_netuid, reserve, reserve); + mock::setup_reserves(origin_netuid, reserve, reserve.into()); // Set up initial stake SubtensorModule::stake_into_subnet( @@ -225,7 +235,7 @@ fn test_do_move_nonexistent_origin_hotkey() { destination_hotkey, netuid, netuid, - 123 + 123.into() ), Error::::HotKeyAccountNotExists ); @@ -237,7 +247,7 @@ fn test_do_move_nonexistent_origin_hotkey() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -245,7 +255,7 @@ fn test_do_move_nonexistent_origin_hotkey() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); }); } @@ -263,7 +273,7 @@ fn test_do_move_nonexistent_destination_hotkey() { let stake_amount = 1_000_000; let reserve = stake_amount * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Set up initial stake SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); @@ -307,7 +317,7 @@ fn test_do_move_nonexistent_destination_hotkey() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); }); } @@ -347,7 +357,7 @@ fn test_do_move_partial_stake() { ); // Move partial stake - let alpha_moved = alpha * portion_moved / 10; + let alpha_moved = AlphaCurrency::from(alpha.to_u64() * portion_moved / 10); SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); assert_ok!(SubtensorModule::do_move_stake( @@ -367,7 +377,7 @@ fn test_do_move_partial_stake() { netuid ), alpha - alpha_moved, - epsilon = 10 + epsilon = 10.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -375,8 +385,8 @@ fn test_do_move_partial_stake() { &coldkey, netuid ), - alpha_moved * 997 / 1000, - epsilon = 10_000 + alpha_moved, + epsilon = 10_000.into() ); }); }); @@ -412,7 +422,7 @@ fn test_do_move_multiple_times() { SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid); // Move stake multiple times - let mut expected_alpha: u64 = alpha; + let expected_alpha = alpha; for _ in 0..3 { let alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey, netuid, @@ -438,20 +448,17 @@ fn test_do_move_multiple_times() { netuid, alpha2, )); - - // Reduce expected_alpha by fees x2 - expected_alpha -= expected_alpha * 6 / 1000; } // Check final stake distribution assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey1, &coldkey, netuid), expected_alpha, - epsilon = expected_alpha / 1000, + epsilon = expected_alpha / 1000.into(), ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey2, &coldkey, netuid), - 0 + AlphaCurrency::ZERO ); }); } @@ -470,7 +477,7 @@ fn test_do_move_wrong_origin() { let stake_amount = DefaultMinStake::::get() * 10; let reserve = stake_amount * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Set up initial stake SubtensorModule::stake_into_subnet( @@ -519,7 +526,7 @@ fn test_do_move_wrong_origin() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); }); } @@ -606,7 +613,9 @@ fn test_do_move_event_emission() { // Move stake and capture events System::reset_events(); - let (tao_equivalent, _) = mock::swap_alpha_to_tao_ext(netuid, alpha, true); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); + let tao_equivalent = (current_price * U96F32::from_num(alpha)).to_num::(); // no fee conversion assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -684,7 +693,7 @@ fn test_do_move_storage_updates() { &coldkey, origin_netuid ), - 0 + AlphaCurrency::ZERO ); assert_abs_diff_eq!( @@ -694,7 +703,66 @@ fn test_do_move_storage_updates() { destination_netuid ), alpha2, - epsilon = 2 + epsilon = 2.into() + ); + }); +} + +#[test] +fn test_move_full_amount_same_netuid() { + new_test_ext(1).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let coldkey = U256::from(1); + let origin_hotkey = U256::from(2); + let destination_hotkey = U256::from(3); + let stake_amount = DefaultMinStake::::get() * 10; + SubtensorModule::create_account_if_non_existent(&coldkey, &origin_hotkey); + SubtensorModule::create_account_if_non_existent(&coldkey, &destination_hotkey); + + // Set up initial stake + SubtensorModule::stake_into_subnet( + &origin_hotkey, + &coldkey, + netuid, + stake_amount, + ::SwapInterface::max_price(), + false, + ) + .unwrap(); + + // Move all stake + let alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &origin_hotkey, + &coldkey, + netuid, + ); + assert_ok!(SubtensorModule::do_move_stake( + RuntimeOrigin::signed(coldkey), + origin_hotkey, + destination_hotkey, + netuid, + netuid, + alpha, + )); + + // Verify storage updates + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &origin_hotkey, + &coldkey, + netuid + ), + AlphaCurrency::ZERO + ); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &destination_hotkey, + &coldkey, + netuid + ), + alpha ); }); } @@ -719,7 +787,7 @@ fn test_do_move_max_values() { // Add lots of liquidity to bypass low liquidity check let reserve = u64::MAX / 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); SubtensorModule::stake_into_subnet( &origin_hotkey, @@ -737,7 +805,6 @@ fn test_do_move_max_values() { ); // Move maximum stake - let (_, fee) = mock::swap_alpha_to_tao_ext(netuid, alpha, true); assert_ok!(SubtensorModule::do_move_stake( RuntimeOrigin::signed(coldkey), origin_hotkey, @@ -754,17 +821,15 @@ fn test_do_move_max_values() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); - let alpha_after_fee = alpha - fee; - assert_abs_diff_eq!( + assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &destination_hotkey, &coldkey, netuid ), - alpha_after_fee, - epsilon = alpha_after_fee / 100_000 + alpha ); }); } @@ -802,7 +867,7 @@ fn test_moving_too_little_unstakes() { hotkey_account_id, netuid, netuid2, - 1 + 1.into() ), Error::::AmountTooLow ); @@ -842,7 +907,7 @@ fn test_do_transfer_success() { ); // 4. Transfer the entire stake to the destination coldkey on the same subnet (netuid, netuid). - let expected_alpha = alpha * 997 / 1000; + let expected_alpha = alpha; assert_ok!(SubtensorModule::do_transfer_stake( RuntimeOrigin::signed(origin_coldkey), destination_coldkey, @@ -859,7 +924,7 @@ fn test_do_transfer_success() { &origin_coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -868,7 +933,7 @@ fn test_do_transfer_success() { netuid ), expected_alpha, - epsilon = expected_alpha / 1000 + epsilon = expected_alpha / 1000.into() ); }); } @@ -889,7 +954,7 @@ fn test_do_transfer_nonexistent_subnet() { hotkey, nonexistent_netuid, nonexistent_netuid, - stake_amount + stake_amount.into() ), Error::::SubnetNotExists ); @@ -914,7 +979,7 @@ fn test_do_transfer_nonexistent_hotkey() { nonexistent_hotkey, netuid, netuid, - 100 + 100.into() ), Error::::HotKeyAccountNotExists ); @@ -952,7 +1017,7 @@ fn test_do_transfer_insufficient_stake() { hotkey, netuid, netuid, - alpha + alpha.into() ), Error::::NotEnoughStakeToWithdraw ); @@ -992,7 +1057,7 @@ fn test_do_transfer_wrong_origin() { hotkey, netuid, netuid, - stake_amount + stake_amount.into() ), Error::::NotEnoughStakeToWithdraw ); @@ -1029,7 +1094,7 @@ fn test_do_transfer_minimum_stake_check() { hotkey, netuid, netuid, - 1 + 1.into() ), Error::::AmountTooLow ); @@ -1095,7 +1160,7 @@ fn test_do_transfer_different_subnets() { &origin_coldkey, origin_netuid ), - 0 + AlphaCurrency::ZERO ); // 8. Verify stake ended up in destination subnet for destination coldkey. @@ -1106,7 +1171,7 @@ fn test_do_transfer_different_subnets() { destination_netuid, ), expected_alpha, - epsilon = 1000 + epsilon = 1000.into() ); }); } @@ -1155,7 +1220,7 @@ fn test_do_swap_success() { &coldkey, origin_netuid ), - 0 + AlphaCurrency::ZERO ); let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1164,7 +1229,7 @@ fn test_do_swap_success() { destination_netuid, ); - assert_abs_diff_eq!(alpha_after, expected_alpha, epsilon = 1000); + assert_abs_diff_eq!(alpha_after, expected_alpha, epsilon = 1000.into()); }); } @@ -1185,7 +1250,7 @@ fn test_do_swap_nonexistent_subnet() { hotkey, nonexistent_netuid1, nonexistent_netuid2, - stake_amount + stake_amount.into() ), Error::::SubnetNotExists ); @@ -1210,7 +1275,7 @@ fn test_do_swap_nonexistent_hotkey() { nonexistent_hotkey, netuid1, netuid2, - stake_amount + stake_amount.into() ), Error::::HotKeyAccountNotExists ); @@ -1247,7 +1312,7 @@ fn test_do_swap_insufficient_stake() { hotkey, netuid1, netuid2, - attempted_swap + attempted_swap.into() ), Error::::NotEnoughStakeToWithdraw ); @@ -1284,7 +1349,7 @@ fn test_do_swap_wrong_origin() { hotkey, netuid1, netuid2, - stake_amount + stake_amount.into() ), Error::::NotEnoughStakeToWithdraw ); @@ -1321,7 +1386,7 @@ fn test_do_swap_minimum_stake_check() { hotkey, netuid1, netuid2, - swap_amount + swap_amount.into() ), Error::::AmountTooLow ); @@ -1399,7 +1464,7 @@ fn test_do_swap_partial_stake() { origin_netuid, ); - let swap_amount = total_stake_alpha / 2; + let swap_amount = total_stake_alpha / 2.into(); let (tao_equivalent, _) = mock::swap_alpha_to_tao_ext(origin_netuid, swap_amount, true); let (expected_alpha, _) = mock::swap_tao_to_alpha(destination_netuid, tao_equivalent); assert_ok!(SubtensorModule::do_swap_stake( @@ -1417,7 +1482,7 @@ fn test_do_swap_partial_stake() { destination_netuid ), expected_alpha, - epsilon = 1000 + epsilon = 1000.into() ); }); } @@ -1466,7 +1531,7 @@ fn test_do_swap_storage_updates() { &coldkey, origin_netuid ), - 0 + AlphaCurrency::ZERO ); assert_abs_diff_eq!( @@ -1476,7 +1541,7 @@ fn test_do_swap_storage_updates() { destination_netuid ), expected_alpha, - epsilon = 1000 + epsilon = 1000.into() ); }); } @@ -1504,12 +1569,12 @@ fn test_do_swap_multiple_times() { ) .unwrap(); - let mut expected_alpha: u64 = 0; + let mut expected_alpha = AlphaCurrency::ZERO; for _ in 0..3 { let alpha1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid1, ); - if alpha1 > 0 { + if !alpha1.is_zero() { remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid1); assert_ok!(SubtensorModule::do_swap_stake( RuntimeOrigin::signed(coldkey), @@ -1522,7 +1587,7 @@ fn test_do_swap_multiple_times() { let alpha2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid2, ); - if alpha2 > 0 { + if !alpha2.is_zero() { let (tao_equivalent, _) = mock::swap_alpha_to_tao_ext(netuid2, alpha2, true); // 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; @@ -1540,11 +1605,11 @@ fn test_do_swap_multiple_times() { assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid1), expected_alpha, - epsilon = 1000 + epsilon = 1000.into() ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid2), - 0 + AlphaCurrency::ZERO ); }); } @@ -1606,8 +1671,8 @@ fn test_swap_stake_limit_validate() { 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); + mock::setup_reserves(origin_netuid, reserve, reserve.into()); + mock::setup_reserves(destination_netuid, reserve, reserve.into()); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); let unstake_amount = SubtensorModule::stake_into_subnet( @@ -1772,10 +1837,10 @@ fn test_move_stake_specific_stake_into_subnet_fail() { let existing_shares: U64F64 = U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX)); - let existing_stake = 36_711_495_953; + let existing_stake = AlphaCurrency::from(36_711_495_953); let tao_in = 2_409_892_148_947; - let alpha_in = 15_358_708_513_716; + let alpha_in = AlphaCurrency::from(15_358_708_513_716); let tao_staked = 200_000_000; @@ -1817,7 +1882,7 @@ fn test_move_stake_specific_stake_into_subnet_fail() { ); // Setup Subnet pool for origin netuid - SubnetAlphaIn::::insert(origin_netuid, alpha_in + 10_000_000); + SubnetAlphaIn::::insert(origin_netuid, alpha_in + 10_000_000.into()); SubnetTAO::::insert(origin_netuid, tao_in + 10_000_000); // Add stake as new hotkey @@ -1853,7 +1918,7 @@ fn test_move_stake_specific_stake_into_subnet_fail() { &coldkey_account_id, origin_netuid ), - 0 + AlphaCurrency::ZERO ); assert_abs_diff_eq!( @@ -1863,7 +1928,7 @@ fn test_move_stake_specific_stake_into_subnet_fail() { netuid ), expected_value, - epsilon = 1000 + epsilon = 1000.into() ); }); } diff --git a/pallets/subtensor/src/tests/networks.rs b/pallets/subtensor/src/tests/networks.rs index ff14a641db..aa6a65918c 100644 --- a/pallets/subtensor/src/tests/networks.rs +++ b/pallets/subtensor/src/tests/networks.rs @@ -298,8 +298,8 @@ fn test_register_subnet_low_lock_cost() { assert!(SubtensorModule::if_subnet_exist(netuid)); // Ensure that both Subnet TAO and Subnet Alpha In equal to (actual) lock_cost - assert_eq!(SubnetTAO::::get(netuid), lock_cost,); - assert_eq!(SubnetAlphaIn::::get(netuid), lock_cost,); + assert_eq!(SubnetTAO::::get(netuid), lock_cost); + assert_eq!(SubnetAlphaIn::::get(netuid), lock_cost.into()); }) } @@ -322,7 +322,7 @@ fn test_register_subnet_high_lock_cost() { // Ensure that both Subnet TAO and Subnet Alpha In equal to 100 TAO assert_eq!(SubnetTAO::::get(netuid), lock_cost); - assert_eq!(SubnetAlphaIn::::get(netuid), lock_cost); + assert_eq!(SubnetAlphaIn::::get(netuid), lock_cost.into()); }) } diff --git a/pallets/subtensor/src/tests/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index ef23d1807d..e2dd644fa7 100644 --- a/pallets/subtensor/src/tests/recycle_alpha.rs +++ b/pallets/subtensor/src/tests/recycle_alpha.rs @@ -1,6 +1,7 @@ use approx::assert_abs_diff_eq; use frame_support::{assert_noop, assert_ok, traits::Currency}; use sp_core::U256; +use subtensor_runtime_common::{AlphaCurrency, Currency as CurrencyT}; use super::mock; use super::mock::*; @@ -34,7 +35,7 @@ fn test_recycle_success() { let initial_net_alpha = SubnetAlphaOut::::get(netuid); // amount to recycle - let recycle_amount = stake / 2; + let recycle_amount = AlphaCurrency::from(stake / 2); // recycle assert_ok!(SubtensorModule::recycle_alpha( @@ -94,7 +95,7 @@ fn test_recycle_two_stakers() { let initial_net_alpha = SubnetAlphaOut::::get(netuid); // amount to recycle - let recycle_amount = stake / 2; + let recycle_amount = AlphaCurrency::from(stake / 2); // recycle assert_ok!(SubtensorModule::recycle_alpha( @@ -108,7 +109,7 @@ fn test_recycle_two_stakers() { assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) - < stake + < stake.into() ); // Make sure the other coldkey has no change assert_abs_diff_eq!( @@ -118,7 +119,7 @@ fn test_recycle_two_stakers() { netuid ), expected_alpha, - epsilon = 2 + epsilon = 2.into() ); assert!(System::events().iter().any(|e| { @@ -170,7 +171,7 @@ fn test_recycle_staker_is_nominator() { let initial_net_alpha = SubnetAlphaOut::::get(netuid); // amount to recycle - let recycle_amount = stake / 2; + let recycle_amount = AlphaCurrency::from(stake / 2); // recycle from nominator coldkey assert_ok!(SubtensorModule::recycle_alpha( @@ -187,13 +188,13 @@ fn test_recycle_staker_is_nominator() { &hotkey, &other_coldkey, netuid - ) < stake + ) < stake.into() ); // Make sure the other coldkey has no change assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), expected_alpha, - epsilon = 2 + epsilon = 2.into() ); assert!(System::events().iter().any(|e| { @@ -239,7 +240,7 @@ fn test_burn_success() { assert_ok!(SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), hotkey, - burn_amount, + burn_amount.into(), netuid )); @@ -247,7 +248,7 @@ fn test_burn_success() { assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) - < stake + < stake.into() ); assert!(System::events().iter().any(|e| { @@ -294,7 +295,7 @@ fn test_burn_staker_is_nominator() { let initial_net_alpha = SubnetAlphaOut::::get(netuid); // amount to recycle - let burn_amount = stake / 2; + let burn_amount = AlphaCurrency::from(stake / 2); // burn from nominator coldkey assert_ok!(SubtensorModule::burn_alpha( @@ -311,13 +312,13 @@ fn test_burn_staker_is_nominator() { &hotkey, &other_coldkey, netuid - ) < stake + ) < stake.into() ); // Make sure the other coldkey has no change assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), expected_alpha, - epsilon = 2 + epsilon = 2.into() ); assert!(System::events().iter().any(|e| { @@ -363,7 +364,7 @@ fn test_burn_two_stakers() { let initial_net_alpha = SubnetAlphaOut::::get(netuid); // amount to recycle - let burn_amount = stake / 2; + let burn_amount = AlphaCurrency::from(stake / 2); // burn from coldkey assert_ok!(SubtensorModule::burn_alpha( @@ -377,7 +378,7 @@ fn test_burn_two_stakers() { assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) - < stake + < stake.into() ); // Make sure the other coldkey has no change assert_abs_diff_eq!( @@ -387,7 +388,7 @@ fn test_burn_two_stakers() { netuid ), expected_alpha, - epsilon = 2 + epsilon = 2.into() ); assert!(System::events().iter().any(|e| { @@ -426,7 +427,7 @@ fn test_recycle_errors() { SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 100_000, + 100_000.into(), 99.into() // non-existent subnet ), Error::::SubNetworkDoesNotExist @@ -436,7 +437,7 @@ fn test_recycle_errors() { SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 100_000, + 100_000.into(), NetUid::ROOT, ), Error::::CannotBurnOrRecycleOnRootSubnet @@ -446,7 +447,7 @@ fn test_recycle_errors() { SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey), wrong_hotkey, - 100_000, + 100_000.into(), netuid ), Error::::HotKeyAccountNotExists @@ -456,7 +457,7 @@ fn test_recycle_errors() { SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 10_000_000_000, // too much + 10_000_000_000.into(), // too much netuid ), Error::::NotEnoughStakeToWithdraw @@ -466,14 +467,14 @@ fn test_recycle_errors() { TotalHotkeyAlpha::::set( hotkey, netuid, - SubnetAlphaOut::::get(netuid).saturating_mul(2), + SubnetAlphaOut::::get(netuid).saturating_mul(2.into()), ); assert_noop!( SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey), hotkey, - SubnetAlphaOut::::get(netuid) + 1, + SubnetAlphaOut::::get(netuid) + 1.into(), netuid ), Error::::InsufficientLiquidity @@ -508,7 +509,7 @@ fn test_burn_errors() { SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 100_000, + 100_000.into(), 99.into() // non-existent subnet ), Error::::SubNetworkDoesNotExist @@ -518,7 +519,7 @@ fn test_burn_errors() { SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 100_000, + 100_000.into(), NetUid::ROOT, ), Error::::CannotBurnOrRecycleOnRootSubnet @@ -528,7 +529,7 @@ fn test_burn_errors() { SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), wrong_hotkey, - 100_000, + 100_000.into(), netuid ), Error::::HotKeyAccountNotExists @@ -538,7 +539,7 @@ fn test_burn_errors() { SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), hotkey, - 10_000_000_000, // too much + 10_000_000_000.into(), // too much netuid ), Error::::NotEnoughStakeToWithdraw @@ -548,14 +549,14 @@ fn test_burn_errors() { TotalHotkeyAlpha::::set( hotkey, netuid, - SubnetAlphaOut::::get(netuid).saturating_mul(2), + SubnetAlphaOut::::get(netuid).saturating_mul(2.into()), ); assert_noop!( SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey), hotkey, - SubnetAlphaOut::::get(netuid) + 1, + SubnetAlphaOut::::get(netuid) + 1.into(), netuid ), Error::::InsufficientLiquidity diff --git a/pallets/subtensor/src/tests/registration.rs b/pallets/subtensor/src/tests/registration.rs index 084eda0b66..997a71268e 100644 --- a/pallets/subtensor/src/tests/registration.rs +++ b/pallets/subtensor/src/tests/registration.rs @@ -8,7 +8,7 @@ use frame_support::{assert_err, assert_noop, assert_ok}; use frame_system::{Config, RawOrigin}; use sp_core::U256; use sp_runtime::traits::{DispatchInfoOf, TransactionExtension, TxBaseImplication}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, Currency as CurrencyT, NetUid}; use super::mock; use super::mock::*; @@ -153,7 +153,7 @@ fn test_registration_ok() { // Check if the balance of this hotkey account for this subnetwork == 0 assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid, neuron_uid), - 0 + AlphaCurrency::ZERO ); }); } @@ -320,7 +320,7 @@ fn test_burned_registration_under_limit() { SubtensorModule::set_burn(netuid, burn_cost); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); add_network(netuid, 13, 0); // Add the network // Give it some TAO to the coldkey balance; more than the burn cost @@ -420,7 +420,7 @@ fn test_burned_registration_rate_allows_burn_adjustment() { SubtensorModule::set_burn(netuid, burn_cost); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); add_network(netuid, 13, 0); // Add the network // Give it some TAO to the coldkey balance; more than the burn cost @@ -477,7 +477,7 @@ fn test_burned_registration_ok() { add_network(netuid, tempo, 0); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); @@ -510,7 +510,7 @@ fn test_burned_registration_ok() { // Check if the balance of this hotkey account for this subnetwork == 0 assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid, neuron_uid), - 0 + AlphaCurrency::ZERO ); }); } @@ -599,7 +599,7 @@ fn test_burn_adjustment() { ); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Register key 1. let hotkey_account_id_1 = U256::from(1); @@ -655,7 +655,7 @@ fn test_burn_registration_pruning_scenarios() { SubtensorModule::set_immunity_period(netuid, immunity_period); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); add_network(netuid, tempo, 0); @@ -1560,8 +1560,8 @@ fn test_burn_registration_increase_recycled_rao() { 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); + mock::setup_reserves(netuid, reserve, reserve.into()); + mock::setup_reserves(netuid2, reserve, reserve.into()); 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 3aeec0eb9a..be1a90ded4 100644 --- a/pallets/subtensor/src/tests/senate.rs +++ b/pallets/subtensor/src/tests/senate.rs @@ -76,7 +76,7 @@ fn test_senate_join_works() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = 1_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -116,13 +116,13 @@ fn test_senate_join_works() { &staker_coldkey, netuid ), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_ok!(SubtensorModule::root_register( @@ -152,7 +152,7 @@ fn test_senate_vote_works() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -193,13 +193,13 @@ fn test_senate_vote_works() { &staker_coldkey, netuid ), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_ok!(SubtensorModule::root_register( @@ -268,7 +268,7 @@ fn test_senate_vote_not_member() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -332,7 +332,7 @@ fn test_senate_leave_works() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = stake * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -372,13 +372,13 @@ fn test_senate_leave_works() { &staker_coldkey, netuid ), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_ok!(SubtensorModule::root_register( @@ -411,7 +411,7 @@ fn test_senate_leave_vote_removal() { SubtokenEnabled::::insert(netuid, true); let reserve = stake * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -451,13 +451,13 @@ fn test_senate_leave_vote_removal() { &staker_coldkey, netuid ), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake, - epsilon = 1 + AlphaCurrency::from(stake), + epsilon = 1.into() ); assert_ok!(SubtensorModule::root_register( @@ -496,8 +496,8 @@ fn test_senate_leave_vote_removal() { 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); + mock::setup_reserves(other_netuid, reserve, reserve.into()); + mock::setup_reserves(NetUid::ROOT, reserve, reserve.into()); SubtokenEnabled::::insert(NetUid::ROOT, true); SubtokenEnabled::::insert(other_netuid, true); @@ -562,7 +562,7 @@ fn test_senate_not_leave_when_stake_removed() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -603,13 +603,13 @@ fn test_senate_not_leave_when_stake_removed() { &staker_coldkey, netuid ), - stake_amount, - epsilon = 1 + AlphaCurrency::from(stake_amount), + epsilon = 1.into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_account_id, netuid), - stake_amount, - epsilon = 1 + AlphaCurrency::from(stake_amount), + epsilon = 1.into() ); assert_ok!(SubtensorModule::root_register( @@ -624,7 +624,7 @@ fn test_senate_not_leave_when_stake_removed() { <::RuntimeOrigin>::signed(staker_coldkey), hotkey_account_id, netuid, - stake_amount - 1 + (stake_amount - 1).into() )); assert!(Senate::is_member(&hotkey_account_id)); }); @@ -649,7 +649,7 @@ fn test_senate_join_current_delegate() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); let reserve = 1_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -751,7 +751,7 @@ fn test_adjust_senate_events() { SubtokenEnabled::::insert(NetUid::ROOT, true); let reserve = 100_000_000_000_000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Subscribe and check extrinsic output assert_ok!(SubtensorModule::burned_register( @@ -841,7 +841,7 @@ fn test_adjust_senate_events() { let stake = DefaultMinStake::::get() * 10; let reserve = 100_000_000_000_000; - mock::setup_reserves(NetUid::ROOT, reserve, reserve); + mock::setup_reserves(NetUid::ROOT, reserve, reserve.into()); let (_, fee) = mock::swap_tao_to_alpha(NetUid::ROOT, stake); @@ -857,16 +857,16 @@ fn test_adjust_senate_events() { &coldkey_account_id, NetUid::ROOT ), - stake - fee, - epsilon = stake / 1000 + AlphaCurrency::from(stake - fee), + epsilon = (stake / 1000).into() ); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_on_subnet( &replacement_hotkey_account_id, NetUid::ROOT ), - stake - fee, - epsilon = stake / 1000 + AlphaCurrency::from(stake - fee), + epsilon = (stake / 1000).into() ); System::reset_events(); diff --git a/pallets/subtensor/src/tests/staking.rs b/pallets/subtensor/src/tests/staking.rs index 54a4ecd6f9..c7447b51cc 100644 --- a/pallets/subtensor/src/tests/staking.rs +++ b/pallets/subtensor/src/tests/staking.rs @@ -14,7 +14,7 @@ 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_runtime_common::{AlphaCurrency, Currency as CurrencyT, NetUid}; use subtensor_swap_interface::{OrderType, SwapHandler}; use super::mock; @@ -42,7 +42,7 @@ fn test_add_stake_dispatch_info_ok() { call_weight: frame_support::weights::Weight::from_parts(2_495_500_000, 0), extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, - pays_fee: Pays::No + pays_fee: Pays::Yes } ); }); @@ -57,7 +57,7 @@ fn test_add_stake_ok_no_emission() { //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); + mock::setup_reserves(netuid, amount * 1_000_000, (amount * 10_000_000).into()); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); @@ -136,7 +136,7 @@ fn test_dividends_with_run_to_block() { &neuron_src_hotkey_id, &coldkey_account_id, netuid, - initial_stake, + initial_stake.into(), ); // Check if the initial stake has arrived @@ -356,7 +356,7 @@ fn test_add_stake_total_issuance_no_change() { fn test_remove_stake_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(0); - let amount_unstaked = 5000; + let amount_unstaked = AlphaCurrency::from(5000); let netuid = NetUid::from(1); let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake { hotkey, @@ -370,7 +370,7 @@ fn test_remove_stake_dispatch_info_ok() { .add_proof_size(0), extension_weight: frame_support::weights::Weight::zero(), class: DispatchClass::Normal, - pays_fee: Pays::No + pays_fee: Pays::Yes } ); }); @@ -403,7 +403,7 @@ fn test_remove_stake_ok_no_emission() { &hotkey_account_id, &coldkey_account_id, netuid, - amount, + amount.into(), ); assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id), @@ -412,7 +412,7 @@ fn test_remove_stake_ok_no_emission() { ); // Add subnet TAO for the equivalent amount added at price - let (amount_tao, fee) = mock::swap_alpha_to_tao(netuid, amount); + let (amount_tao, fee) = mock::swap_alpha_to_tao(netuid, amount.into()); SubnetTAO::::mutate(netuid, |v| *v += amount_tao + fee); TotalStake::::mutate(|v| *v += amount_tao + fee); @@ -421,7 +421,7 @@ fn test_remove_stake_ok_no_emission() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - amount + amount.into() )); // we do not expect the exact amount due to slippage @@ -466,7 +466,7 @@ fn test_remove_stake_amount_too_low() { &hotkey_account_id, &coldkey_account_id, netuid, - amount, + amount.into(), ); // Do the magic @@ -475,7 +475,7 @@ fn test_remove_stake_amount_too_low() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - 0 + AlphaCurrency::ZERO ), Error::::AmountTooLow ); @@ -493,7 +493,7 @@ fn test_remove_stake_below_min_stake() { register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 192213123); let min_stake = DefaultMinStake::::get(); - let amount = min_stake / 2; + let amount = AlphaCurrency::from(min_stake / 2); // Some basic assertions assert_eq!( @@ -520,7 +520,7 @@ fn test_remove_stake_below_min_stake() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - amount - 1 + amount - 1.into() ), Error::::AmountTooLow ); @@ -537,7 +537,8 @@ fn test_remove_stake_below_min_stake() { &hotkey_account_id, &coldkey_account_id, netuid, - ) == 0 + ) + .is_zero() ); }); } @@ -561,7 +562,7 @@ fn test_add_stake_partial_below_min_stake_fails() { ); // Setup reserves so that price is 1.0 and init swap - mock::setup_reserves(netuid, amount * 10, amount * 10); + mock::setup_reserves(netuid, amount * 10, (amount * 10).into()); // Force the swap to initialize SubtensorModule::swap_tao_for_alpha(netuid, 0, 1_000_000_000_000).unwrap(); @@ -597,7 +598,7 @@ fn test_add_stake_partial_below_min_stake_fails() { fn test_remove_stake_err_signature() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(4968585); - let amount = 10000; // Amount to be removed + let amount = AlphaCurrency::from(10000); // Amount to be removed let netuid = NetUid::from(1); assert_err!( @@ -626,14 +627,14 @@ fn test_remove_stake_ok_hotkey_does_not_belong_to_coldkey() { &hotkey_id, &other_cold_key, netuid, - amount, + amount.into(), ); assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(other_cold_key), hotkey_id, netuid, - amount, + amount.into(), )); }); } @@ -653,7 +654,7 @@ fn test_remove_stake_no_enough_stake() { RuntimeOrigin::signed(coldkey_id), hotkey_id, netuid, - amount, + amount.into(), ), Error::::NotEnoughStakeToWithdraw ); @@ -693,7 +694,7 @@ fn test_remove_stake_total_balance_no_change() { &hotkey_account_id, &coldkey_account_id, netuid, - amount, + amount.into(), ); // Add subnet TAO for the equivalent amount added at price @@ -707,7 +708,7 @@ fn test_remove_stake_total_balance_no_change() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - amount + amount.into() )); let fee = ::SwapInterface::approx_fee_amount(netuid.into(), amount); @@ -747,7 +748,7 @@ fn test_add_stake_insufficient_liquidity() { // 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Check the error assert_noop!( @@ -777,7 +778,7 @@ fn test_remove_stake_insufficient_liquidity() { // Simulate stake for hotkey let reserve = u64::MAX / 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); let alpha = SubtensorModule::stake_into_subnet( &hotkey, @@ -791,7 +792,7 @@ fn test_remove_stake_insufficient_liquidity() { // 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Check the error assert_noop!( @@ -801,7 +802,7 @@ fn test_remove_stake_insufficient_liquidity() { // Mock provided liquidity - remove becomes successful SubnetTaoProvided::::insert(netuid, amount_staked + 1); - SubnetAlphaInProvided::::insert(netuid, 1); + SubnetAlphaInProvided::::insert(netuid, AlphaCurrency::from(1)); assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey), hotkey, @@ -828,7 +829,7 @@ fn test_remove_stake_total_issuance_no_change() { // 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); + mock::setup_reserves(netuid, amount * 100, (amount * 100).into()); // Some basic assertions assert_eq!( @@ -932,6 +933,8 @@ fn test_remove_prev_epoch_stake() { ] .into_iter() .for_each(|(amount_to_stake, alpha_divs, hotkey_alpha)| { + let alpha_divs = AlphaCurrency::from(alpha_divs); + let hotkey_alpha = AlphaCurrency::from(hotkey_alpha); let subnet_owner_coldkey = U256::from(1); let subnet_owner_hotkey = U256::from(2); let hotkey_account_id = U256::from(581337); @@ -945,7 +948,7 @@ fn test_remove_prev_epoch_stake() { 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); + mock::setup_reserves(netuid, amount_to_stake * 10, (amount_to_stake * 10).into()); // Stake to hotkey account, and check if the result is ok let (_, fee) = mock::swap_tao_to_alpha(netuid, amount); @@ -1001,11 +1004,11 @@ fn test_staking_sets_div_variables() { // Verify that divident variables are clear in the beginning assert_eq!( AlphaDividendsPerSubnet::::get(netuid, hotkey_account_id), - 0 + AlphaCurrency::ZERO ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(hotkey_account_id, netuid), - 0 + AlphaCurrency::ZERO ); // Stake to hotkey account, and check if the result is ok @@ -1019,11 +1022,11 @@ fn test_staking_sets_div_variables() { // Verify that divident variables are still clear in the beginning assert_eq!( AlphaDividendsPerSubnet::::get(netuid, hotkey_account_id), - 0 + AlphaCurrency::ZERO ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(hotkey_account_id, netuid), - 0 + AlphaCurrency::ZERO ); // Wait for 1 epoch @@ -1036,11 +1039,13 @@ fn test_staking_sets_div_variables() { netuid, ); - assert!(AlphaDividendsPerSubnet::::get(netuid, hotkey_account_id) > 0); + assert!( + AlphaDividendsPerSubnet::::get(netuid, hotkey_account_id) > AlphaCurrency::ZERO + ); assert_abs_diff_eq!( TotalHotkeyAlphaLastEpoch::::get(hotkey_account_id, netuid), stake, - epsilon = stake / 100_000 + epsilon = stake / 100_000.into() ); }); } @@ -1099,7 +1104,7 @@ fn test_add_stake_to_hotkey_account_ok() { &hotkey_id, &coldkey_id, netuid, - amount, + amount.into(), ); // The stake that is now in the account, should equal the amount @@ -1130,7 +1135,7 @@ fn test_remove_stake_from_hotkey_account() { &hotkey_id, &coldkey_id, netuid, - amount, + amount.into(), ); // Prelimiary checks @@ -1145,7 +1150,7 @@ fn test_remove_stake_from_hotkey_account() { &hotkey_id, &coldkey_id, netuid, - amount, + amount.into(), ); // The stake on the hotkey account should be 0 @@ -1178,16 +1183,16 @@ fn test_remove_stake_from_hotkey_account_registered_in_various_networks() { &hotkey_id, &coldkey_id, netuid, - amount, + amount.into(), ); assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid, neuron_uid), - amount + amount.into() ); assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid_ex, neuron_uid_ex), - 0 + AlphaCurrency::ZERO ); // Remove all stake @@ -1195,17 +1200,17 @@ fn test_remove_stake_from_hotkey_account_registered_in_various_networks() { &hotkey_id, &coldkey_id, netuid, - amount, + amount.into(), ); // assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid, neuron_uid), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_uid_and_subnetwork(netuid_ex, neuron_uid_ex), - 0 + AlphaCurrency::ZERO ); }); } @@ -1354,7 +1359,7 @@ fn test_has_enough_stake_yes() { &hotkey_id, &coldkey_id, netuid, - intial_amount, + intial_amount.into(), ); assert_abs_diff_eq!( @@ -1368,13 +1373,13 @@ fn test_has_enough_stake_yes() { &coldkey_id, netuid ), - intial_amount + intial_amount.into() ); assert_ok!(SubtensorModule::calculate_reduced_stake_on_subnet( &hotkey_id, &coldkey_id, netuid, - intial_amount / 2 + (intial_amount / 2).into() )); }); } @@ -1390,7 +1395,7 @@ fn test_has_enough_stake_no() { &hotkey_id, &coldkey_id, netuid, - intial_amount, + intial_amount.into(), ); assert_abs_diff_eq!( @@ -1404,14 +1409,14 @@ fn test_has_enough_stake_no() { &coldkey_id, netuid ), - intial_amount + intial_amount.into() ); assert_err!( SubtensorModule::calculate_reduced_stake_on_subnet( &hotkey_id, &coldkey_id, netuid, - intial_amount * 2 + (intial_amount * 2).into() ), Error::::NotEnoughStakeToWithdraw ); @@ -1436,14 +1441,14 @@ fn test_has_enough_stake_no_for_zero() { &coldkey_id, netuid ), - intial_amount + intial_amount.into() ); assert_err!( SubtensorModule::calculate_reduced_stake_on_subnet( &hotkey_id, &coldkey_id, netuid, - 1_000 + 1_000.into() ), Error::::NotEnoughStakeToWithdraw ); @@ -1458,7 +1463,7 @@ fn test_non_existent_account() { &U256::from(0), &(U256::from(0)), netuid, - 10, + 10.into(), ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1466,7 +1471,7 @@ fn test_non_existent_account() { &U256::from(0), netuid ), - 10 + 10.into() ); // No subnets => no iteration => zero total stake assert_eq!( @@ -1557,7 +1562,7 @@ fn test_clear_small_nominations() { )); let alpha_stake1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold1, netuid); - let unstake_amount1 = alpha_stake1 * 997 / 1000; + let unstake_amount1 = AlphaCurrency::from(alpha_stake1.to_u64() * 997 / 1000); let small1 = alpha_stake1 - unstake_amount1; remove_stake_rate_limit_for_tests(&hot1, &cold1, netuid); assert_ok!(SubtensorModule::remove_stake( @@ -1581,7 +1586,7 @@ fn test_clear_small_nominations() { )); let alpha_stake2 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold2, netuid); - let unstake_amount2 = alpha_stake2 * 997 / 1000; + let unstake_amount2 = AlphaCurrency::from(alpha_stake2.to_u64() * 997 / 1000); let small2 = alpha_stake2 - unstake_amount2; remove_stake_rate_limit_for_tests(&hot1, &cold2, netuid); assert_ok!(SubtensorModule::remove_stake( @@ -1614,7 +1619,9 @@ fn test_clear_small_nominations() { // Set min nomination to above small1 and small2 let total_hot1_stake_before = TotalHotkeyAlpha::::get(hot1, netuid); let total_stake_before = TotalStake::::get(); - SubtensorModule::set_nominator_min_required_stake(small1.min(small2) * 2); + SubtensorModule::set_nominator_min_required_stake( + (small1.to_u64().min(small2.to_u64()) * 2).into(), + ); // Run clear all small nominations (removes delegations under 10) SubtensorModule::clear_small_nominations(); @@ -1624,7 +1631,7 @@ fn test_clear_small_nominations() { ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold2, netuid), - 0 + AlphaCurrency::ZERO ); // Balances have been added back into accounts. @@ -1636,7 +1643,7 @@ fn test_clear_small_nominations() { assert_abs_diff_eq!( TotalHotkeyAlpha::::get(hot1, netuid), total_hot1_stake_before - small2, - epsilon = 1 + epsilon = 1.into() ); assert!(TotalStake::::get() < total_stake_before); }); @@ -2066,13 +2073,13 @@ fn test_get_total_delegated_stake_after_unstaking() { ); remove_stake_rate_limit_for_tests(&delegator, &delegate_hotkey, netuid); // Unstake part of the delegation - let unstake_amount_alpha = delegated_alpha / 2; + let unstake_amount_alpha = delegated_alpha / 2.into(); remove_stake_rate_limit_for_tests(&delegate_hotkey, &delegator, netuid); assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(delegator), delegate_hotkey, netuid, - unstake_amount_alpha + unstake_amount_alpha.into() )); let current_price = ::SwapInterface::current_alpha_price(netuid.into()); @@ -2229,9 +2236,9 @@ fn test_get_alpha_share_stake_multiple_delegators() { // Total subnet stake should match the sum of delegators' stakes minus existential deposits. assert_abs_diff_eq!( - actual_total_stake, + AlphaCurrency::from(actual_total_stake), expected_total_stake, - epsilon = expected_total_stake / 1000 + epsilon = expected_total_stake / 1000.into() ); }); } @@ -2428,7 +2435,7 @@ fn test_add_stake_fee_goes_to_subnet_tao() { )); // Calculate expected stake - let expected_alpha = tao_to_stake - existential_deposit - fee; + let expected_alpha = AlphaCurrency::from(tao_to_stake - existential_deposit - fee); let actual_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); let subnet_tao_after = SubnetTAO::::get(netuid); @@ -2437,7 +2444,7 @@ fn test_add_stake_fee_goes_to_subnet_tao() { assert_abs_diff_eq!( actual_alpha, expected_alpha, - epsilon = expected_alpha / 1000 + epsilon = expected_alpha / 1000.into() ); // Subnet TAO should have increased by the full tao_to_stake amount @@ -2488,7 +2495,7 @@ fn test_remove_stake_fee_goes_to_subnet_tao() { assert_abs_diff_eq!( subnet_tao_before, subnet_tao_after, - epsilon = alpha_to_unstake / 1000 + epsilon = alpha_to_unstake.to_u64() / 1000 ); // User balance should decrease by 2x fee as a result of staking + unstaking @@ -2506,8 +2513,8 @@ fn test_remove_stake_fee_realistic_values() { let subnet_owner_hotkey = U256::from(1002); let hotkey = U256::from(2); let coldkey = U256::from(3); - let alpha_to_unstake = 111_180_000_000; - let alpha_divs = 2_816_190; + let alpha_to_unstake = AlphaCurrency::from(111_180_000_000); + let alpha_divs = AlphaCurrency::from(2_816_190); let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); @@ -2518,9 +2525,9 @@ fn test_remove_stake_fee_realistic_values() { // A hotkey has 111 Alpha stake and is unstaking all Alpha. // Alpha dividends of this hotkey are ~0.0028 // 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); - mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in.to_num()); + let tao_reserve = 3_896_056_559_708_u64; + let alpha_in = 128_011_331_299_964_u64; + mock::setup_reserves(netuid, tao_reserve, alpha_in.into()); AlphaDividendsPerSubnet::::insert(netuid, hotkey, alpha_divs); TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, alpha_to_unstake); @@ -2763,10 +2770,10 @@ fn test_add_stake_limit_validate() { let netuid = add_dynamic_network(&hotkey, &coldkey); // Force-set alpha in and tao reserve to make price equal 1.5 - let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); - SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + let tao_reserve = 150_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(netuid, tao_reserve); + SubnetAlphaIn::::insert(netuid, alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -2820,7 +2827,7 @@ fn test_remove_stake_limit_validate() { let hotkey = U256::from(533453); let coldkey = U256::from(55453); let stake_amount = 300_000_000_000; - let unstake_amount = 150_000_000_000; + let unstake_amount = AlphaCurrency::from(150_000_000_000); // add network let netuid = add_dynamic_network(&hotkey, &coldkey); @@ -2830,14 +2837,14 @@ fn test_remove_stake_limit_validate() { &hotkey, &coldkey, netuid, - stake_amount, + stake_amount.into(), ); // 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 tao_reserve = 150_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(netuid, tao_reserve); + SubnetAlphaIn::::insert(netuid, alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -2892,7 +2899,7 @@ fn test_stake_overflow() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); // Setup liquidity with 21M TAO values - mock::setup_reserves(netuid, amount, amount); + mock::setup_reserves(netuid, amount, amount.into()); // Stake and check if the result is ok let (expected_alpha, _) = mock::swap_tao_to_alpha(netuid, amount); @@ -2937,7 +2944,7 @@ fn test_stake_low_liquidity_validate() { // 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Add stake call let call = RuntimeCall::SubtensorModule(SubtensorCall::add_stake { @@ -2986,7 +2993,7 @@ fn test_unstake_low_liquidity_validate() { // Simulate stake for hotkey let reserve = u64::MAX / 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); let alpha = SubtensorModule::stake_into_subnet( &hotkey, @@ -3000,7 +3007,7 @@ fn test_unstake_low_liquidity_validate() { // 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // Remove stake call let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake { @@ -3049,7 +3056,7 @@ fn test_unstake_all_validate() { // Simulate stake for hotkey SubnetTAO::::insert(netuid, u64::MAX / 1000); - SubnetAlphaIn::::insert(netuid, u64::MAX / 1000); + SubnetAlphaIn::::insert(netuid, AlphaCurrency::from(u64::MAX / 1000)); SubtensorModule::stake_into_subnet( &hotkey, &coldkey, @@ -3062,7 +3069,7 @@ fn test_unstake_all_validate() { // 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); + mock::setup_reserves(netuid, reserve, reserve.into()); // unstake_all call let call = RuntimeCall::SubtensorModule(SubtensorCall::unstake_all { hotkey }); @@ -3228,6 +3235,7 @@ fn test_max_amount_add_dynamic() { .into_iter() .for_each(|(tao_in, alpha_in, limit_price, expected_max_swappable)| { new_test_ext(0).execute_with(|| { + let alpha_in = AlphaCurrency::from(alpha_in); 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); @@ -3239,7 +3247,7 @@ fn test_max_amount_add_dynamic() { // Force the swap to initialize SubtensorModule::swap_tao_for_alpha(netuid, 0, 1_000_000_000_000).unwrap(); - if alpha_in != 0 { + if !alpha_in.is_zero() { let expected_price = U96F32::from_num(tao_in) / U96F32::from_num(alpha_in); assert_abs_diff_eq!( ::SwapInterface::current_alpha_price(netuid.into()) @@ -3267,25 +3275,25 @@ fn test_max_amount_remove_root() { // 0 price on root => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(NetUid::ROOT, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.5 price on root => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(NetUid::ROOT, 500_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.999999... price on root => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(NetUid::ROOT, 999_999_999), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.0 price on root => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(NetUid::ROOT, 1_000_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.000...001 price on root => max is 0 @@ -3311,19 +3319,19 @@ fn test_max_amount_remove_stable() { // 0 price => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(netuid, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.999999... price => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(netuid, 999_999_999), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.0 price => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_remove(netuid, 1_000_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.000...001 price => max is 0 @@ -3446,11 +3454,12 @@ fn test_max_amount_remove_dynamic() { .iter() .for_each( |&(tao_in, alpha_in, limit_price, ref expected_max_swappable)| { + let alpha_in = AlphaCurrency::from(alpha_in); // 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 { + if !alpha_in.is_zero() { let expected_price = I96F32::from_num(tao_in) / I96F32::from_num(alpha_in); assert_eq!( ::SwapInterface::current_alpha_price(netuid.into()), @@ -3464,12 +3473,11 @@ fn test_max_amount_remove_dynamic() { Error::::ZeroMaxStakeAmount ), Ok(v) => { - let expected = v.saturating_add((*v as f64 * 0.003) as u64); - + let v = AlphaCurrency::from(*v); assert_abs_diff_eq!( SubtensorModule::get_max_amount_remove(netuid, limit_price).unwrap(), - expected, - epsilon = expected / 100 + v, + epsilon = v / 100.into() ); } } @@ -3485,25 +3493,25 @@ fn test_max_amount_move_root_root() { // 0 price on (root, root) exchange => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.5 price on (root, root) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 500_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.999999... price on (root, root) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 999_999_999), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.0 price on (root, root) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, NetUid::ROOT, 1_000_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.000...001 price on (root, root) => max is 0 @@ -3530,25 +3538,25 @@ fn test_max_amount_move_root_stable() { // 0 price on (root, stable) exchange => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.5 price on (root, stable) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 500_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 0.999999... price on (root, stable) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 999_999_999), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.0 price on (root, stable) => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(NetUid::ROOT, netuid, 1_000_000_000), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 1.000...001 price on (root, stable) => max is 0 @@ -3579,10 +3587,10 @@ fn test_max_amount_move_stable_dynamic() { let dynamic_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); // 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 tao_reserve = 50_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(dynamic_netuid, tao_reserve); + SubnetAlphaIn::::insert(dynamic_netuid, alpha_in); let current_price = ::SwapInterface::current_alpha_price(dynamic_netuid.into()); assert_eq!(current_price, U96F32::from_num(0.5)); @@ -3592,7 +3600,7 @@ fn test_max_amount_move_stable_dynamic() { // 0 price => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(stable_netuid, dynamic_netuid, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // 2.0 price => max is 0 @@ -3608,12 +3616,11 @@ 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, 500_000_000) .unwrap(), - tao_reserve_u64 + (tao_reserve_u64 as f64 * 0.003) as u64, - epsilon = tao_reserve_u64 / 100, + AlphaCurrency::from(tao_reserve + (tao_reserve as f64 * 0.003) as u64), + epsilon = AlphaCurrency::from(tao_reserve / 100), ); // Precision test: @@ -3621,7 +3628,7 @@ fn test_max_amount_move_stable_dynamic() { assert!( SubtensorModule::get_max_amount_move(stable_netuid, dynamic_netuid, 1_999_999_000) .unwrap() - > 0 + > AlphaCurrency::ZERO ); // Max price doesn't panic and returns something meaningful @@ -3654,10 +3661,10 @@ fn test_max_amount_move_dynamic_stable() { let dynamic_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); // 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(dynamic_netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(dynamic_netuid, alpha_in.to_num::()); + let tao_reserve = 150_000_000_000_u64; + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(dynamic_netuid, tao_reserve); + SubnetAlphaIn::::insert(dynamic_netuid, alpha_in); let current_price = ::SwapInterface::current_alpha_price(dynamic_netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -3667,18 +3674,21 @@ fn test_max_amount_move_dynamic_stable() { // 0 price => max is u64::MAX assert_eq!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 0), - Ok(u64::MAX) + Ok(AlphaCurrency::MAX) ); // Low price values don't blow things up assert!( - SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 1).unwrap() > 0 + SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 1).unwrap() + > AlphaCurrency::ZERO ); assert!( - SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 2).unwrap() > 0 + SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 2).unwrap() + > AlphaCurrency::ZERO ); assert!( - SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 3).unwrap() > 0 + SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 3).unwrap() + > AlphaCurrency::ZERO ); // 1.5000...1 price => max is 0 @@ -3690,18 +3700,17 @@ fn test_max_amount_move_dynamic_stable() { // 1.5 price => max is 0 because of non-zero slippage assert_abs_diff_eq!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 1_500_000_000) - .unwrap_or(0), - 0, - epsilon = 10_000 + .unwrap_or(AlphaCurrency::ZERO), + AlphaCurrency::ZERO, + epsilon = 10_000.into() ); // 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, 375_000_000) .unwrap(), - alpha_in_u64 + (alpha_in_u64 as f64 * 0.003) as u64, - epsilon = alpha_in_u64 / 1000, + alpha_in, + epsilon = alpha_in / 1000.into(), ); // Precision test: @@ -3709,24 +3718,24 @@ fn test_max_amount_move_dynamic_stable() { assert!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, 1_499_999_999) .unwrap() - > 0 + > AlphaCurrency::ZERO ); // Max price doesn't panic and returns something meaningful assert!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, u64::MAX) - .unwrap_or(0) - < 21_000_000_000_000_000 + .unwrap_or(AlphaCurrency::ZERO) + < 21_000_000_000_000_000.into() ); assert!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, u64::MAX - 1) - .unwrap_or(0) - < 21_000_000_000_000_000 + .unwrap_or(AlphaCurrency::ZERO) + < 21_000_000_000_000_000.into() ); assert!( SubtensorModule::get_max_amount_move(dynamic_netuid, stable_netuid, u64::MAX / 2) - .unwrap_or(0) - < 21_000_000_000_000_000 + .unwrap_or(AlphaCurrency::ZERO) + < 21_000_000_000_000_000.into() ); }); } @@ -3925,15 +3934,20 @@ fn test_max_amount_move_dynamic_dynamic() { expected_max_swappable, precision, )| { + let alpha_in_1 = AlphaCurrency::from(alpha_in_1); + let alpha_in_2 = AlphaCurrency::from(alpha_in_2); + let expected_max_swappable = AlphaCurrency::from(expected_max_swappable); // Forse-set alpha in and tao reserve to achieve relative price of subnets SubnetTAO::::insert(origin_netuid, tao_in_1); SubnetAlphaIn::::insert(origin_netuid, alpha_in_1); SubnetTAO::::insert(destination_netuid, tao_in_2); SubnetAlphaIn::::insert(destination_netuid, alpha_in_2); - if (alpha_in_1 != 0) && (alpha_in_2 != 0) { - let origin_price = I96F32::from_num(tao_in_1) / I96F32::from_num(alpha_in_1); - let dest_price = I96F32::from_num(tao_in_2) / I96F32::from_num(alpha_in_2); + if !alpha_in_1.is_zero() && !alpha_in_2.is_zero() { + let origin_price = + I96F32::from_num(tao_in_1) / I96F32::from_num(u64::from(alpha_in_1)); + let dest_price = + I96F32::from_num(tao_in_2) / I96F32::from_num(u64::from(alpha_in_2)); if dest_price != 0 { let expected_price = origin_price / dest_price; assert_eq!( @@ -3953,9 +3967,9 @@ fn test_max_amount_move_dynamic_dynamic() { destination_netuid, limit_price ) - .unwrap_or(0u64), + .unwrap_or(AlphaCurrency::ZERO), expected_max_swappable, - epsilon = precision + epsilon = precision.into() ); }, ); @@ -3974,8 +3988,8 @@ fn test_add_stake_limit_ok() { // Forse-set alpha in and tao reserve to make price equal 1.5 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 alpha_in = AlphaCurrency::from(100_000_000_000_u64); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -3987,7 +4001,7 @@ fn test_add_stake_limit_ok() { // 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 = 24_000_000_000; - let expected_executed_stake = 75_000_000_000; + let expected_executed_stake = AlphaCurrency::from(75_000_000_000); // Add stake with slippage safety and check if the result is ok assert_ok!(SubtensorModule::add_stake_limit( @@ -4007,7 +4021,7 @@ fn test_add_stake_limit_ok() { netuid ), expected_executed_stake, - epsilon = expected_executed_stake / 1000, + epsilon = expected_executed_stake / 1000.into(), ); // Check that 450 TAO less fees balance still remains free on coldkey @@ -4045,9 +4059,9 @@ fn test_add_stake_limit_fill_or_kill() { // Force-set alpha in and tao reserve to make price equal 1.5 let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in = AlphaCurrency::from(100_000_000_000_u64); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); 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 @@ -4099,11 +4113,11 @@ fn test_add_stake_limit_partial_zero_max_stake_amount_error() { let amount = 19980000000; let limit_price = 26953618; let tao_reserve: U96F32 = U96F32::from_num(5_032_494_439_940_u64); - let alpha_in: U96F32 = U96F32::from_num(186_268_425_402_874_u64); + let alpha_in = AlphaCurrency::from(186_268_425_402_874); let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, amount); @@ -4137,9 +4151,9 @@ fn test_remove_stake_limit_ok() { // 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); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); // Stake to hotkey account, and check if the result is ok assert_ok!(SubtensorModule::add_stake( @@ -4160,7 +4174,7 @@ fn test_remove_stake_limit_ok() { let limit_price = (current_price.to_num::() * 990_000_000_f64) as u64; // Alpha unstaked - calculated using formula from delta_in() - let expected_alpha_reduction = (0.00138 * alpha_in.to_num::()) as u64; + let expected_alpha_reduction = (0.00138 * (alpha_in.to_u64() as f64)) as u64; let fee: u64 = (expected_alpha_reduction as f64 * 0.003) as u64; // Remove stake with slippage safety @@ -4169,7 +4183,7 @@ fn test_remove_stake_limit_ok() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - alpha_before / 2, + alpha_before / 2.into(), limit_price, true )); @@ -4182,8 +4196,8 @@ fn test_remove_stake_limit_ok() { // Check if stake has decreased properly assert_abs_diff_eq!( alpha_before - alpha_after, - expected_alpha_reduction + fee, - epsilon = expected_alpha_reduction / 10, + AlphaCurrency::from(expected_alpha_reduction + fee), + epsilon = AlphaCurrency::from(expected_alpha_reduction / 10), ); }); } @@ -4193,8 +4207,8 @@ fn test_remove_stake_limit_fill_or_kill() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(533453); let coldkey_account_id = U256::from(55453); - let stake_amount = 300_000_000_000; - let unstake_amount = 150_000_000_000; + let stake_amount = AlphaCurrency::from(300_000_000_000); + let unstake_amount = AlphaCurrency::from(150_000_000_000); // add network let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); @@ -4209,9 +4223,9 @@ fn test_remove_stake_limit_fill_or_kill() { // 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); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -4237,7 +4251,7 @@ fn test_remove_stake_limit_fill_or_kill() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - unstake_amount / 100, + unstake_amount / 100.into(), limit_price, false ),); @@ -4256,10 +4270,10 @@ fn test_add_stake_specific_stake_into_subnet_fail() { let existing_shares: U64F64 = U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX)); - let existing_stake = 36_711_495_953; + let existing_stake = AlphaCurrency::from(36_711_495_953); let tao_in = 2_409_892_148_947; - let alpha_in = 15_358_708_513_716; + let alpha_in = AlphaCurrency::from(15_358_708_513_716); let tao_staked = 200_000_000; @@ -4296,16 +4310,18 @@ fn test_add_stake_specific_stake_into_subnet_fail() { ); // Add stake as new hotkey - let expected_alpha = ::SwapInterface::swap( - netuid.into(), - OrderType::Buy, - tao_staked, - ::SwapInterface::max_price(), - false, - true, - ) - .map(|v| v.amount_paid_out) - .unwrap_or_default(); + let expected_alpha = AlphaCurrency::from( + ::SwapInterface::swap( + netuid.into(), + OrderType::Buy, + tao_staked, + ::SwapInterface::max_price(), + false, + true, + ) + .map(|v| v.amount_paid_out) + .unwrap_or_default(), + ); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, @@ -4314,7 +4330,7 @@ fn test_add_stake_specific_stake_into_subnet_fail() { )); // Check we have non-zero staked - assert!(expected_alpha > 0); + assert!(expected_alpha > AlphaCurrency::ZERO); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_account_id, @@ -4322,7 +4338,7 @@ fn test_add_stake_specific_stake_into_subnet_fail() { netuid ), expected_alpha, - epsilon = expected_alpha / 1000 + epsilon = expected_alpha / 1000.into() ); }); } @@ -4357,7 +4373,9 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { netuid, ); remove_stake_rate_limit_for_tests(&hotkey_account_id, &coldkey_account_id, netuid); - let remove_amount = (U64F64::from_num(alpha) * U64F64::from_num(0.999991)).to_num::(); + let remove_amount = AlphaCurrency::from( + (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( @@ -4382,7 +4400,7 @@ fn test_remove_99_9991_per_cent_stake_removes_all() { &coldkey_account_id, netuid, ); - assert_eq!(new_alpha, 0); + assert!(new_alpha.is_zero()); }); } @@ -4417,12 +4435,15 @@ 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; + let fee = + mock::swap_alpha_to_tao(netuid, ((alpha.to_u64() as f64 * 0.99) as u64).into()).1 + fee; assert_ok!(SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - (U64F64::from_num(alpha) * U64F64::from_num(0.99)).to_num::() + (U64F64::from_num(alpha.to_u64()) * U64F64::from_num(0.99)) + .to_num::() + .into() )); // Check that all alpha was unstaked and 99% TAO balance was returned (less fees) @@ -4442,7 +4463,11 @@ fn test_remove_99_9989_per_cent_stake_leaves_a_little() { &coldkey_account_id, netuid, ); - assert_abs_diff_eq!(new_alpha, (alpha as f64 * 0.01) as u64, epsilon = 10); + assert_abs_diff_eq!( + new_alpha, + AlphaCurrency::from((alpha.to_u64() as f64 * 0.01) as u64), + epsilon = 10.into() + ); }); } @@ -4453,8 +4478,8 @@ fn test_move_stake_limit_partial() { let subnet_owner_hotkey = U256::from(1002); let coldkey = U256::from(1); let hotkey = U256::from(2); - let stake_amount = 150_000_000_000; - let move_amount = 150_000_000_000; + let stake_amount = AlphaCurrency::from(150_000_000_000); + let move_amount = AlphaCurrency::from(150_000_000_000); // add network let origin_netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); @@ -4473,11 +4498,11 @@ fn test_move_stake_limit_partial() { // Forse-set alpha in and tao reserve to make price equal 1.5 on both origin and destination, // but there's much more liquidity on destination, so its price wouldn't go up when restaked let tao_reserve: U96F32 = U96F32::from_num(150_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(origin_netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(origin_netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(origin_netuid, alpha_in); SubnetTAO::::insert(destination_netuid, (tao_reserve * 100_000).to_num::()); - SubnetAlphaIn::::insert(destination_netuid, (alpha_in * 100_000).to_num::()); + SubnetAlphaIn::::insert(destination_netuid, alpha_in * 100_000.into()); let current_price = ::SwapInterface::current_alpha_price(origin_netuid.into()); assert_eq!(current_price, U96F32::from_num(1.5)); @@ -4503,7 +4528,11 @@ fn test_move_stake_limit_partial() { origin_netuid, ); - assert_abs_diff_eq!(new_alpha, 149_000_000_000, epsilon = 100_000_000,); + assert_abs_diff_eq!( + new_alpha, + AlphaCurrency::from(149_000_000_000), + epsilon = 100_000_000.into() + ); }); } @@ -4516,7 +4545,7 @@ fn test_unstake_all_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 = AlphaCurrency::from(190_000_000_000); // 190 Alpha let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, hotkey, coldkey, 192213123); @@ -4530,8 +4559,12 @@ 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::from_num(u64::from(mock::SwapMinimumReserve::get()) - 1); - let alpha_reserves = I110F18::from(stake_amount + 10_000_000); - mock::setup_reserves(netuid, remaining_tao.to_num(), alpha_reserves.to_num()); + let alpha_reserves = I110F18::from(stake_amount.to_u64() + 10_000_000); + mock::setup_reserves( + netuid, + remaining_tao.to_num(), + alpha_reserves.to_num::().into(), + ); // Try to unstake, but we reduce liquidity too far @@ -4543,7 +4576,7 @@ fn test_unstake_all_hits_liquidity_min() { // 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_abs_diff_eq!(new_alpha, stake_amount, epsilon = AlphaCurrency::ZERO); }); } @@ -4576,16 +4609,16 @@ fn test_unstake_all_alpha_hits_liquidity_min() { .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 alpha_reserves = I110F18::from(u64::from(alpha) + 10_000_000); let k = I110F18::from_fixed(remaining_tao) - .saturating_mul(alpha_reserves.saturating_add(I110F18::from(alpha))); + .saturating_mul(alpha_reserves.saturating_add(I110F18::from(u64::from(alpha)))); let tao_reserves = k.safe_div(alpha_reserves); mock::setup_reserves( netuid, tao_reserves.to_num::() / 100_u64, - alpha_reserves.to_num(), + alpha_reserves.to_num::().into(), ); // Try to unstake, but we reduce liquidity too far @@ -4630,7 +4663,7 @@ fn test_unstake_all_alpha_works() { remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); // Setup the pool so that removing all the TAO will keep liq above min - mock::setup_reserves(netuid, stake_amount * 10, stake_amount * 100); + mock::setup_reserves(netuid, stake_amount * 10, (stake_amount * 100).into()); // Unstake all alpha to root assert_ok!(SubtensorModule::unstake_all_alpha( @@ -4640,13 +4673,13 @@ fn test_unstake_all_alpha_works() { let new_alpha = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid); - assert_abs_diff_eq!(new_alpha, 0, epsilon = 1_000); + assert_abs_diff_eq!(new_alpha, AlphaCurrency::ZERO, epsilon = 1_000.into()); let new_root = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, NetUid::ROOT, ); - assert!(new_root > 100_000); + assert!(new_root > 100_000.into()); }); } @@ -4676,8 +4709,13 @@ fn test_unstake_all_works() { )); // Setup the pool so that removing all the TAO will keep liq above min - mock::setup_reserves(netuid, stake_amount * 10, stake_amount * 100); + mock::setup_reserves( + netuid, + stake_amount * 10, + AlphaCurrency::from(stake_amount * 100), + ); remove_stake_rate_limit_for_tests(&hotkey, &coldkey, netuid); + // Unstake all alpha to free balance assert_ok!(SubtensorModule::unstake_all( RuntimeOrigin::signed(coldkey), @@ -4686,7 +4724,7 @@ 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, AlphaCurrency::ZERO, epsilon = 1_000.into()); let new_balance = SubtensorModule::get_coldkey_balance(&coldkey); assert!(new_balance > 100_000); }); @@ -4706,8 +4744,8 @@ fn test_stake_into_subnet_ok() { // 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 alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()) .to_num::(); @@ -4731,12 +4769,14 @@ fn test_stake_into_subnet_ok() { u64::MAX, false, )); - let expected_stake = (amount as f64) * 0.997 / current_price; + let fee_rate = pallet_subtensor_swap::FeeRate::::get(NetUid::from(netuid)) as f64 + / u16::MAX as f64; + let expected_stake = (amount as f64) * (1. - fee_rate) / 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, + .to_u64() as f64, expected_stake, epsilon = expected_stake / 1000., ); @@ -4757,8 +4797,8 @@ fn test_stake_into_subnet_low_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()); + let alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); let current_price = ::SwapInterface::current_alpha_price(netuid.into()) .to_num::(); @@ -4782,14 +4822,13 @@ fn test_stake_into_subnet_low_amount() { u64::MAX, false, )); - let expected_stake = ((amount as f64) * 0.997 / current_price) as u64; + let expected_stake = AlphaCurrency::from(((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, + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), expected_stake, - epsilon = expected_stake / 100, + epsilon = expected_stake / 100.into() ); }); } @@ -4808,8 +4847,8 @@ fn test_unstake_from_subnet_low_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()); + let alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Initialize swap v3 assert_ok!(::SwapInterface::swap( @@ -4846,7 +4885,7 @@ fn test_unstake_from_subnet_low_amount() { // Check if stake is zero assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid), - 0, + AlphaCurrency::ZERO, ); }); } @@ -4865,8 +4904,8 @@ fn test_stake_into_subnet_prohibitive_limit() { // 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 alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Initialize swap v3 assert_ok!(::SwapInterface::swap( @@ -4899,7 +4938,7 @@ fn test_stake_into_subnet_prohibitive_limit() { &coldkey, netuid ), - 0_u64 + AlphaCurrency::ZERO ); // Check if balance has NOT decreased @@ -4921,8 +4960,8 @@ fn test_unstake_from_subnet_prohibitive_limit() { // 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 alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Initialize swap v3 assert_ok!(::SwapInterface::swap( @@ -4996,8 +5035,8 @@ fn test_unstake_full_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()); + let alpha_in = AlphaCurrency::from(1_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Initialize swap v3 assert_ok!(::SwapInterface::swap( @@ -5041,7 +5080,7 @@ fn test_unstake_full_amount() { &coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); // Check if balance has increased accordingly @@ -5106,8 +5145,8 @@ fn test_swap_fees_tao_correctness() { // 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()); + let alpha_in = AlphaCurrency::from(400_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Check starting "total TAO" let total_tao_before = @@ -5199,7 +5238,7 @@ fn test_increase_stake_for_hotkey_and_coldkey_on_subnet_adds_to_staking_hotkeys_ &hotkey, &coldkey, netuid, - stake_amount, + stake_amount.into(), ); // Check entry exists in the staking hotkeys map @@ -5215,7 +5254,7 @@ fn test_increase_stake_for_hotkey_and_coldkey_on_subnet_adds_to_staking_hotkeys_ &hotkey, &coldkey1, netuid, - stake_amount, + stake_amount.into(), ); // Check entry exists in the staking hotkeys map for coldkey1 @@ -5230,7 +5269,7 @@ fn test_remove_stake_full_limit_ok() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(2); - let stake_amount = 10_000_000_000; + let stake_amount = AlphaCurrency::from(10_000_000_000); // add network let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); @@ -5244,9 +5283,9 @@ fn test_remove_stake_full_limit_ok() { ); let tao_reserve: U96F32 = U96F32::from_num(100_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); let limit_price = 90_000_000; @@ -5265,11 +5304,11 @@ fn test_remove_stake_full_limit_ok() { &coldkey_account_id, netuid ), - 0 + AlphaCurrency::ZERO ); let new_balance = SubtensorModule::get_coldkey_balance(&coldkey_account_id); - assert_abs_diff_eq!(new_balance, 9_066_000_000, epsilon = 1_000_000); + assert_abs_diff_eq!(new_balance, 9_086_000_000, epsilon = 1_000_000); }); } @@ -5278,7 +5317,7 @@ fn test_remove_stake_full_limit_fails_slippage_too_high() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(2); - let stake_amount = 10_000_000_000; + let stake_amount = AlphaCurrency::from(10_000_000_000); // add network let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); @@ -5292,9 +5331,9 @@ fn test_remove_stake_full_limit_fails_slippage_too_high() { ); let tao_reserve: U96F32 = U96F32::from_num(100_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); let invalid_limit_price = 910_000_000; @@ -5316,7 +5355,7 @@ fn test_remove_stake_full_limit_ok_with_no_limit_price() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); let coldkey_account_id = U256::from(2); - let stake_amount = 10_000_000_000; + let stake_amount = AlphaCurrency::from(10_000_000_000); // add network let netuid = add_dynamic_network(&hotkey_account_id, &coldkey_account_id); @@ -5330,9 +5369,9 @@ fn test_remove_stake_full_limit_ok_with_no_limit_price() { ); let tao_reserve: U96F32 = U96F32::from_num(100_000_000_000_u64); - let alpha_in: U96F32 = U96F32::from_num(100_000_000_000_u64); + let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve.to_num::()); - SubnetAlphaIn::::insert(netuid, alpha_in.to_num::()); + SubnetAlphaIn::::insert(netuid, alpha_in); // Remove stake with slippage safety assert_ok!(SubtensorModule::remove_stake_full_limit( @@ -5349,11 +5388,11 @@ fn test_remove_stake_full_limit_ok_with_no_limit_price() { &coldkey_account_id, netuid ), - 0 + AlphaCurrency::ZERO ); let new_balance = SubtensorModule::get_coldkey_balance(&coldkey_account_id); - assert_abs_diff_eq!(new_balance, 9_066_000_000, epsilon = 1_000_000); + assert_abs_diff_eq!(new_balance, 9_086_000_000, epsilon = 1_000_000); }); } /// This test verifies that minimum stake amount is sufficient to move price and apply @@ -5380,8 +5419,8 @@ fn test_default_min_stake_sufficiency() { // 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 alpha_in = AlphaCurrency::from(21_000_000_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); let current_price_before = ::SwapInterface::current_alpha_price(netuid.into()); @@ -5407,7 +5446,7 @@ fn test_default_min_stake_sufficiency() { netuid, user_alpha, )); - let fee_unstake = (fee_rate * user_alpha as f64) as u64; + let fee_unstake = (fee_rate * user_alpha.to_u64() as f64) as u64; let current_price_after_unstake = ::SwapInterface::current_alpha_price(netuid.into()); @@ -5439,8 +5478,8 @@ fn test_update_position_fees() { // 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()); + let alpha_in = AlphaCurrency::from(400_000_000_000); + mock::setup_reserves(netuid, tao_reserve.to_num(), alpha_in); // Get alpha for owner assert_ok!(SubtensorModule::add_stake( @@ -5574,7 +5613,7 @@ fn setup_positions(netuid: NetUid) { &U256::from(hotkey), &U256::from(coldkey), netuid.into(), - 1_000_000_000_000_000, + 1_000_000_000_000_000.into(), ); let tick_low = price_to_tick(low_price); @@ -5645,7 +5684,12 @@ fn test_stake_rate_limits() { )); assert_err!( - SubtensorModule::remove_stake(RuntimeOrigin::signed(cold1), hot1, netuid, amount), + SubtensorModule::remove_stake( + RuntimeOrigin::signed(cold1), + hot1, + netuid, + amount.into() + ), Error::::StakingOperationRateLimitExceeded ); diff --git a/pallets/subtensor/src/tests/staking2.rs b/pallets/subtensor/src/tests/staking2.rs index 0c98a83bb1..9e374095de 100644 --- a/pallets/subtensor/src/tests/staking2.rs +++ b/pallets/subtensor/src/tests/staking2.rs @@ -6,6 +6,7 @@ use frame_support::{ weights::Weight, }; use sp_core::U256; +use subtensor_runtime_common::{AlphaCurrency, Currency}; use subtensor_swap_interface::SwapHandler; use super::mock; @@ -24,7 +25,7 @@ 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 + let initial_subnet_alpha = AlphaCurrency::from(5_000_000_000); // 5 Alpha mock::setup_reserves(netuid, initial_subnet_tao, initial_subnet_alpha); SubnetAlphaOut::::insert(netuid, initial_subnet_alpha); @@ -33,13 +34,15 @@ fn test_stake_base_case() { // Perform 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; + let alpha_received = AlphaCurrency::from( + SubtensorModule::swap_tao_for_alpha( + netuid, + tao_to_swap, + ::SwapInterface::max_price(), + ) + .unwrap() + .amount_paid_out, + ); // Verify correct alpha calculation using constant product formula assert_eq!( @@ -85,7 +88,7 @@ fn test_share_based_staking() { let netuid = NetUid::from(1); let primary_hotkey = U256::from(1); let primary_coldkey = U256::from(2); - let stake_amount = 1_000_000_000; // 1 TAO + let stake_amount = AlphaCurrency::from(1_000_000_000); // 1 Alpha stake increase // Test Case 1: Initial Stake // The first stake should create shares 1:1 with the staked amount @@ -133,7 +136,9 @@ fn test_share_based_staking() { initial_stake + stake_amount ); assert!( - (stake_after_second as i64 - (initial_stake + stake_amount) as i64).abs() <= 1, + (stake_after_second.to_u64() as i64 - (initial_stake + stake_amount).to_u64() as i64) + .abs() + <= 1, "Total stake should double after second deposit (within rounding error)" ); @@ -153,7 +158,10 @@ fn test_share_based_staking() { stake_after_second + stake_amount ); assert!( - (stake_after_direct as i64 - (stake_after_second + stake_amount) as i64).abs() <= 1, + (stake_after_direct.to_u64() as i64 + - (stake_after_second + stake_amount).to_u64() as i64) + .abs() + <= 1, "Direct hotkey stake should be added to existing stake (within rounding error)" ); @@ -179,7 +187,7 @@ fn test_share_based_staking() { stake_amount ); assert!( - (secondary_stake as i64 - (stake_amount) as i64).abs() <= 1, + (secondary_stake.to_u64() as i64 - stake_amount.to_u64() as i64).abs() <= 1, "Secondary coldkey should receive full stake amount (within rounding error)" ); @@ -193,7 +201,10 @@ fn test_share_based_staking() { stake_after_direct + stake_amount ); assert!( - (total_hotkey_stake as i64 - (stake_after_direct + stake_amount) as i64).abs() <= 1, + (total_hotkey_stake.to_u64() as i64 + - (stake_after_direct + stake_amount).to_u64() as i64) + .abs() + <= 1, "Total hotkey stake should match sum of all coldkey stakes" ); @@ -212,10 +223,12 @@ fn test_share_based_staking() { ); // Calculate expected proportional distribution - let primary_expected = stake_after_direct as f64 - + stake_amount as f64 * (stake_after_direct as f64 / total_hotkey_stake as f64); - let secondary_expected = secondary_stake as f64 - + stake_amount as f64 * (secondary_stake as f64 / total_hotkey_stake as f64); + let primary_expected = stake_after_direct.to_u64() as f64 + + stake_amount.to_u64() as f64 + * (stake_after_direct.to_u64() as f64 / total_hotkey_stake.to_u64() as f64); + let secondary_expected = secondary_stake.to_u64() as f64 + + stake_amount.to_u64() as f64 + * (secondary_stake.to_u64() as f64 / total_hotkey_stake.to_u64() as f64); log::info!( "Primary final stake: {} (expected: {})", @@ -229,11 +242,11 @@ fn test_share_based_staking() { ); assert!( - (primary_final_stake as f64 - primary_expected).abs() <= 1.0, + (primary_final_stake.to_u64() as f64 - primary_expected).abs() <= 1.0, "Primary stake should increase proportionally" ); assert!( - (secondary_final_stake as f64 - secondary_expected).abs() <= 1.0, + (secondary_final_stake.to_u64() as f64 - secondary_expected).abs() <= 1.0, "Secondary stake should increase proportionally" ); @@ -258,7 +271,10 @@ fn test_share_based_staking() { primary_final_stake - stake_amount ); assert!( - (primary_after_removal as i64 - (primary_final_stake - stake_amount) as i64).abs() <= 1, + (primary_after_removal.to_u64() as i64 + - (primary_final_stake - stake_amount).to_u64() as i64) + .abs() + <= 1, "Stake removal should decrease balance by exact amount" ); @@ -281,7 +297,9 @@ fn test_share_based_staking() { secondary_final_stake - stake_amount ); assert!( - (secondary_after_removal as i64 - (secondary_final_stake - stake_amount) as i64).abs() + (secondary_after_removal.to_u64() as i64 + - (secondary_final_stake - stake_amount).to_u64() as i64) + .abs() <= 1, "Stake removal should decrease balance by exact amount" ); @@ -297,7 +315,9 @@ fn test_share_based_staking() { primary_after_removal + secondary_after_removal ); assert!( - (final_total as i64 - (primary_after_removal + secondary_after_removal) as i64).abs() + (final_total.to_u64() as i64 + - (primary_after_removal + secondary_after_removal).to_u64() as i64) + .abs() <= 1, "Final total should match sum of remaining stakes" ); @@ -309,7 +329,7 @@ fn test_share_based_staking() { &primary_hotkey, &primary_coldkey, netuid, - 0, + AlphaCurrency::ZERO, ); let zero_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &primary_hotkey, @@ -327,7 +347,7 @@ fn test_share_based_staking() { &primary_coldkey, netuid, ); - let excessive_amount = available_stake + 1000; + let excessive_amount = available_stake + 1000.into(); log::info!( "Attempting to remove excessive stake: {} + 1000 = {}", available_stake, @@ -386,7 +406,7 @@ fn test_share_based_staking() { netuid, ); assert!( - non_existent_coldkey_stake == 0, + non_existent_coldkey_stake.is_zero(), "Removing stake from non-existent coldkey should not change the stake" ); }); @@ -410,8 +430,8 @@ fn test_share_based_staking_denominator_precision() { let netuid = NetUid::from(1); let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); - let stake_amount = test_case.0; - let unstake_amount = test_case.1; + let stake_amount = AlphaCurrency::from(test_case.0); + let unstake_amount = AlphaCurrency::from(test_case.1); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, @@ -420,8 +440,10 @@ fn test_share_based_staking_denominator_precision() { stake_amount, ); assert_eq!( - Alpha::::get((hotkey1, coldkey1, netuid)), - stake_amount + stake_amount, + Alpha::::get((hotkey1, coldkey1, netuid)) + .to_num::() + .into(), ); SubtensorModule::decrease_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, @@ -433,13 +455,15 @@ fn test_share_based_staking_denominator_precision() { let stake1 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey1, &coldkey1, netuid, ); - let expected_remaining_stake = - if (stake_amount as f64 - unstake_amount as f64) / (stake_amount as f64) <= 0.00001 - { - 0 - } else { - stake_amount - unstake_amount - }; + let expected_remaining_stake = if (stake_amount.to_u64() as f64 + - unstake_amount.to_u64() as f64) + / (stake_amount.to_u64() as f64) + <= 0.00001 + { + AlphaCurrency::ZERO + } else { + stake_amount - unstake_amount + }; assert_eq!(stake1, expected_remaining_stake); }); }); @@ -465,9 +489,9 @@ fn test_share_based_staking_stake_unstake_inject() { let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); let coldkey2 = U256::from(3); - let stake_amount = test_case.0; - let unstake_amount = test_case.1; - let inject_amount = test_case.2; + let stake_amount = AlphaCurrency::from(test_case.0); + let unstake_amount = AlphaCurrency::from(test_case.1); + let inject_amount = AlphaCurrency::from(test_case.2); let tolerance = test_case.3; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -504,14 +528,16 @@ fn test_share_based_staking_stake_unstake_inject() { ); assert!( - (stake1 as i64 - - (stake_amount as i64 - unstake_amount as i64 + (inject_amount / 2) as i64)) + (stake1.to_u64() as i64 + - (stake_amount.to_u64() as i64 - unstake_amount.to_u64() as i64 + + (inject_amount.to_u64() / 2) as i64)) .abs() <= tolerance ); assert!( - (stake2 as i64 - - (stake_amount as i64 - unstake_amount as i64 + (inject_amount / 2) as i64)) + (stake2.to_u64() as i64 + - (stake_amount.to_u64() as i64 - unstake_amount.to_u64() as i64 + + (inject_amount.to_u64() / 2) as i64)) .abs() <= tolerance ); @@ -535,9 +561,9 @@ fn test_share_based_staking_stake_inject_stake_new() { let hotkey1 = U256::from(1); let coldkey1 = U256::from(2); let coldkey2 = U256::from(3); - let stake_amount = test_case.0; - let inject_amount = test_case.1; - let stake_amount_2 = test_case.2; + let stake_amount = AlphaCurrency::from(test_case.0); + let inject_amount = AlphaCurrency::from(test_case.1); + let stake_amount_2 = AlphaCurrency::from(test_case.2); let tolerance = test_case.3; SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -561,8 +587,12 @@ fn test_share_based_staking_stake_inject_stake_new() { &hotkey1, &coldkey2, netuid, ); - assert!((stake1 as i64 - (stake_amount + inject_amount) as i64).abs() <= tolerance); - assert!((stake2 as i64 - stake_amount_2 as i64).abs() <= tolerance); + assert!( + (stake1.to_u64() as i64 - (stake_amount.to_u64() + inject_amount.to_u64()) as i64) + .abs() + <= tolerance + ); + assert!((stake2.to_u64() as i64 - stake_amount_2.to_u64() as i64).abs() <= tolerance); }); }); } @@ -641,19 +671,19 @@ fn test_stake_fee_api() { let netuid1 = NetUid::from(2); let root_netuid = NetUid::ROOT; - let alpha_divs = 100_000_000_000; - let total_hotkey_alpha = 100_000_000_000; + let alpha_divs = AlphaCurrency::from(100_000_000_000); + let total_hotkey_alpha = AlphaCurrency::from(100_000_000_000); let tao_in = 100_000_000_000; // 100 TAO let reciprocal_price = 2; // 1 / price let stake_amount = 100_000_000_000; // Setup alpha out - SubnetAlphaOut::::insert(netuid0, 100_000_000_000); - SubnetAlphaOut::::insert(netuid1, 100_000_000_000); + SubnetAlphaOut::::insert(netuid0, AlphaCurrency::from(100_000_000_000)); + SubnetAlphaOut::::insert(netuid1, AlphaCurrency::from(100_000_000_000)); // Set pools using price - SubnetAlphaIn::::insert(netuid0, tao_in * reciprocal_price); + SubnetAlphaIn::::insert(netuid0, AlphaCurrency::from(tao_in * reciprocal_price)); SubnetTAO::::insert(netuid0, tao_in); - SubnetAlphaIn::::insert(netuid1, tao_in * reciprocal_price); + SubnetAlphaIn::::insert(netuid1, AlphaCurrency::from(tao_in * reciprocal_price)); SubnetTAO::::insert(netuid1, tao_in); // Setup alpha divs for hotkey1 @@ -787,8 +817,8 @@ fn test_stake_fee_calculation() { SubnetMechanism::::insert(netuid0, 1); SubnetMechanism::::insert(netuid1, 1); - let alpha_divs = 100_000_000_000; - let total_hotkey_alpha = 100_000_000_000; + let alpha_divs = AlphaCurrency::from(100_000_000_000); + let total_hotkey_alpha = AlphaCurrency::from(100_000_000_000); let tao_in = 100_000_000_000; // 100 TAO let reciprocal_price = 2; // 1 / price let stake_amount = 100_000_000_000_u64; @@ -796,11 +826,19 @@ fn test_stake_fee_calculation() { 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); + SubnetAlphaOut::::insert(netuid0, AlphaCurrency::from(100_000_000_000)); + SubnetAlphaOut::::insert(netuid1, AlphaCurrency::from(100_000_000_000)); // Set pools using price - mock::setup_reserves(netuid0, tao_in, tao_in * reciprocal_price); - mock::setup_reserves(netuid1, tao_in, tao_in * reciprocal_price); + mock::setup_reserves( + netuid0, + tao_in, + AlphaCurrency::from(tao_in * reciprocal_price), + ); + mock::setup_reserves( + netuid1, + tao_in, + AlphaCurrency::from(tao_in * reciprocal_price), + ); // Setup alpha divs for hotkey1 AlphaDividendsPerSubnet::::insert(netuid0, hotkey1, alpha_divs); diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index e29018d80d..d2bab08d39 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -5,6 +5,7 @@ use crate::*; use frame_support::{assert_err, assert_noop, assert_ok}; use frame_system::Config; use sp_core::U256; +use subtensor_runtime_common::AlphaCurrency; use super::mock; @@ -21,7 +22,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); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000.into()); // account 0 is the default owner for any subnet assert_eq!(SubnetOwner::::get(netuid), coldkey_account_id); @@ -67,7 +68,7 @@ fn test_do_start_call_fail_not_owner() { //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); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000.into()); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); @@ -97,7 +98,7 @@ fn test_do_start_call_fail_with_cannot_start_call_now() { //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); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000.into()); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); @@ -128,7 +129,7 @@ fn test_do_start_call_fail_for_set_again() { 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); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000.into()); // Give it some $$$ in his coldkey balance SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); @@ -169,7 +170,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); + mock::setup_reserves(netuid, 1_000_000_000, 1_000_000_000.into()); assert_eq!(SubnetOwner::::get(netuid), coldkey_account_id); @@ -391,7 +392,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { let hotkey_account_2_id: U256 = U256::from(3); let amount = DefaultMinStake::::get() * 10; - let stake_bal = 10_000_000_000; // 10 Alpha + let stake_bal = AlphaCurrency::from(10_000_000_000); // 10 Alpha let limit_price = 1_000_000_000; // not important @@ -403,7 +404,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { // Set liq high enough to not trigger other errors SubnetTAO::::set(netuid, 20_000_000_000); - SubnetAlphaIn::::set(netuid, 20_000_000_000); + SubnetAlphaIn::::set(netuid, AlphaCurrency::from(20_000_000_000)); // Register so staking *could* work register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 0); @@ -482,7 +483,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - amount, + amount.into(), limit_price, false, ) @@ -493,7 +494,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, netuid, - amount + amount.into() ), Error::::SubtokenDisabled ); @@ -502,7 +503,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { SubtensorModule::recycle_alpha( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, - amount, + amount.into(), netuid ), Error::::SubtokenDisabled @@ -512,7 +513,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { SubtensorModule::burn_alpha( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id, - amount, + amount.into(), netuid ), Error::::SubtokenDisabled @@ -525,7 +526,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { hotkey_account_2_id, netuid, netuid2, - amount, + amount.into(), ), Error::::SubtokenDisabled ); @@ -537,7 +538,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { hotkey_account_2_id, netuid, netuid2, - amount, + amount.into(), ), Error::::SubtokenDisabled ); @@ -548,7 +549,7 @@ fn test_subtoken_enable_reject_trading_before_enable() { hotkey_account_id, netuid, netuid2, - amount, + amount.into(), ), Error::::SubtokenDisabled ); @@ -567,16 +568,16 @@ fn test_subtoken_enable_trading_ok_with_enable() { // stake big enough let stake_amount = DefaultMinStake::::get() * 10000; // unstake, transfer, swap just very little - let unstake_amount = DefaultMinStake::::get() * 10; + let unstake_amount = AlphaCurrency::from(DefaultMinStake::::get() * 10); 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); + mock::setup_reserves(netuid, reserve, reserve.into()); + mock::setup_reserves(netuid2, reserve, reserve.into()); + SubnetAlphaOut::::insert(netuid, AlphaCurrency::from(reserve)); + SubnetAlphaOut::::insert(netuid2, AlphaCurrency::from(reserve)); // Register so staking works register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 0); diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index 42ab701a72..bab264a3c6 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -12,7 +12,7 @@ use frame_system::{Config, RawOrigin}; use sp_core::{Get, H256, U256}; use sp_runtime::{DispatchError, traits::TxBaseImplication}; use substrate_fixed::types::U96F32; -use subtensor_runtime_common::SubnetInfo; +use subtensor_runtime_common::{AlphaCurrency, Currency, SubnetInfo}; use subtensor_swap_interface::{OrderType, SwapHandler}; use super::mock; @@ -91,7 +91,7 @@ fn test_swap_total_coldkey_stake() { register_ok_neuron(netuid, other_hotkey, other_coldkey, 1001000); let reserve = stake * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); assert_ok!(SubtensorModule::add_stake( <::RuntimeOrigin>::signed(old_coldkey), @@ -299,7 +299,7 @@ fn test_swap_idempotency() { let stake = DefaultMinStake::::get() * 10; let reserve = stake * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Add a network add_network(netuid, 1, 0); @@ -369,8 +369,8 @@ fn test_swap_with_max_values() { 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); + mock::setup_reserves(netuid, reserve, reserve.into()); + mock::setup_reserves(netuid2, reserve, reserve.into()); // Stake to hotkey on each subnet. assert_ok!(SubtensorModule::add_stake( @@ -415,8 +415,8 @@ fn test_swap_with_max_values() { ); assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), - expected_stake1, - epsilon = expected_stake1 / 1000 + expected_stake1.to_u64(), + epsilon = expected_stake1.to_u64() / 1000 ); assert_eq!( SubtensorModule::get_total_stake_for_coldkey(&old_coldkey2), @@ -424,8 +424,8 @@ fn test_swap_with_max_values() { ); assert_abs_diff_eq!( SubtensorModule::get_total_stake_for_coldkey(&new_coldkey2), - expected_stake2, - epsilon = expected_stake2 / 1000 + expected_stake2.to_u64(), + epsilon = expected_stake2.to_u64() / 1000 ); }); } @@ -446,7 +446,7 @@ fn test_swap_with_non_existent_new_coldkey() { SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake + 1_000); let reserve = stake * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Stake to hotkey. assert_ok!(SubtensorModule::add_stake( @@ -481,7 +481,7 @@ fn test_swap_with_non_existent_new_coldkey() { assert_abs_diff_eq!( actual_stake, expected_stake, - epsilon = expected_stake / 1000 + epsilon = expected_stake / 1000.into() ); }); } @@ -581,7 +581,7 @@ fn test_swap_concurrent_modifications() { let additional_stake = 500_000_000_000; let reserve = (initial_stake + additional_stake) * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Setup initial state add_network(netuid, 1, 1); @@ -682,7 +682,7 @@ fn test_do_swap_coldkey_success() { let free_balance_old = 12345u64 + swap_cost; let reserve = (stake_amount1 + stake_amount2) * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Setup initial state add_network(netuid, 13, 0); @@ -874,7 +874,7 @@ fn test_swap_stake_for_coldkey() { ); let reserve = (stake_amount1 + stake_amount2 + stake_amount3) * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Stake to hotkeys assert_ok!(SubtensorModule::add_stake( @@ -967,7 +967,7 @@ fn test_swap_stake_for_coldkey() { &old_coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -975,7 +975,7 @@ fn test_swap_stake_for_coldkey() { &old_coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); // Verify TotalHotkeyStake remains unchanged @@ -1028,7 +1028,7 @@ fn test_swap_staking_hotkeys_for_coldkey() { register_ok_neuron(netuid, hotkey2, other_coldkey, 0); let reserve = (stake_amount1 + stake_amount2) * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Stake to hotkeys assert_ok!(SubtensorModule::add_stake( @@ -1087,7 +1087,7 @@ fn test_swap_delegated_stake_for_coldkey() { register_ok_neuron(netuid, hotkey2, other_coldkey, 0); let reserve = (stake_amount1 + stake_amount2) * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Notice hotkey1 and hotkey2 are Owned by other_coldkey // old_coldkey and new_coldkey therefore delegates stake to them @@ -1122,7 +1122,7 @@ fn test_swap_delegated_stake_for_coldkey() { &old_coldkey, netuid, ); - let fee = (expected_stake_alpha2 as f64 * 0.003) as u64; + let fee = (expected_stake_alpha2.to_u64() as f64 * 0.003) as u64; // Record initial values let initial_total_issuance = SubtensorModule::get_total_issuance(); @@ -1167,7 +1167,7 @@ fn test_swap_delegated_stake_for_coldkey() { &old_coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1175,7 +1175,7 @@ fn test_swap_delegated_stake_for_coldkey() { &old_coldkey, netuid ), - 0 + AlphaCurrency::ZERO ); // Verify TotalColdkeyStake @@ -1317,9 +1317,9 @@ fn test_coldkey_swap_total() { 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); + mock::setup_reserves(netuid1, reserve, reserve.into()); + mock::setup_reserves(netuid2, reserve, reserve.into()); + mock::setup_reserves(netuid3, reserve, reserve.into()); // Setup initial state add_network(netuid1, 13, 0); @@ -1664,8 +1664,8 @@ fn test_coldkey_delegations() { let stake = DefaultMinStake::::get() * 10; let reserve = stake * 1000; - mock::setup_reserves(netuid, reserve, reserve); - mock::setup_reserves(netuid2, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); + mock::setup_reserves(netuid2, reserve, reserve.into()); add_network(netuid, 13, 0); // root add_network(netuid2, 13, 0); @@ -1719,14 +1719,18 @@ fn test_coldkey_delegations() { epsilon = approx_total_stake / 100 ); assert_eq!( - Alpha::::get((delegate, new_coldkey, netuid)).to_num::(), - expected_stake + expected_stake, + Alpha::::get((delegate, new_coldkey, netuid)) + .to_num::() + .into(), ); assert_eq!(Alpha::::get((delegate, coldkey, netuid)), 0); assert_eq!( - Alpha::::get((delegate, new_coldkey, netuid2)).to_num::(), expected_stake, + Alpha::::get((delegate, new_coldkey, netuid2)) + .to_num::() + .into() ); assert_eq!(Alpha::::get((delegate, coldkey, netuid2)), 0); }); @@ -1810,7 +1814,7 @@ fn test_schedule_swap_coldkey_execution() { let stake_amount = DefaultMinStake::::get() * 10; let reserve = stake_amount * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); add_network(netuid, 13, 0); register_ok_neuron(netuid, hotkey, old_coldkey, 0); @@ -2021,7 +2025,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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2074,7 +2078,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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2111,7 +2115,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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); assert_ok!(SubtensorModule::burned_register( <::RuntimeOrigin>::signed(old_coldkey), @@ -2185,7 +2189,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { let stake = 100_000_000_000; let reserve = stake * 100; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); let who = coldkey; // The coldkey signs this transaction @@ -2289,7 +2293,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: stake, + alpha_amount: stake.into(), }); let result = extension.validate( RawOrigin::Signed(who).into(), @@ -2312,7 +2316,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: stake, + alpha_amount: stake.into(), limit_price: stake, allow_partial: false, }); @@ -2338,7 +2342,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { destination_hotkey: hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: stake, + alpha_amount: stake.into(), }); let result = extension.validate( RawOrigin::Signed(who).into(), @@ -2362,7 +2366,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { hotkey, origin_netuid: netuid, destination_netuid: netuid, - alpha_amount: stake, + alpha_amount: stake.into(), }); let result = extension.validate( RawOrigin::Signed(who).into(), @@ -2467,7 +2471,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake { hotkey, netuid, - amount_unstaked: DefaultMinStake::::get() * 2, + amount_unstaked: (DefaultMinStake::::get() * 2).into(), }); let result = extension.validate( RawOrigin::Signed(who).into(), @@ -2485,7 +2489,7 @@ fn test_coldkey_in_swap_schedule_prevents_funds_usage() { let call = RuntimeCall::SubtensorModule(SubtensorCall::remove_stake_limit { hotkey, netuid, - amount_unstaked: DefaultMinStake::::get() * 2, + amount_unstaked: (DefaultMinStake::::get() * 2).into(), limit_price: 123456789, // should be low enough allow_partial: true, }); @@ -2520,7 +2524,7 @@ fn test_coldkey_in_swap_schedule_prevents_critical_calls() { let stake = 100_000_000_000; let reserve = stake * 10; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); let who = coldkey; // The coldkey signs this transaction diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index 28a453aed9..506bd77a9d 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -8,6 +8,7 @@ use frame_system::{Config, RawOrigin}; use sp_core::{Get, H160, H256, U256}; use sp_runtime::SaturatedConversion; use substrate_fixed::types::U64F64; +use subtensor_runtime_common::AlphaCurrency; use subtensor_swap_interface::SwapHandler; use super::mock; @@ -72,14 +73,14 @@ fn test_swap_total_hotkey_stake() { //add network let netuid = add_dynamic_network(&old_hotkey, &coldkey); - mock::setup_reserves(netuid, amount * 100, amount * 100); + mock::setup_reserves(netuid, amount * 100, (amount * 100).into()); // 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!(!expected_alpha.is_zero()); assert_ok!(SubtensorModule::add_stake( RuntimeOrigin::signed(coldkey), old_hotkey, @@ -614,8 +615,8 @@ 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); + mock::setup_reserves(netuid1, stake * 100, (stake * 100).into()); + mock::setup_reserves(netuid2, stake * 100, (stake * 100).into()); // Add balance to both coldkeys SubtensorModule::add_balance_to_coldkey_account(&coldkey1, stake + 1_000); @@ -647,8 +648,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey2, netuid2, ); - assert!(ck1_stake > 0); - assert!(ck2_stake > 0); + assert!(!ck1_stake.is_zero()); + assert!(!ck2_stake.is_zero()); let total_hk_stake = SubtensorModule::get_total_stake_for_hotkey(&old_hotkey); assert!(total_hk_stake > 0); @@ -689,7 +690,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey1, netuid1 ), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -697,7 +698,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey2, netuid2 ), - 0 + AlphaCurrency::ZERO ); // Check subnet membership transfer @@ -884,11 +885,15 @@ fn test_swap_stake_success() { let mut weight = Weight::zero(); // Initialize staking variables for old_hotkey - TotalHotkeyAlpha::::insert(old_hotkey, netuid, amount); - TotalHotkeyAlphaLastEpoch::::insert(old_hotkey, netuid, amount * 2); - TotalHotkeyShares::::insert(old_hotkey, netuid, U64F64::from_num(shares)); + TotalHotkeyAlpha::::insert(old_hotkey, netuid, AlphaCurrency::from(amount)); + TotalHotkeyAlphaLastEpoch::::insert( + old_hotkey, + netuid, + AlphaCurrency::from(amount * 2), + ); + TotalHotkeyShares::::insert(old_hotkey, netuid, shares); Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(amount)); - AlphaDividendsPerSubnet::::insert(netuid, old_hotkey, amount); + AlphaDividendsPerSubnet::::insert(netuid, old_hotkey, AlphaCurrency::from(amount)); TaoDividendsPerSubnet::::insert(netuid, old_hotkey, amount); // Perform the swap @@ -900,15 +905,21 @@ fn test_swap_stake_success() { ); // Verify the swap - assert_eq!(TotalHotkeyAlpha::::get(old_hotkey, netuid), 0); - assert_eq!(TotalHotkeyAlpha::::get(new_hotkey, netuid), amount); + assert_eq!( + TotalHotkeyAlpha::::get(old_hotkey, netuid), + AlphaCurrency::ZERO + ); + assert_eq!( + TotalHotkeyAlpha::::get(new_hotkey, netuid), + amount.into() + ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(old_hotkey, netuid), - 0 + AlphaCurrency::ZERO ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid), - amount * 2 + AlphaCurrency::from(amount * 2) ); assert_eq!( TotalHotkeyShares::::get(old_hotkey, netuid), @@ -926,10 +937,13 @@ fn test_swap_stake_success() { Alpha::::get((new_hotkey, coldkey, netuid)), U64F64::from_num(amount) ); - assert_eq!(AlphaDividendsPerSubnet::::get(netuid, old_hotkey), 0); + assert_eq!( + AlphaDividendsPerSubnet::::get(netuid, old_hotkey), + AlphaCurrency::ZERO + ); assert_eq!( AlphaDividendsPerSubnet::::get(netuid, new_hotkey), - amount + amount.into() ); assert_eq!(TaoDividendsPerSubnet::::get(netuid, old_hotkey), 0); assert_eq!( diff --git a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs index 82e1b9a58a..de012d4074 100644 --- a/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs +++ b/pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs @@ -5,6 +5,7 @@ use codec::Encode; use frame_support::weights::Weight; use frame_support::{assert_err, assert_noop, assert_ok}; use frame_system::{Config, RawOrigin}; +use subtensor_runtime_common::{AlphaCurrency, Currency}; use super::mock::*; use crate::*; @@ -672,8 +673,8 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey2, netuid2, ); - assert!(ck1_stake > 0); - assert!(ck2_stake > 0); + assert!(!ck1_stake.is_zero()); + assert!(!ck2_stake.is_zero()); let total_hk_stake = SubtensorModule::get_total_stake_for_hotkey(&old_hotkey); assert!(total_hk_stake > 0); System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get()); @@ -728,7 +729,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey1, netuid1 ), - 0 + AlphaCurrency::ZERO ); assert_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -736,7 +737,7 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { &coldkey2, netuid2 ), - 0 + AlphaCurrency::ZERO ); // Check subnet membership transfer @@ -937,11 +938,15 @@ fn test_swap_stake_success() { let shares = U64F64::from_num(123456); // Initialize staking variables for old_hotkey - TotalHotkeyAlpha::::insert(old_hotkey, netuid, amount); - TotalHotkeyAlphaLastEpoch::::insert(old_hotkey, netuid, amount * 2); + TotalHotkeyAlpha::::insert(old_hotkey, netuid, AlphaCurrency::from(amount)); + TotalHotkeyAlphaLastEpoch::::insert( + old_hotkey, + netuid, + AlphaCurrency::from(amount * 2), + ); TotalHotkeyShares::::insert(old_hotkey, netuid, U64F64::from_num(shares)); Alpha::::insert((old_hotkey, coldkey, netuid), U64F64::from_num(amount)); - AlphaDividendsPerSubnet::::insert(netuid, old_hotkey, amount); + AlphaDividendsPerSubnet::::insert(netuid, old_hotkey, AlphaCurrency::from(amount)); TaoDividendsPerSubnet::::insert(netuid, old_hotkey, amount); // Perform the swap @@ -954,15 +959,21 @@ fn test_swap_stake_success() { ),); // Verify the swap - assert_eq!(TotalHotkeyAlpha::::get(old_hotkey, netuid), 0); - assert_eq!(TotalHotkeyAlpha::::get(new_hotkey, netuid), amount); + assert_eq!( + TotalHotkeyAlpha::::get(old_hotkey, netuid), + AlphaCurrency::ZERO + ); + assert_eq!( + TotalHotkeyAlpha::::get(new_hotkey, netuid), + AlphaCurrency::from(amount) + ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(old_hotkey, netuid), - 0 + AlphaCurrency::ZERO ); assert_eq!( TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid), - amount * 2 + AlphaCurrency::from(amount * 2) ); assert_eq!( TotalHotkeyShares::::get(old_hotkey, netuid), @@ -980,10 +991,13 @@ fn test_swap_stake_success() { Alpha::::get((new_hotkey, coldkey, netuid)), U64F64::from_num(amount) ); - assert_eq!(AlphaDividendsPerSubnet::::get(netuid, old_hotkey), 0); + assert_eq!( + AlphaDividendsPerSubnet::::get(netuid, old_hotkey), + AlphaCurrency::ZERO + ); assert_eq!( AlphaDividendsPerSubnet::::get(netuid, new_hotkey), - amount + AlphaCurrency::from(amount) ); assert_eq!(TaoDividendsPerSubnet::::get(netuid, old_hotkey), 0); assert_eq!( diff --git a/pallets/subtensor/src/tests/uids.rs b/pallets/subtensor/src/tests/uids.rs index 1d4c41b982..bca6945b44 100644 --- a/pallets/subtensor/src/tests/uids.rs +++ b/pallets/subtensor/src/tests/uids.rs @@ -5,6 +5,7 @@ use crate::*; use frame_support::{assert_err, assert_ok}; use frame_system::Config; use sp_core::{H160, U256}; +use subtensor_runtime_common::AlphaCurrency; /******************************************** tests for uids.rs file @@ -57,7 +58,7 @@ fn test_replace_neuron() { SubtensorModule::set_element_at(v, neuron_uid as usize, 5u16) }); Emission::::mutate(netuid, |v| { - SubtensorModule::set_element_at(v, neuron_uid as usize, 5u64) + SubtensorModule::set_element_at(v, neuron_uid as usize, 5.into()) }); Consensus::::mutate(netuid, |v| { SubtensorModule::set_element_at(v, neuron_uid as usize, 5u16) @@ -120,7 +121,10 @@ fn test_replace_neuron() { // Check trust, emission, consensus, incentive, dividends have been reset to 0. assert_eq!(SubtensorModule::get_trust_for_uid(netuid, neuron_uid), 0); - assert_eq!(SubtensorModule::get_emission_for_uid(netuid, neuron_uid), 0); + assert_eq!( + SubtensorModule::get_emission_for_uid(netuid, neuron_uid), + AlphaCurrency::ZERO + ); assert_eq!( SubtensorModule::get_consensus_for_uid(netuid, neuron_uid), 0 diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index f978b17596..cec33a940c 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -232,7 +232,7 @@ fn test_commit_weights_validate() { let min_stake = 500_000_000_000; let reserve = min_stake * 1000; - mock::setup_reserves(netuid, reserve, reserve); + mock::setup_reserves(netuid, reserve, reserve.into()); // Stake some TAO and read what get_total_stake_for_hotkey it gets // It will be a different value due to the slippage @@ -355,7 +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); + mock::setup_reserves(netuid, 1_000_000_000_000, 1_000_000_000_000.into()); // Register the hotkey SubtensorModule::append_neuron(netuid, &hotkey, 0); crate::Owner::::insert(hotkey, coldkey); @@ -764,7 +764,7 @@ fn test_weights_err_setting_weights_too_fast() { &hotkey_account_id, &(U256::from(66)), netuid, - 1, + 1.into(), ); SubtensorModule::set_weights_set_rate_limit(netuid, 10); assert_eq!(SubtensorModule::get_weights_set_rate_limit(netuid), 10); @@ -857,7 +857,7 @@ fn test_weights_err_has_duplicate_ids() { &hotkey_account_id, &(U256::from(77)), netuid, - 1, + 1.into(), ); // uid 1 @@ -1048,7 +1048,7 @@ fn test_set_weights_err_invalid_uid() { &hotkey_account_id, &(U256::from(66)), netuid, - 1, + 1.into(), ); let weight_keys: Vec = vec![9999]; // Does not exist let weight_values: Vec = vec![88]; // random value @@ -1085,7 +1085,7 @@ fn test_set_weight_not_enough_values() { &account_id, &(U256::from(2)), netuid, - 1, + 1.into(), ); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300000); @@ -1196,7 +1196,7 @@ fn test_set_weights_sum_larger_than_u16_max() { &(U256::from(1)), &(U256::from(2)), netuid, - 1, + 1.into(), ); register_ok_neuron(1.into(), U256::from(3), U256::from(4), 300_000); @@ -1696,13 +1696,13 @@ fn test_commit_reveal_weights_ok() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Commit at block 0 @@ -1764,13 +1764,13 @@ fn test_commit_reveal_tempo_interval() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Commit at block 0 @@ -1899,13 +1899,13 @@ fn test_commit_reveal_hash() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -1999,13 +1999,13 @@ fn test_commit_reveal_disabled_or_enabled() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Disable commit/reveal @@ -2076,13 +2076,13 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Enable commit/reveal @@ -2162,13 +2162,13 @@ fn test_tempo_change_during_commit_reveal_process() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); assert_ok!(SubtensorModule::commit_weights( @@ -2311,13 +2311,13 @@ fn test_commit_reveal_multiple_commits() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // 1. Commit 10 times successfully @@ -2714,13 +2714,13 @@ fn test_expired_commits_handling_in_commit_and_reveal() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // 1. Commit 5 times in epoch 0 @@ -2912,13 +2912,13 @@ fn test_reveal_at_exact_epoch() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); let reveal_periods: Vec = vec![0, 1, 2, 7, 40, 86, 100]; @@ -3076,13 +3076,13 @@ fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Step 1: Commit weights @@ -3266,13 +3266,13 @@ fn test_commit_reveal_order_enforcement() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // Commit three times: A, B, C @@ -3538,13 +3538,13 @@ fn test_successful_batch_reveal() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // 1. Commit multiple times @@ -3616,13 +3616,13 @@ fn test_batch_reveal_with_expired_commits() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); let mut commit_info = Vec::new(); @@ -4033,13 +4033,13 @@ fn test_batch_reveal_with_out_of_order_commits() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // 1. Commit multiple times (A, B, C) @@ -4438,13 +4438,13 @@ fn test_get_reveal_blocks() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); // **6. Commit Weights at Block 0** @@ -4572,13 +4572,13 @@ fn test_commit_weights_rate_limit() { &(U256::from(0)), &(U256::from(0)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &(U256::from(1)), &(U256::from(1)), netuid, - 1, + 1.into(), ); let neuron_uid = @@ -4762,13 +4762,13 @@ fn test_reveal_crv3_commits_success() { &hotkey1, &(U256::from(3)), netuid, - 1, + 1.into(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey2, &(U256::from(4)), netuid, - 1, + 1.into(), ); let version_key = SubtensorModule::get_weights_version_key(netuid); @@ -5039,11 +5039,11 @@ fn test_do_commit_crv3_weights_success() { let cur_epoch = SubtensorModule::get_epoch_index(netuid, SubtensorModule::get_current_block_as_u64()); - let commits = CRV3WeightCommits::::get(netuid, cur_epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, cur_epoch); assert_eq!(commits.len(), 1); assert_eq!(commits[0].0, hotkey); - assert_eq!(commits[0].1, commit_data); - assert_eq!(commits[0].2, reveal_round); + assert_eq!(commits[0].2, commit_data); + assert_eq!(commits[0].3, reveal_round); }); } @@ -5879,7 +5879,7 @@ fn test_multiple_commits_by_same_hotkey_within_limit() { let cur_epoch = SubtensorModule::get_epoch_index(netuid, SubtensorModule::get_current_block_as_u64()); - let commits = CRV3WeightCommits::::get(netuid, cur_epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, cur_epoch); assert_eq!( commits.len(), 10, @@ -5914,18 +5914,18 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() { .clone() .try_into() .expect("Failed to convert commit data into bounded vector"); - assert_ok!(CRV3WeightCommits::::try_mutate( + assert_ok!(CRV3WeightCommitsV2::::try_mutate( netuid, *epoch, |commits| -> DispatchResult { - commits.push_back((hotkey, bounded_commit_data, reveal_round)); + commits.push_back((hotkey, current_block, bounded_commit_data, reveal_round)); Ok(()) } )); } for epoch in &past_epochs { - let commits = CRV3WeightCommits::::get(netuid, *epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, *epoch); assert!( !commits.is_empty(), "Expected commits to be present for past epoch {}", @@ -5936,7 +5936,7 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() { assert_ok!(SubtensorModule::reveal_crv3_commits(netuid)); for epoch in &past_epochs { - let commits = CRV3WeightCommits::::get(netuid, *epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, *epoch); assert!( commits.is_empty(), "Expected commits for past epoch {} to be removed", @@ -5944,7 +5944,7 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() { ); } - let current_epoch_commits = CRV3WeightCommits::::get(netuid, current_epoch); + let current_epoch_commits = CRV3WeightCommitsV2::::get(netuid, current_epoch); assert!( current_epoch_commits.is_empty(), "Expected no commits for current epoch {}", @@ -6134,7 +6134,7 @@ fn test_reveal_crv3_commits_multiple_valid_commits_all_processed() { netuid, SubtensorModule::get_current_block_as_u64(), ); - let commits = CRV3WeightCommits::::get(netuid, cur_epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, cur_epoch); assert!( commits.is_empty(), "Expected no commits left in storage after reveal" @@ -6321,10 +6321,119 @@ fn test_reveal_crv3_commits_max_neurons() { netuid, SubtensorModule::get_current_block_as_u64(), ); - let commits = CRV3WeightCommits::::get(netuid, cur_epoch); + let commits = CRV3WeightCommitsV2::::get(netuid, cur_epoch); assert!( commits.is_empty(), "Expected no commits left in storage after reveal" ); }); } + +#[test] +fn test_get_first_block_of_epoch_epoch_zero() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = NetUid::from(1); + let tempo: u16 = 10; + add_network(netuid, tempo, 0); + + let first_block = SubtensorModule::get_first_block_of_epoch(netuid, 0); + assert_eq!(first_block, 0); + + // Cross-check: epoch at block 0 should be 0 + assert_eq!(SubtensorModule::get_epoch_index(netuid, 0), 0); + }); +} + +#[test] +fn test_get_first_block_of_epoch_small_epoch() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = NetUid::from(0); + let tempo: u16 = 1; + add_network(netuid, tempo, 0); + + let first_block = SubtensorModule::get_first_block_of_epoch(netuid, 1); + assert_eq!(first_block, 1); // 1 * 2 - 1 = 1 + + // Cross-check + assert_eq!(SubtensorModule::get_epoch_index(netuid, 1), 1); + assert_eq!(SubtensorModule::get_epoch_index(netuid, 0), 0); + }); +} + +#[test] +fn test_get_first_block_of_epoch_with_offset() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = NetUid::from(1); + let tempo: u16 = 10; + add_network(netuid, tempo, 0); + + let first_block = SubtensorModule::get_first_block_of_epoch(netuid, 1); + assert_eq!(first_block, 9); // 1 * 11 - 2 = 9 + + // Cross-check + assert_eq!(SubtensorModule::get_epoch_index(netuid, 9), 1); + assert_eq!(SubtensorModule::get_epoch_index(netuid, 8), 0); + }); +} + +#[test] +fn test_get_first_block_of_epoch_large_epoch() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = NetUid::from(0); + let tempo: u16 = 100; + add_network(netuid, tempo, 0); + + let epoch: u64 = 1000; + let first_block = SubtensorModule::get_first_block_of_epoch(netuid, epoch); + assert_eq!(first_block, epoch * 101 - 1); // No overflow for this size + + // Cross-check (simulate, as large block not runnable, but math holds) + assert_eq!(first_block + 1, epoch * 101); + }); +} + +#[test] +fn test_get_first_block_of_epoch_step_blocks_and_assert_with_until_next() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = NetUid::from(1); + let tempo: u16 = 10; + add_network(netuid, tempo, 0); + + let mut current_block: u64 = 0; + for expected_epoch in 0..10u64 { + let expected_first = SubtensorModule::get_first_block_of_epoch(netuid, expected_epoch); + + // Step blocks until we reach the start of this epoch + while current_block < expected_first { + run_to_block(current_block + 1); + current_block += 1; + } + + // Assert we are at the first block of the epoch + assert_eq!(current_block, expected_first); + assert_eq!( + SubtensorModule::get_epoch_index(netuid, current_block), + expected_epoch + ); + + // From here, blocks_until_next_epoch should point to the start of next epoch + let until_next = SubtensorModule::blocks_until_next_epoch(netuid, tempo, current_block); + let next_first = SubtensorModule::get_first_block_of_epoch(netuid, expected_epoch + 1); + assert_eq!(current_block + until_next + 1, next_first); // +1 since until is blocks to end, +1 to start next + + // Advance to near end of this epoch + let last_block = next_first.saturating_sub(1); + run_to_block(last_block); + current_block = System::block_number(); + assert_eq!( + SubtensorModule::get_epoch_index(netuid, current_block), + expected_epoch + ); + + // Until next from near end + let until_next_end = + SubtensorModule::blocks_until_next_epoch(netuid, tempo, current_block); + assert_eq!(current_block + until_next_end + 1, next_first); + } + }); +} diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index b351e7e067..2481d56a6c 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -8,7 +8,7 @@ use sp_core::Get; use sp_core::U256; use sp_runtime::Saturating; use substrate_fixed::types::{I32F32, U96F32}; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; impl Pallet { pub fn ensure_subnet_owner_or_root( @@ -92,7 +92,7 @@ impl Pallet { pub fn get_active(netuid: NetUid) -> Vec { Active::::get(netuid) } - pub fn get_emission(netuid: NetUid) -> Vec { + pub fn get_emission(netuid: NetUid) -> Vec { Emission::::get(netuid) } pub fn get_consensus(netuid: NetUid) -> Vec { @@ -171,9 +171,9 @@ impl Pallet { let vec = Trust::::get(netuid); vec.get(uid as usize).copied().unwrap_or(0) } - pub fn get_emission_for_uid(netuid: NetUid, uid: u16) -> u64 { + pub fn get_emission_for_uid(netuid: NetUid, uid: u16) -> AlphaCurrency { let vec = Emission::::get(netuid); - vec.get(uid as usize).copied().unwrap_or(0) + vec.get(uid as usize).copied().unwrap_or_default() } pub fn get_active_for_uid(netuid: NetUid, uid: u16) -> bool { let vec = Active::::get(netuid); @@ -217,7 +217,7 @@ impl Pallet { pub fn get_tempo(netuid: NetUid) -> u16 { Tempo::::get(netuid) } - pub fn get_pending_emission(netuid: NetUid) -> u64 { + pub fn get_pending_emission(netuid: NetUid) -> AlphaCurrency { PendingEmission::::get(netuid) } pub fn get_last_adjustment_block(netuid: NetUid) -> u64 { @@ -695,8 +695,10 @@ impl Pallet { } pub fn set_alpha_values_32(netuid: NetUid, low: I32F32, high: I32F32) { - let low = (low.saturating_mul(I32F32::saturating_from_num(u16::MAX))).to_num::(); - let high = (high.saturating_mul(I32F32::saturating_from_num(u16::MAX))).to_num::(); + let low = + (low.saturating_mul(I32F32::saturating_from_num(u16::MAX))).saturating_to_num::(); + let high = + (high.saturating_mul(I32F32::saturating_from_num(u16::MAX))).saturating_to_num::(); AlphaValues::::insert(netuid, (low, high)); } diff --git a/pallets/swap-interface/src/lib.rs b/pallets/swap-interface/src/lib.rs index 83b75105e6..fce3d53f18 100644 --- a/pallets/swap-interface/src/lib.rs +++ b/pallets/swap-interface/src/lib.rs @@ -2,7 +2,7 @@ use frame_support::pallet_prelude::*; use substrate_fixed::types::U96F32; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OrderType { @@ -28,7 +28,7 @@ pub trait SwapHandler { fn current_alpha_price(netuid: NetUid) -> U96F32; fn max_price() -> u64; fn min_price() -> u64; - fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64); + fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: AlphaCurrency); fn is_user_liquidity_enabled(netuid: NetUid) -> bool; } diff --git a/pallets/swap/src/mock.rs b/pallets/swap/src/mock.rs index 36e8797031..014c6ce4fe 100644 --- a/pallets/swap/src/mock.rs +++ b/pallets/swap/src/mock.rs @@ -14,7 +14,7 @@ use sp_runtime::{ BuildStorage, traits::{BlakeTwo256, IdentityLookup}, }; -use subtensor_runtime_common::{BalanceOps, NetUid, SubnetInfo}; +use subtensor_runtime_common::{AlphaCurrency, BalanceOps, NetUid, SubnetInfo}; use crate::pallet::EnabledUserLiquidity; @@ -95,11 +95,11 @@ impl SubnetInfo for MockLiquidityProvider { } } - fn alpha_reserve(netuid: NetUid) -> u64 { + fn alpha_reserve(netuid: NetUid) -> AlphaCurrency { match netuid.into() { - 123u16 => 10_000, - WRAPPING_FEES_NETUID => 400_000_000_000, - _ => 4_000_000_000_000, + 123u16 => 10_000.into(), + WRAPPING_FEES_NETUID => 400_000_000_000.into(), + _ => 4_000_000_000_000.into(), } } @@ -132,7 +132,7 @@ impl BalanceOps for MockBalanceOps { _: NetUid, coldkey_account_id: &AccountId, hotkey_account_id: &AccountId, - ) -> u64 { + ) -> AlphaCurrency { 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, @@ -141,6 +141,7 @@ impl BalanceOps for MockBalanceOps { } _ => 1_000_000_000, } + .into() } fn increase_balance(_coldkey: &AccountId, _tao: u64) {} @@ -153,7 +154,7 @@ impl BalanceOps for MockBalanceOps { _coldkey: &AccountId, _hotkey: &AccountId, _netuid: NetUid, - _alpha: u64, + _alpha: AlphaCurrency, ) -> Result<(), DispatchError> { Ok(()) } @@ -162,15 +163,15 @@ impl BalanceOps for MockBalanceOps { _coldkey: &AccountId, _hotkey: &AccountId, _netuid: NetUid, - alpha: u64, - ) -> Result { + alpha: AlphaCurrency, + ) -> 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) {} + fn increase_provided_alpha_reserve(_netuid: NetUid, _alpha: AlphaCurrency) {} + fn decrease_provided_alpha_reserve(_netuid: NetUid, _alpha: AlphaCurrency) {} } impl crate::pallet::Config for Test { diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index e114fe1ec5..2e0a28c978 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -7,7 +7,7 @@ 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_runtime_common::{AlphaCurrency, BalanceOps, Currency, NetUid, SubnetInfo}; use subtensor_swap_interface::{SwapHandler, SwapResult}; use super::pallet::*; @@ -22,9 +22,9 @@ const MAX_SWAP_ITERATIONS: u16 = 1000; #[derive(Debug, PartialEq)] pub struct UpdateLiquidityResult { pub tao: u64, - pub alpha: u64, + pub alpha: AlphaCurrency, pub fee_tao: u64, - pub fee_alpha: u64, + pub fee_alpha: AlphaCurrency, pub removed: bool, pub tick_low: TickIndex, pub tick_high: TickIndex, @@ -33,9 +33,9 @@ pub struct UpdateLiquidityResult { #[derive(Debug, PartialEq)] pub struct RemoveLiquidityResult { pub tao: u64, - pub alpha: u64, + pub alpha: AlphaCurrency, pub fee_tao: u64, - pub fee_alpha: u64, + pub fee_alpha: AlphaCurrency, pub tick_low: TickIndex, pub tick_high: TickIndex, pub liquidity: u64, @@ -292,7 +292,7 @@ impl Pallet { } else { let tao_reserve = T::SubnetInfo::tao_reserve(netuid.into()); let alpha_reserve = T::SubnetInfo::alpha_reserve(netuid.into()); - if alpha_reserve > 0 { + if !alpha_reserve.is_zero() { U96F32::saturating_from_num(tao_reserve) .saturating_div(U96F32::saturating_from_num(alpha_reserve)) } else { @@ -335,9 +335,9 @@ impl Pallet { // 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 liquidity = helpers_128bit::sqrt( + (tao_reserve as u128).saturating_mul(u64::from(alpha_reserve) as u128), + ) as u64; let protocol_account_id = Self::protocol_account_id(); let (position, _, _) = Self::add_liquidity_not_insert( @@ -354,7 +354,11 @@ impl Pallet { } /// Adjusts protocol liquidity with new values of TAO and Alpha reserve - pub(super) fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64) { + pub(super) fn adjust_protocol_liquidity( + netuid: NetUid, + tao_delta: u64, + alpha_delta: AlphaCurrency, + ) { // Update protocol position with new liquidity let protocol_account_id = Self::protocol_account_id(); let mut positions = @@ -367,7 +371,7 @@ impl Pallet { if let Ok((tao, alpha)) = maybe_token_amounts { // Get updated reserves, calculate liquidity let new_tao_reserve = tao.saturating_add(tao_delta); - let new_alpha_reserve = alpha.saturating_add(alpha_delta); + let new_alpha_reserve = alpha.saturating_add(alpha_delta.to_u64()); let new_liquidity = helpers_128bit::sqrt( (new_tao_reserve as u128).saturating_mul(new_alpha_reserve as u128), ) as u64; @@ -440,7 +444,7 @@ impl Pallet { // Check if reserves are overused if let Ok(ref swap_result) = result { let checked_reserve = match order_type { - OrderType::Buy => alpha_reserve, + OrderType::Buy => u64::from(alpha_reserve), OrderType::Sell => tao_reserve, }; @@ -463,7 +467,8 @@ impl Pallet { ) -> Result> { ensure!( T::SubnetInfo::tao_reserve(netuid.into()) >= T::MinimumReserve::get().get() - && T::SubnetInfo::alpha_reserve(netuid.into()) >= T::MinimumReserve::get().get(), + && u64::from(T::SubnetInfo::alpha_reserve(netuid.into())) + >= T::MinimumReserve::get().get(), Error::::ReservesTooLow ); @@ -837,7 +842,7 @@ impl Pallet { netuid.into(), coldkey_account_id, hotkey_account_id - ) >= alpha, + ) >= AlphaCurrency::from(alpha), Error::::InsufficientBalance ); @@ -929,9 +934,9 @@ impl Pallet { Ok(RemoveLiquidityResult { tao, - alpha, + alpha: alpha.into(), fee_tao, - fee_alpha, + fee_alpha: fee_alpha.into(), tick_low: position.tick_low, tick_high: position.tick_high, liquidity: position.liquidity, @@ -1002,7 +1007,7 @@ impl Pallet { ensure!( T::BalanceOps::tao_balance(coldkey_account_id) >= tao && T::BalanceOps::alpha_balance(netuid, coldkey_account_id, hotkey_account_id) - >= alpha, + >= AlphaCurrency::from(alpha.saturating_to_num::()), Error::::InsufficientBalance ); } else { @@ -1052,9 +1057,9 @@ impl Pallet { Ok(UpdateLiquidityResult { tao: tao.saturating_to_num::(), - alpha: alpha.saturating_to_num::(), + alpha: alpha.saturating_to_num::().into(), fee_tao, - fee_alpha, + fee_alpha: fee_alpha.into(), removed: remove, tick_low: position.tick_low, tick_high: position.tick_high, @@ -1264,7 +1269,7 @@ impl SwapHandler for Pallet { .saturating_to_num() } - fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: u64) { + fn adjust_protocol_liquidity(netuid: NetUid, tao_delta: u64, alpha_delta: AlphaCurrency) { Self::adjust_protocol_liquidity(netuid, tao_delta, alpha_delta); } diff --git a/pallets/swap/src/pallet/mod.rs b/pallets/swap/src/pallet/mod.rs index e5fdec045f..1630a44c07 100644 --- a/pallets/swap/src/pallet/mod.rs +++ b/pallets/swap/src/pallet/mod.rs @@ -4,7 +4,7 @@ use core::ops::Neg; use frame_support::{PalletId, pallet_prelude::*, traits::Get}; use frame_system::pallet_prelude::*; use substrate_fixed::types::U64F64; -use subtensor_runtime_common::{BalanceOps, NetUid, SubnetInfo}; +use subtensor_runtime_common::{AlphaCurrency, BalanceOps, Currency, NetUid, SubnetInfo}; use crate::{ position::{Position, PositionId}, @@ -68,7 +68,7 @@ mod pallet { /// Default fee rate if not set #[pallet::type_value] pub fn DefaultFeeRate() -> u16 { - 196 // 0.3 % + 33 // ~0.05 % } /// The fee rate applied to swaps per subnet, normalized value between 0 and u16::MAX @@ -165,7 +165,7 @@ mod pallet { /// The amount of TAO tokens committed to the position tao: u64, /// The amount of Alpha tokens committed to the position - alpha: u64, + alpha: AlphaCurrency, /// the lower tick tick_low: TickIndex, /// the upper tick @@ -187,11 +187,11 @@ mod pallet { /// The amount of TAO tokens returned to the user tao: u64, /// The amount of Alpha tokens returned to the user - alpha: u64, + alpha: AlphaCurrency, /// The amount of TAO fees earned from the position fee_tao: u64, /// The amount of Alpha fees earned from the position - fee_alpha: u64, + fee_alpha: AlphaCurrency, /// the lower tick tick_low: TickIndex, /// the upper tick @@ -218,7 +218,7 @@ mod pallet { /// The amount of TAO fees earned from the position fee_tao: u64, /// The amount of Alpha fees earned from the position - fee_alpha: u64, + fee_alpha: AlphaCurrency, /// the lower tick tick_low: TickIndex, /// the upper tick @@ -372,6 +372,7 @@ mod pallet { tick_high, liquidity, )?; + let alpha = AlphaCurrency::from(alpha); // Remove TAO and Alpha balances or fail transaction if they can't be removed exactly let tao_provided = T::BalanceOps::decrease_balance(&coldkey, tao)?; @@ -509,7 +510,7 @@ mod pallet { position_id, liquidity: liquidity_delta, tao: result.tao as i64, - alpha: result.alpha as i64, + alpha: result.alpha.to_u64() as i64, fee_tao: result.fee_tao, fee_alpha: result.fee_alpha, tick_low: result.tick_low, @@ -543,7 +544,7 @@ mod pallet { position_id, liquidity: liquidity_delta, tao: (result.tao as i64).neg(), - alpha: (result.alpha as i64).neg(), + alpha: (result.alpha.to_u64() as i64).neg(), fee_tao: result.fee_tao, fee_alpha: result.fee_alpha, tick_low: result.tick_low, @@ -556,7 +557,7 @@ mod pallet { if result.fee_tao > 0 { T::BalanceOps::increase_balance(&coldkey, result.fee_tao); } - if result.fee_alpha > 0 { + if !result.fee_alpha.is_zero() { T::BalanceOps::increase_stake( &coldkey, &hotkey.clone(), diff --git a/pallets/swap/src/pallet/tests.rs b/pallets/swap/src/pallet/tests.rs index 8a65b2fa7e..12bd19813a 100644 --- a/pallets/swap/src/pallet/tests.rs +++ b/pallets/swap/src/pallet/tests.rs @@ -176,7 +176,7 @@ fn test_swap_initialization() { // Calculate expected liquidity let expected_liquidity = - helpers_128bit::sqrt((tao as u128).saturating_mul(alpha as u128)) as u64; + helpers_128bit::sqrt((tao as u128).saturating_mul(u64::from(alpha) as u128)) as u64; // Get the protocol account let protocol_account_id = Pallet::::protocol_account_id(); @@ -516,9 +516,13 @@ fn test_remove_liquidity_basic() { 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_abs_diff_eq!( + u64::from(remove_result.alpha), + alpha, + epsilon = alpha / 1000 + ); assert_eq!(remove_result.fee_tao, 0); - assert_eq!(remove_result.fee_alpha, 0); + assert_eq!(remove_result.fee_alpha, 0.into()); // Liquidity position is removed assert_eq!( @@ -645,9 +649,13 @@ fn test_modify_position_basic() { -((liquidity / 10) as i64), ) .unwrap(); - assert_abs_diff_eq!(modify_result.alpha, alpha / 10, epsilon = alpha / 1000); + assert_abs_diff_eq!( + u64::from(modify_result.alpha), + alpha / 10, + epsilon = alpha / 1000 + ); assert!(modify_result.fee_tao > 0); - assert_eq!(modify_result.fee_alpha, 0); + assert_eq!(modify_result.fee_alpha, 0.into()); // Liquidity position is reduced assert_eq!( @@ -696,9 +704,13 @@ fn test_modify_position_basic() { ) .unwrap(); - assert_abs_diff_eq!(modify_result.alpha, alpha / 100, epsilon = alpha / 1000); + assert_abs_diff_eq!( + u64::from(modify_result.alpha), + alpha / 100, + epsilon = alpha / 1000 + ); assert_eq!(modify_result.fee_tao, 0); - assert_eq!(modify_result.fee_alpha, 0); + assert_eq!(modify_result.fee_alpha, 0.into()); }); }); } @@ -810,7 +822,8 @@ fn test_swap_basic() { position.liquidity, helpers_128bit::sqrt( MockLiquidityProvider::tao_reserve(netuid.into()) as u128 - * MockLiquidityProvider::alpha_reserve(netuid.into()) as u128 + * u64::from(MockLiquidityProvider::alpha_reserve(netuid.into())) + as u128 ) as u64 ); assert_eq!(position.tick_low, tick_low); @@ -919,7 +932,8 @@ fn test_swap_single_position() { // 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 alpha_reserve = + u64::from(MockLiquidityProvider::alpha_reserve(netuid.into())); let protocol_liquidity = (tao_reserve as f64 * alpha_reserve as f64).sqrt(); // Add liquidity @@ -1223,7 +1237,7 @@ fn test_swap_multiple_positions() { ); let tao_reserve = MockLiquidityProvider::tao_reserve(netuid.into()); - let alpha_reserve = MockLiquidityProvider::alpha_reserve(netuid.into()); + let alpha_reserve = u64::from(MockLiquidityProvider::alpha_reserve(netuid.into())); let output_amount = output_amount as u64; assert!(output_amount > 0); diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml index 16c73ac76d..c5da4eef95 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -34,6 +34,7 @@ pallet-subtensor = { workspace = true } pallet-subtensor-swap = { workspace = true } pallet-admin-utils = { workspace = true } subtensor-swap-interface = { workspace = true } +pallet-crowdloan = { workspace = true } [lints] workspace = true @@ -53,6 +54,7 @@ std = [ "pallet-evm-precompile-sha3fips/std", "pallet-evm-precompile-simple/std", "pallet-evm/std", + "pallet-crowdloan/std", "pallet-proxy/std", "pallet-subtensor/std", "pallet-subtensor-swap/std", diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs index 3a4a36fb79..9be98b3b8a 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -1,11 +1,12 @@ use core::marker::PhantomData; use fp_evm::{ExitError, PrecompileFailure}; -use pallet_evm::PrecompileHandle; +use pallet_evm::{BalanceConverter, PrecompileHandle, SubstrateBalance}; use precompile_utils::EvmResult; use sp_core::U256; +use sp_std::vec::Vec; use substrate_fixed::types::U96F32; -use subtensor_runtime_common::NetUid; +use subtensor_runtime_common::{Currency, NetUid}; use subtensor_swap_interface::{OrderType, SwapHandler}; use crate::PrecompileExt; @@ -14,7 +15,10 @@ pub struct AlphaPrecompile(PhantomData); impl PrecompileExt for AlphaPrecompile where - R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config, + R: frame_system::Config + + pallet_subtensor::Config + + pallet_subtensor_swap::Config + + pallet_evm::Config, R::AccountId: From<[u8; 32]>, { const INDEX: u64 = 2056; @@ -23,7 +27,10 @@ where #[precompile_utils::precompile] impl AlphaPrecompile where - R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config, + R: frame_system::Config + + pallet_subtensor::Config + + pallet_subtensor_swap::Config + + pallet_evm::Config, { #[precompile::public("getAlphaPrice(uint16)")] #[precompile::view] @@ -32,14 +39,24 @@ where as SwapHandler>::current_alpha_price( netuid.into(), ); - Ok(U256::from(price.saturating_to_num::())) + let price: SubstrateBalance = price.saturating_to_num::().into(); + let price_eth = ::BalanceConverter::into_evm_balance(price) + .map(|amount| amount.into_u256()) + .ok_or(ExitError::InvalidRange)?; + + Ok(price_eth) } #[precompile::public("getMovingAlphaPrice(uint16)")] #[precompile::view] fn get_moving_alpha_price(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { let price: U96F32 = pallet_subtensor::Pallet::::get_moving_alpha_price(netuid.into()); - Ok(U256::from(price.saturating_to_num::())) + let price: SubstrateBalance = price.saturating_to_num::().into(); + let price_eth = ::BalanceConverter::into_evm_balance(price) + .map(|amount| amount.into_u256()) + .ok_or(ExitError::InvalidRange)?; + + Ok(price_eth) } #[precompile::public("getTaoInPool(uint16)")] @@ -51,32 +68,26 @@ where #[precompile::public("getAlphaInPool(uint16)")] #[precompile::view] fn get_alpha_in_pool(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::SubnetAlphaIn::::get(NetUid::from( - netuid, - ))) + Ok(pallet_subtensor::SubnetAlphaIn::::get(NetUid::from(netuid)).into()) } #[precompile::public("getAlphaOutPool(uint16)")] #[precompile::view] fn get_alpha_out_pool(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::SubnetAlphaOut::::get(NetUid::from( - netuid, - ))) + Ok(pallet_subtensor::SubnetAlphaOut::::get(NetUid::from(netuid)).into()) } #[precompile::public("getAlphaIssuance(uint16)")] #[precompile::view] fn get_alpha_issuance(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_alpha_issuance( - netuid.into(), - )) + Ok(pallet_subtensor::Pallet::::get_alpha_issuance(netuid.into()).into()) } #[precompile::public("getTaoWeight()")] #[precompile::view] fn get_tao_weight(_handle: &mut impl PrecompileHandle) -> EvmResult { - let weight = pallet_subtensor::Pallet::::get_tao_weight(); - Ok(U256::from(weight.saturating_to_num::())) + let tao_weight = pallet_subtensor::TaoWeight::::get(); + Ok(U256::from(tao_weight)) } #[precompile::public("simSwapTaoForAlpha(uint16,uint64)")] @@ -149,4 +160,55 @@ where NetUid::from(netuid), ))) } + + #[precompile::public("getTaoInEmission(uint16)")] + #[precompile::view] + fn get_tao_in_emission(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(U256::from(pallet_subtensor::SubnetTaoInEmission::::get( + NetUid::from(netuid), + ))) + } + + #[precompile::public("getAlphaInEmission(uint16)")] + #[precompile::view] + fn get_alpha_in_emission(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(U256::from( + pallet_subtensor::SubnetAlphaInEmission::::get(NetUid::from(netuid)).to_u64(), + )) + } + + #[precompile::public("getAlphaOutEmission(uint16)")] + #[precompile::view] + fn get_alpha_out_emission(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(U256::from( + pallet_subtensor::SubnetAlphaOutEmission::::get(NetUid::from(netuid)).to_u64(), + )) + } + + #[precompile::public("getSumAlphaPrice()")] + #[precompile::view] + fn get_sum_alpha_price(_handle: &mut impl PrecompileHandle) -> EvmResult { + let netuids = pallet_subtensor::NetworksAdded::::iter() + .filter(|(netuid, _)| *netuid != NetUid::ROOT) + .collect::>(); + + let mut sum_alpha_price: U96F32 = U96F32::from_num(0); + for (netuid, _) in netuids { + let price = + as SwapHandler>::current_alpha_price( + netuid.into(), + ); + + if price < U96F32::from_num(1) { + sum_alpha_price = sum_alpha_price.saturating_add(price); + } + } + + let price: SubstrateBalance = sum_alpha_price.saturating_to_num::().into(); + let price_eth = ::BalanceConverter::into_evm_balance(price) + .map(|amount| amount.into_u256()) + .ok_or(ExitError::InvalidRange)?; + + Ok(price_eth) + } } diff --git a/precompiles/src/crowdloan.rs b/precompiles/src/crowdloan.rs new file mode 100644 index 0000000000..cedcf24af3 --- /dev/null +++ b/precompiles/src/crowdloan.rs @@ -0,0 +1,228 @@ +use alloc::string::String; +use core::marker::PhantomData; + +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use frame_system::RawOrigin; +use pallet_evm::AddressMapping; +use pallet_evm::PrecompileHandle; +use precompile_utils::prelude::Address; +use precompile_utils::{EvmResult, solidity::Codec}; +use sp_core::{ByteArray, H256}; +use sp_runtime::traits::{Dispatchable, UniqueSaturatedInto}; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +pub struct CrowdloanPrecompile(PhantomData); + +impl PrecompileExt for CrowdloanPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_crowdloan::Config + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, +{ + const INDEX: u64 = 2057; +} + +#[precompile_utils::precompile] +impl CrowdloanPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_crowdloan::Config + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, +{ + #[precompile::public("getCrowdloan(uint32)")] + #[precompile::view] + fn get_crowdloan( + _handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + ) -> EvmResult { + let crowdloan = pallet_crowdloan::Crowdloans::::get(crowdloan_id).ok_or( + PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }, + )?; + + Ok(CrowdloanInfo { + creator: H256::from_slice(crowdloan.creator.as_slice()), + deposit: crowdloan.deposit, + min_contribution: crowdloan.min_contribution, + end: crowdloan.end.unique_saturated_into(), + cap: crowdloan.cap, + funds_account: H256::from_slice(crowdloan.funds_account.as_slice()), + raised: crowdloan.raised, + has_target_address: crowdloan.target_address.is_some(), + target_address: crowdloan + .target_address + .map(|a| H256::from_slice(a.as_slice())) + .unwrap_or_else(H256::zero), + finalized: crowdloan.finalized, + contributors_count: crowdloan.contributors_count, + }) + } + + #[precompile::public("getContribution(uint32,bytes32)")] + #[precompile::view] + fn get_contribution( + _handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + coldkey: H256, + ) -> EvmResult { + let coldkey = R::AccountId::from(coldkey.0); + let contribution = pallet_crowdloan::Contributions::::get(crowdloan_id, coldkey).ok_or( + PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }, + )?; + + Ok(contribution) + } + + #[precompile::public("create(uint64,uint64,uint64,uint32,address)")] + #[precompile::payable] + fn create( + handle: &mut impl PrecompileHandle, + deposit: u64, + min_contribution: u64, + cap: u64, + end: u32, + target_address: Address, + ) -> EvmResult<()> { + let who = handle.caller_account_id::(); + let target_address = R::AddressMapping::into_account_id(target_address.0); + let call = pallet_crowdloan::Call::::create { + deposit, + min_contribution, + cap, + end: end.into(), + call: None, + target_address: Some(target_address), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(who)) + } + + #[precompile::public("contribute(uint32,uint64)")] + #[precompile::payable] + fn contribute( + handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + amount: u64, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::contribute { + crowdloan_id, + amount, + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("withdraw(uint32)")] + #[precompile::payable] + fn withdraw(handle: &mut impl PrecompileHandle, crowdloan_id: u32) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::withdraw { crowdloan_id }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("finalize(uint32)")] + #[precompile::payable] + fn finalize(handle: &mut impl PrecompileHandle, crowdloan_id: u32) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::finalize { crowdloan_id }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("refund(uint32)")] + #[precompile::payable] + fn refund(handle: &mut impl PrecompileHandle, crowdloan_id: u32) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::refund { crowdloan_id }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("dissolve(uint32)")] + #[precompile::payable] + fn dissolve(handle: &mut impl PrecompileHandle, crowdloan_id: u32) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::dissolve { crowdloan_id }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("updateMinContribution(uint32,uint64)")] + #[precompile::payable] + fn update_min_contribution( + handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + new_min_contribution: u64, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::update_min_contribution { + crowdloan_id, + new_min_contribution, + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("updateEnd(uint32,uint32)")] + #[precompile::payable] + fn update_end( + handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + new_end: u32, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::update_end { + crowdloan_id, + new_end: new_end.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("updateCap(uint32,uint64)")] + #[precompile::payable] + fn update_cap( + handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + new_cap: u64, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::update_cap { + crowdloan_id, + new_cap, + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } +} + +#[derive(Codec)] +struct CrowdloanInfo { + creator: H256, + deposit: u64, + min_contribution: u64, + end: u32, + cap: u64, + funds_account: H256, + raised: u64, + has_target_address: bool, + target_address: H256, + finalized: bool, + contributors_count: u32, +} diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 19020a0d1b..2eb83d1678 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -26,6 +26,7 @@ use pallet_admin_utils::PrecompileEnum; use crate::alpha::*; use crate::balance_transfer::*; +use crate::crowdloan::*; use crate::ed25519::*; use crate::extensions::*; use crate::metagraph::*; @@ -38,6 +39,7 @@ use crate::uid_lookup::*; mod alpha; mod balance_transfer; +mod crowdloan; mod ed25519; mod extensions; mod metagraph; @@ -57,12 +59,14 @@ where + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config - + pallet_proxy::Config, + + pallet_proxy::Config + + pallet_crowdloan::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> + From> + From> + From> + + From> + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, @@ -82,12 +86,14 @@ where + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config - + pallet_proxy::Config, + + pallet_proxy::Config + + pallet_crowdloan::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> + From> + From> + From> + + From> + GetDispatchInfo + Dispatchable, ::AddressMapping: AddressMapping, @@ -98,7 +104,7 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 19] { + pub fn used_addresses() -> [H160; 20] { [ hash(1), hash(2), @@ -119,6 +125,7 @@ where hash(StorageQueryPrecompile::::INDEX), hash(UidLookupPrecompile::::INDEX), hash(AlphaPrecompile::::INDEX), + hash(CrowdloanPrecompile::::INDEX), ] } } @@ -130,12 +137,14 @@ where + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config - + pallet_proxy::Config, + + pallet_proxy::Config + + pallet_crowdloan::Config, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeCall: From> + From> + From> + From> + + From> + GetDispatchInfo + Dispatchable + Decode, @@ -194,6 +203,9 @@ where a if a == hash(AlphaPrecompile::::INDEX) => { AlphaPrecompile::::try_execute::(handle, PrecompileEnum::Alpha) } + a if a == hash(CrowdloanPrecompile::::INDEX) => { + CrowdloanPrecompile::::try_execute::(handle, PrecompileEnum::Crowdloan) + } _ => None, } } diff --git a/precompiles/src/metagraph.rs b/precompiles/src/metagraph.rs index 05f7a5bf79..a508dd7c02 100644 --- a/precompiles/src/metagraph.rs +++ b/precompiles/src/metagraph.rs @@ -94,10 +94,7 @@ where #[precompile::public("getEmission(uint16,uint16)")] #[precompile::view] fn get_emission(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { - Ok(pallet_subtensor::Pallet::::get_emission_for_uid( - netuid.into(), - uid, - )) + Ok(pallet_subtensor::Pallet::::get_emission_for_uid(netuid.into(), uid).into()) } #[precompile::public("getVtrust(uint16,uint16)")] diff --git a/precompiles/src/solidity/alpha.abi b/precompiles/src/solidity/alpha.abi index feb2b518af..06975d5e61 100644 --- a/precompiles/src/solidity/alpha.abi +++ b/precompiles/src/solidity/alpha.abi @@ -7,7 +7,7 @@ "type": "uint16" } ], - "name": "getAlphaPrice", + "name": "getAlphaInEmission", "outputs": [ { "internalType": "uint256", @@ -26,12 +26,12 @@ "type": "uint16" } ], - "name": "getMovingAlphaPrice", + "name": "getAlphaInPool", "outputs": [ { - "internalType": "uint256", + "internalType": "uint64", "name": "", - "type": "uint256" + "type": "uint64" } ], "stateMutability": "view", @@ -45,7 +45,7 @@ "type": "uint16" } ], - "name": "getTaoInPool", + "name": "getAlphaIssuance", "outputs": [ { "internalType": "uint64", @@ -64,12 +64,12 @@ "type": "uint16" } ], - "name": "getAlphaInPool", + "name": "getAlphaOutEmission", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" } ], "stateMutability": "view", @@ -102,7 +102,26 @@ "type": "uint16" } ], - "name": "getAlphaIssuance", + "name": "getAlphaPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getEMAPriceHalvingBlocks", "outputs": [ { "internalType": "uint64", @@ -114,8 +133,14 @@ "type": "function" }, { - "inputs": [], - "name": "getTaoWeight", + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMovingAlphaPrice", "outputs": [ { "internalType": "uint256", @@ -126,20 +151,47 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getRootNetuid", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "uint16", "name": "netuid", "type": "uint16" - }, + } + ], + "name": "getSubnetMechanism", + "outputs": [ { - "internalType": "uint64", - "name": "tao", - "type": "uint64" + "internalType": "uint16", + "name": "", + "type": "uint16" } ], - "name": "simSwapTaoForAlpha", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetVolume", "outputs": [ { "internalType": "uint256", @@ -156,14 +208,9 @@ "internalType": "uint16", "name": "netuid", "type": "uint16" - }, - { - "internalType": "uint64", - "name": "alpha", - "type": "uint64" } ], - "name": "simSwapAlphaForTao", + "name": "getTaoInEmission", "outputs": [ { "internalType": "uint256", @@ -182,12 +229,12 @@ "type": "uint16" } ], - "name": "getSubnetMechanism", + "name": "getTaoInPool", "outputs": [ { - "internalType": "uint16", + "internalType": "uint64", "name": "", - "type": "uint16" + "type": "uint64" } ], "stateMutability": "view", @@ -195,12 +242,12 @@ }, { "inputs": [], - "name": "getRootNetuid", + "name": "getTaoWeight", "outputs": [ { - "internalType": "uint16", + "internalType": "uint256", "name": "", - "type": "uint16" + "type": "uint256" } ], "stateMutability": "view", @@ -212,14 +259,19 @@ "internalType": "uint16", "name": "netuid", "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" } ], - "name": "getEMAPriceHalvingBlocks", + "name": "simSwapAlphaForTao", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" } ], "stateMutability": "view", @@ -231,9 +283,27 @@ "internalType": "uint16", "name": "netuid", "type": "uint16" + }, + { + "internalType": "uint64", + "name": "tao", + "type": "uint64" } ], - "name": "getSubnetVolume", + "name": "simSwapTaoForAlpha", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSumAlphaPrice", "outputs": [ { "internalType": "uint256", diff --git a/precompiles/src/solidity/alpha.sol b/precompiles/src/solidity/alpha.sol index 7bb529f684..e66dcf00d9 100644 --- a/precompiles/src/solidity/alpha.sol +++ b/precompiles/src/solidity/alpha.sol @@ -41,13 +41,19 @@ interface IAlpha { /// @param netuid The subnet identifier. /// @param tao The amount of TAO to swap. /// @return The amount of alpha that would be received. - function simSwapTaoForAlpha(uint16 netuid, uint64 tao) external view returns (uint256); + function simSwapTaoForAlpha( + uint16 netuid, + uint64 tao + ) external view returns (uint256); /// @dev Simulates swapping alpha for TAO. /// @param netuid The subnet identifier. /// @param alpha The amount of alpha to swap. /// @return The amount of TAO that would be received. - function simSwapAlphaForTao(uint16 netuid, uint64 alpha) external view returns (uint256); + function simSwapAlphaForTao( + uint16 netuid, + uint64 alpha + ) external view returns (uint256); /// @dev Returns the mechanism type for a subnet (0 for Stable, 1 for Dynamic). /// @param netuid The subnet identifier. @@ -61,10 +67,31 @@ interface IAlpha { /// @dev Returns the EMA price halving blocks parameter for a subnet. /// @param netuid The subnet identifier. /// @return The number of blocks for EMA price halving. - function getEMAPriceHalvingBlocks(uint16 netuid) external view returns (uint64); + function getEMAPriceHalvingBlocks( + uint16 netuid + ) external view returns (uint64); /// @dev Returns the transaction volume for a subnet. /// @param netuid The subnet identifier. /// @return The subnet volume. function getSubnetVolume(uint16 netuid) external view returns (uint256); + + /// @dev Returns the amount of tao emission into the pool per block for a subnet. + /// @param netuid The subnet identifier. + /// @return The tao-in emission per block. + function getTaoInEmission(uint16 netuid) external view returns (uint256); + + /// @dev Returns the amount of alpha emission into the pool per block for a subnet. + /// @param netuid The subnet identifier. + /// @return The alpha-in emission per block. + function getAlphaInEmission(uint16 netuid) external view returns (uint256); + + /// @dev Returns the amount of alpha emission outside the pool per block for a subnet. + /// @param netuid The subnet identifier. + /// @return The alpha-out emission per block. + function getAlphaOutEmission(uint16 netuid) external view returns (uint256); + + /// @dev Returns the sum of alpha prices for all subnets. + /// @return The sum of alpha prices. + function getSumAlphaPrice() external view returns (uint256); } diff --git a/precompiles/src/solidity/crowdloan.abi b/precompiles/src/solidity/crowdloan.abi new file mode 100644 index 0000000000..c507afcca2 --- /dev/null +++ b/precompiles/src/solidity/crowdloan.abi @@ -0,0 +1,259 @@ +[ + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + } + ], + "name": "contribute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "deposit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minContribution", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cap", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "end", + "type": "uint32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "create", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "dissolve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "finalize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getContribution", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "getCrowdloan", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "creator", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "deposit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "min_contribution", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "end", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "cap", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "funds_account", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "raised", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "has_target_address", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "target_address", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "contributors_count", + "type": "uint32" + } + ], + "internalType": "struct CrowdloanInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "refund", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "newCap", + "type": "uint64" + } + ], + "name": "updateCap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "newEnd", + "type": "uint32" + } + ], + "name": "updateEnd", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "newMinContribution", + "type": "uint64" + } + ], + "name": "updateMinContribution", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/crowdloan.sol b/precompiles/src/solidity/crowdloan.sol new file mode 100644 index 0000000000..e8bf30c5d0 --- /dev/null +++ b/precompiles/src/solidity/crowdloan.sol @@ -0,0 +1,111 @@ +pragma solidity ^0.8.0; + +address constant ICROWDLOAN_ADDRESS = 0x0000000000000000000000000000000000000809; + +interface ICrowdloan { + /** + * @dev Retrieves the crowdloan info for a given crowdloan id. + * @param crowdloanId The id of the crowdloan to get info for. + * @return The crowdloan info. + */ + function getCrowdloan(uint32 crowdloanId) + external + view + returns (CrowdloanInfo memory); + + /** + * @dev Retrieves the contribution for a given crowdloan id and coldkey. + * @param crowdloanId The id of the crowdloan to get contribution for. + * @param coldkey The coldkey of the contributor. + * @return The contribution. + */ + function getContribution(uint32 crowdloanId, bytes32 coldkey) + external + view + returns (uint64); + + /** + * @dev Creates a crowdloan that will raise funds up to a maximum cap and if successful, transfer the funds to the target address. + * @param deposit The initial deposit from the creator. + * @param minContribution The minimum contribution required to contribute to the crowdloan. + * @param cap The maximum amount of funds that can be raised. + * @param end The block number at which the crowdloan will end. + * @param targetAddress The address to transfer the raised funds to. + */ + function create( + uint64 deposit, + uint64 minContribution, + uint64 cap, + uint32 end, + address targetAddress + ) external payable; + + /** + * @dev Contributes to an active crowdloan. + * @param crowdloanId The id of the crowdloan to contribute to. + * @param amount The amount of funds to contribute. + */ + function contribute(uint32 crowdloanId, uint64 amount) external payable; + + /** + * @dev Withdraws a contribution from an active crowdloan. + * @param crowdloanId The id of the crowdloan to withdraw from. + */ + function withdraw(uint32 crowdloanId) external payable; + + /** + * @dev Finalizes a successful crowdloan. + * @param crowdloanId The id of the crowdloan to finalize. + */ + function finalize(uint32 crowdloanId) external payable; + + /** + * @dev Refunds a failed crowdloan (may need to be called multiple times to refund all contributors). + * @param crowdloanId The id of the crowdloan to refund. + */ + function refund(uint32 crowdloanId) external payable; + + /** + * @dev Dissolves a failed crowdloan. + * @param crowdloanId The id of the crowdloan to dissolve. + */ + function dissolve(uint32 crowdloanId) external payable; + + /** + * @dev Updates the minimum contribution for an active crowdloan. + * @param crowdloanId The id of the crowdloan to update. + * @param newMinContribution The new minimum contribution. + */ + function updateMinContribution( + uint32 crowdloanId, + uint64 newMinContribution + ) external payable; + + /** + * @dev Updates the end block for an active crowdloan. + * @param crowdloanId The id of the crowdloan to update. + * @param newEnd The new end block. + */ + function updateEnd(uint32 crowdloanId, uint32 newEnd) external payable; + + /** + * @dev Updates the cap for an active crowdloan. + * @param crowdloanId The id of the crowdloan to update. + * @param newCap The new cap. + */ + function updateCap(uint32 crowdloanId, uint64 newCap) external payable; +} + +struct CrowdloanInfo { + bytes32 creator; + uint64 deposit; + uint64 min_contribution; + uint32 end; + uint64 cap; + bytes32 funds_account; + uint64 raised; + bool has_target_address; + bytes32 target_address; + bool finalized; + uint32 contributors_count; +} \ No newline at end of file diff --git a/precompiles/src/solidity/stakingV2.abi b/precompiles/src/solidity/stakingV2.abi index 6772a15905..2c936898ab 100644 --- a/precompiles/src/solidity/stakingV2.abi +++ b/precompiles/src/solidity/stakingV2.abi @@ -183,6 +183,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getNominatorMinRequiredStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/precompiles/src/solidity/stakingV2.sol b/precompiles/src/solidity/stakingV2.sol index f9feafd07b..c8c39761ad 100644 --- a/precompiles/src/solidity/stakingV2.sol +++ b/precompiles/src/solidity/stakingV2.sol @@ -195,6 +195,16 @@ interface IStaking { uint256 netuid ) external view returns (uint256); + /** + * @dev Returns the minimum required stake for a nominator. + * + * This function retrieves the minimum required stake for a nominator. + * It is a view function, meaning it does not modify the state of the contract and is free to call. + * + * @return The minimum required stake for a nominator. + */ + function getNominatorMinRequiredStake() external view returns (uint256); + /** * @dev Adds a subtensor stake `amount` associated with the `hotkey` within a price limit. * diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 1acee0514e..22756c2a9a 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -111,11 +111,11 @@ where let account_id = handle.caller_account_id::(); let hotkey = R::AccountId::from(address.0); let netuid = try_u16_from_u256(netuid)?; - let amount_unstaked = amount_alpha.unique_saturated_into(); + let amount_unstaked: u64 = amount_alpha.unique_saturated_into(); let call = pallet_subtensor::Call::::remove_stake { hotkey, netuid: netuid.into(), - amount_unstaked, + amount_unstaked: amount_unstaked.into(), }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) @@ -173,13 +173,13 @@ where let destination_hotkey = R::AccountId::from(destination_hotkey.0); let origin_netuid = try_u16_from_u256(origin_netuid)?; let destination_netuid = try_u16_from_u256(destination_netuid)?; - let alpha_amount = amount_alpha.unique_saturated_into(); + let alpha_amount: u64 = amount_alpha.unique_saturated_into(); let call = pallet_subtensor::Call::::move_stake { origin_hotkey, destination_hotkey, origin_netuid: origin_netuid.into(), destination_netuid: destination_netuid.into(), - alpha_amount, + alpha_amount: alpha_amount.into(), }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) @@ -199,13 +199,13 @@ where let hotkey = R::AccountId::from(hotkey.0); let origin_netuid = try_u16_from_u256(origin_netuid)?; let destination_netuid = try_u16_from_u256(destination_netuid)?; - let alpha_amount = amount_alpha.unique_saturated_into(); + let alpha_amount: u64 = amount_alpha.unique_saturated_into(); let call = pallet_subtensor::Call::::transfer_stake { destination_coldkey, hotkey, origin_netuid: origin_netuid.into(), destination_netuid: destination_netuid.into(), - alpha_amount, + alpha_amount: alpha_amount.into(), }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) @@ -252,7 +252,7 @@ where netuid.into(), ); - Ok(stake.into()) + Ok(u64::from(stake).into()) } #[precompile::public("getAlphaStakedValidators(bytes32,uint256)")] @@ -288,6 +288,14 @@ where let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_on_subnet(&hotkey, netuid.into()); + Ok(u64::from(stake).into()) + } + + #[precompile::public("getNominatorMinRequiredStake()")] + #[precompile::view] + fn get_nominator_min_required_stake(_handle: &mut impl PrecompileHandle) -> EvmResult { + let stake = pallet_subtensor::Pallet::::get_nominator_min_required_stake(); + Ok(stake.into()) } @@ -356,12 +364,12 @@ where let account_id = handle.caller_account_id::(); let hotkey = R::AccountId::from(address.0); let netuid = try_u16_from_u256(netuid)?; - let amount_unstaked = amount_alpha.unique_saturated_into(); + let amount_unstaked: u64 = amount_alpha.unique_saturated_into(); let limit_price = limit_price_rao.unique_saturated_into(); let call = pallet_subtensor::Call::::remove_stake_limit { hotkey, netuid: netuid.into(), - amount_unstaked, + amount_unstaked: amount_unstaked.into(), limit_price, allow_partial, }; @@ -451,7 +459,7 @@ where let call = pallet_subtensor::Call::::remove_stake { hotkey, netuid: netuid.into(), - amount_unstaked, + amount_unstaked: amount_unstaked.into(), }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) @@ -511,7 +519,7 @@ where &coldkey, netuid.into(), ); - let stake: SubstrateBalance = stake.into(); + let stake: SubstrateBalance = u64::from(stake).into(); let stake = ::BalanceConverter::into_evm_balance(stake) .map(|amount| amount.into_u256()) .ok_or(ExitError::InvalidRange)?; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 384e841072..513dc017c5 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -68,7 +68,7 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use subtensor_precompiles::Precompiles; -use subtensor_runtime_common::{time::*, *}; +use subtensor_runtime_common::{AlphaCurrency, time::*, *}; // A few exports that help ease life for downstream crates. pub use frame_support::{ @@ -218,7 +218,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `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: 292, + spec_version: 294, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -746,7 +746,7 @@ impl InstanceFilter for ProxyType { RuntimeCall::SubtensorModule(pallet_subtensor::Call::transfer_stake { alpha_amount, .. - }) => *alpha_amount < SMALL_TRANSFER_LIMIT, + }) => *alpha_amount < SMALL_TRANSFER_LIMIT.into(), _ => false, }, ProxyType::Owner => { @@ -2314,7 +2314,7 @@ impl_runtime_apis! { SubtensorModule::get_delegate(delegate_account) } - fn get_delegated(delegatee_account: AccountId32) -> Vec<(DelegateInfo, (Compact, Compact))> { + fn get_delegated(delegatee_account: AccountId32) -> Vec<(DelegateInfo, (Compact, Compact))> { SubtensorModule::get_delegated(delegatee_account) } }