From 7e4d477d4667d3e4efe335ff862fa23fea0d2c1b Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 7 Aug 2025 11:50:40 +0800 Subject: [PATCH 01/10] more test cases for different types storage --- .../test/runtime.call.precompile.test.ts | 122 +++++++++++++++--- 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/evm-tests/test/runtime.call.precompile.test.ts b/evm-tests/test/runtime.call.precompile.test.ts index 1b96c474a5..6ae1973593 100644 --- a/evm-tests/test/runtime.call.precompile.test.ts +++ b/evm-tests/test/runtime.call.precompile.test.ts @@ -1,26 +1,40 @@ import * as assert from "assert"; -import { getAliceSigner, getDevnetApi } from "../src/substrate" +import { getAliceSigner, getDevnetApi, getRandomSubstrateKeypair } from "../src/substrate" import { generateRandomEthersWallet, getPublicClient } from "../src/utils"; import { IDISPATCH_ADDRESS, ISTORAGE_QUERY_ADDRESS, ETH_LOCAL_URL } from "../src/config"; import { devnet, MultiAddress } from "@polkadot-api/descriptors" -import { hexToNumber, PublicClient } from "viem"; -import { PolkadotSigner, TypedApi } from "polkadot-api"; +import { PublicClient } from "viem"; +import { PolkadotSigner, TypedApi, getTypedCodecs } from "polkadot-api"; import { convertPublicKeyToSs58 } from "../src/address-utils" -import { forceSetBalanceToEthAddress, setMaxChildkeyTake } from "../src/subtensor"; -import { xxhashAsU8a } from '@polkadot/util-crypto'; -import { u8aToHex } from '@polkadot/util'; +import { forceSetBalanceToEthAddress, setMaxChildkeyTake, burnedRegister, forceSetBalanceToSs58Address, addStake, setTxRateLimit, addNewSubnetwork, startCall, setTempo } from "../src/subtensor"; describe("Test the dispatch precompile", () => { let publicClient: PublicClient; const wallet1 = generateRandomEthersWallet(); let api: TypedApi let alice: PolkadotSigner; + const hotkey = getRandomSubstrateKeypair(); + const coldkey = getRandomSubstrateKeypair(); + let netuid: number; before(async () => { publicClient = await getPublicClient(ETH_LOCAL_URL) api = await getDevnetApi() alice = await getAliceSigner() await forceSetBalanceToEthAddress(api, wallet1.address) + + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) + + + netuid = await addNewSubnetwork(api, hotkey, coldkey) + // set tempo big enough to avoid stake value updated with fast block feature + await setTempo(api, netuid, 10000) + await startCall(api, netuid, coldkey) + await setTxRateLimit(api, BigInt(0)) + + await burnedRegister(api, netuid, convertPublicKeyToSs58(hotkey.publicKey), coldkey) + await addStake(api, netuid, convertPublicKeyToSs58(hotkey.publicKey), BigInt(1_000_000_000), coldkey) }) it("Dispatch transfer call via precompile contract works correctly", async () => { @@ -49,13 +63,8 @@ describe("Test the dispatch precompile", () => { }) - it("Storage query call via precompile contract works correctly", async () => { - const palletPrefixBytes = xxhashAsU8a("SubtensorModule", 128); - const storageItemPrefixBytes = xxhashAsU8a("MaxChildkeyTake", 128); - const fullStorageKeyBytes = new Uint8Array([...palletPrefixBytes, ...storageItemPrefixBytes]); - // 0x658faa385070e074c85bf6b568cf0555dba018859cab7e989f77669457b394be - // key for max child key take - const fullStorageKeyHex = u8aToHex(fullStorageKeyBytes); + it("Value type storage query call via precompile contract works correctly", async () => { + const key = await api.query.SubtensorModule.MaxChildkeyTake.getKey(); let maxChildkeyTake = 257; await setMaxChildkeyTake(api, maxChildkeyTake) @@ -63,13 +72,86 @@ describe("Test the dispatch precompile", () => { api.query.SubtensorModule.MaxChildkeyTake.getValue(); const rawCallResponse = await publicClient.call({ to: ISTORAGE_QUERY_ADDRESS, - data: fullStorageKeyHex, + data: key.toString() as `0x${string}`, + }) + const rawResultData = rawCallResponse.data ?? ""; + + const codec = await getTypedCodecs(devnet); + const maxChildkeyTakeCodec = codec.query.SubtensorModule.MaxChildkeyTake.value; + const maxChildkeyTakeFromContract = maxChildkeyTakeCodec.dec(rawResultData); + assert.equal(maxChildkeyTakeFromContract, maxChildkeyTake, "value should be 257") + }) + + it("Map type storage query call via precompile contract works correctly", async () => { + + const key = await api.query.SubtensorModule.Tempo.getKey(netuid); + + const tempoOnChain = await api.query.SubtensorModule.Tempo.getValue(netuid); + const rawCallResponse = await publicClient.call({ + to: ISTORAGE_QUERY_ADDRESS, + data: key.toString() as `0x${string}`, + }) + const rawResultData = rawCallResponse.data ?? ""; + + const codec = await getTypedCodecs(devnet); + const maxChildkeyTakeValueCodec = codec.query.SubtensorModule.Tempo.value; + const decodedValue = maxChildkeyTakeValueCodec.dec(rawResultData); + assert.equal(tempoOnChain, decodedValue, "value should be the same as on chain") + }) + + it("Double map type storage query call via precompile contract works correctly", async () => { + const key = await api.query.SubtensorModule.TotalHotkeyAlpha.getKey(convertPublicKeyToSs58(hotkey.publicKey), netuid); + const totalHotkeyAlphaOnChain = await api.query.SubtensorModule.TotalHotkeyAlpha.getValue(convertPublicKeyToSs58(hotkey.publicKey), netuid); + + const rawCallResponse = await publicClient.call({ + to: ISTORAGE_QUERY_ADDRESS, + data: key.toString() as `0x${string}`, }) - const rawResultData = rawCallResponse.data; - if (rawResultData === undefined) { - throw new Error("rawResultData is undefined"); - } - let value = hexToNumber(rawResultData); - assert.equal(value, maxChildkeyTake, "value should be 257") + const rawResultData = rawCallResponse.data ?? ""; + const codec = await getTypedCodecs(devnet); + const totalHotkeyAlphaValueCodec = codec.query.SubtensorModule.TotalHotkeyAlpha.value; + const decodedValue = totalHotkeyAlphaValueCodec.dec(rawResultData); + assert.equal(totalHotkeyAlphaOnChain, decodedValue, "value should be the same as on chain") + }) + + // Polkadot api can't decode the boolean type for now. + // it("Double map type storage query call via precompile contract works correctly", async () => { + + // const storageItemPrefixBytes = xxhashAsU8a("IsNetworkMember", 128); + // const codec = await getTypedCodecs(devnet); + // const isNetworkMemberArgsCodec = codec.query.SubtensorModule.IsNetworkMember.args; + // const encodedArgs = isNetworkMemberArgsCodec.enc([convertPublicKeyToSs58(alice.publicKey), netuid]); + + // console.log(encodedArgs) + + // const fullStorageKeyBytes = new Uint8Array([...palletPrefixBytes, ...storageItemPrefixBytes, ...encodedArgs]); + + // console.log(fullStorageKeyBytes) + + // const fullStorageKeyHex = u8aToHex(fullStorageKeyBytes); + + // console.log(fullStorageKeyHex) + + // const isNetworkMemberOnChain = await api.query.SubtensorModule.IsNetworkMember.getValue(convertPublicKeyToSs58(alice.publicKey), netuid); + + // console.log(isNetworkMemberOnChain) + + // const rawCallResponse = await publicClient.call({ + // to: ISTORAGE_QUERY_ADDRESS, + // data: fullStorageKeyHex, + // }) + + // console.log(rawCallResponse) + + // const rawResultData = rawCallResponse.data ?? ""; + + // const isNetworkMemberValueCodec = codec.query.SubtensorModule.IsNetworkMember.value; + // const decodedValue = isNetworkMemberValueCodec.dec(rawResultData); + + // console.log(decodedValue) + + // assert.equal(isNetworkMemberOnChain, decodedValue, "value should be the same as on chain") + // }) + }); From be146d375b68c9143c842b912ae170eff8effa83 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 7 Aug 2025 11:52:11 +0800 Subject: [PATCH 02/10] more test cases for different types storage --- .../test/runtime.call.precompile.test.ts | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/evm-tests/test/runtime.call.precompile.test.ts b/evm-tests/test/runtime.call.precompile.test.ts index 6ae1973593..dd91ce7f79 100644 --- a/evm-tests/test/runtime.call.precompile.test.ts +++ b/evm-tests/test/runtime.call.precompile.test.ts @@ -117,40 +117,18 @@ describe("Test the dispatch precompile", () => { // Polkadot api can't decode the boolean type for now. // it("Double map type storage query call via precompile contract works correctly", async () => { - - // const storageItemPrefixBytes = xxhashAsU8a("IsNetworkMember", 128); - // const codec = await getTypedCodecs(devnet); - // const isNetworkMemberArgsCodec = codec.query.SubtensorModule.IsNetworkMember.args; - // const encodedArgs = isNetworkMemberArgsCodec.enc([convertPublicKeyToSs58(alice.publicKey), netuid]); - - // console.log(encodedArgs) - - // const fullStorageKeyBytes = new Uint8Array([...palletPrefixBytes, ...storageItemPrefixBytes, ...encodedArgs]); - - // console.log(fullStorageKeyBytes) - - // const fullStorageKeyHex = u8aToHex(fullStorageKeyBytes); - - // console.log(fullStorageKeyHex) + // const key = await api.query.SubtensorModule.IsNetworkMember.getKey(convertPublicKeyToSs58(alice.publicKey), netuid); // const isNetworkMemberOnChain = await api.query.SubtensorModule.IsNetworkMember.getValue(convertPublicKeyToSs58(alice.publicKey), netuid); - - // console.log(isNetworkMemberOnChain) - // const rawCallResponse = await publicClient.call({ // to: ISTORAGE_QUERY_ADDRESS, - // data: fullStorageKeyHex, + // data: key.toString() as `0x${string}`, // }) - // console.log(rawCallResponse) - // const rawResultData = rawCallResponse.data ?? ""; - + // const codec = await getTypedCodecs(devnet); // const isNetworkMemberValueCodec = codec.query.SubtensorModule.IsNetworkMember.value; // const decodedValue = isNetworkMemberValueCodec.dec(rawResultData); - - // console.log(decodedValue) - // assert.equal(isNetworkMemberOnChain, decodedValue, "value should be the same as on chain") // }) From a99244f910d0d816abf9d78f4bd290e8971eeeb6 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 7 Aug 2025 11:57:22 +0800 Subject: [PATCH 03/10] bump version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index db35faf7e0..64f48294e4 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -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: 299, + spec_version: 300, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 332701a7cf72de6ad103434208fc7413c8f12669 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 7 Aug 2025 12:42:04 +0800 Subject: [PATCH 04/10] upgrade polkadot api version --- evm-tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm-tests/package.json b/evm-tests/package.json index 9970967a88..8ac57b6e93 100644 --- a/evm-tests/package.json +++ b/evm-tests/package.json @@ -15,7 +15,7 @@ "dotenv": "16.4.7", "ethers": "^6.13.5", "mocha": "^11.1.0", - "polkadot-api": "^1.9.5", + "polkadot-api": "^1.11.0", "scale-ts": "^1.6.1", "viem": "2.23.4", "ws": "^8.18.2" From ea4e39f2d220c7c9bc7add3f17ac5704c64da60f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 12 Aug 2025 05:57:01 +0000 Subject: [PATCH 05/10] auto-update benchmark weights --- pallets/subtensor/src/macros/dispatches.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 1f9d85d08b..549a87d28d 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -693,7 +693,7 @@ mod dispatches { /// - Attempting to set prometheus information withing the rate limit min. /// #[pallet::call_index(4)] - #[pallet::weight((Weight::from_parts(28_150_000, 0) + #[pallet::weight((Weight::from_parts(43_000_000, 0) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::No))] pub fn serve_axon( @@ -827,7 +827,7 @@ mod dispatches { /// - The ip type v4 or v6. /// #[pallet::call_index(5)] - #[pallet::weight((Weight::from_parts(30_170_000, 0) + #[pallet::weight((Weight::from_parts(22_480_000, 0) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::No))] pub fn serve_prometheus( @@ -915,7 +915,7 @@ mod dispatches { /// Attempt to adjust the senate membership to include a hotkey #[pallet::call_index(63)] - #[pallet::weight((Weight::from_parts(48_160_000, 0) + #[pallet::weight((Weight::from_parts(63_690_000, 0) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)), DispatchClass::Normal, Pays::Yes))] pub fn adjust_senate(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { @@ -924,7 +924,7 @@ mod dispatches { /// User register a new subnetwork via burning token #[pallet::call_index(7)] - #[pallet::weight((Weight::from_parts(278_400_000, 0) + #[pallet::weight((Weight::from_parts(378_800_000, 0) .saturating_add(T::DbWeight::get().reads(49)) .saturating_add(T::DbWeight::get().writes(43)), DispatchClass::Normal, Pays::No))] pub fn burned_register( @@ -1956,7 +1956,7 @@ mod dispatches { /// Emits a `FirstEmissionBlockNumberSet` event on success. #[pallet::call_index(92)] #[pallet::weight(( - Weight::from_parts(24_370_000, 0).saturating_add(T::DbWeight::get().reads_writes(4, 2)), + Weight::from_parts(32_710_000, 0).saturating_add(T::DbWeight::get().reads_writes(4, 2)), DispatchClass::Operational, Pays::Yes ))] @@ -2020,7 +2020,7 @@ mod dispatches { /// Emits a `TokensRecycled` event on success. #[pallet::call_index(101)] #[pallet::weight(( - Weight::from_parts(76_470_000, 0).saturating_add(T::DbWeight::get().reads_writes(7, 4)), + Weight::from_parts(100_700_000, 0).saturating_add(T::DbWeight::get().reads_writes(7, 4)), DispatchClass::Operational, Pays::Yes ))] @@ -2045,7 +2045,7 @@ mod dispatches { /// Emits a `TokensBurned` event on success. #[pallet::call_index(102)] #[pallet::weight(( - Weight::from_parts(74_650_000, 0).saturating_add(T::DbWeight::get().reads_writes(7, 3)), + Weight::from_parts(97_500_000, 0).saturating_add(T::DbWeight::get().reads_writes(7, 3)), DispatchClass::Operational, Pays::Yes ))] From 92a3a73786df34db3ec17d407b911e31837bc347 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 20 Aug 2025 21:07:16 +0800 Subject: [PATCH 06/10] reduce new subnet creation --- evm-tests/test/uid.precompile.lookup.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm-tests/test/uid.precompile.lookup.test.ts b/evm-tests/test/uid.precompile.lookup.test.ts index f6e22ce032..648262cb02 100644 --- a/evm-tests/test/uid.precompile.lookup.test.ts +++ b/evm-tests/test/uid.precompile.lookup.test.ts @@ -11,7 +11,7 @@ import { PolkadotSigner, TypedApi } from "polkadot-api"; import { toViemAddress, convertPublicKeyToSs58 } from "../src/address-utils" import { IUIDLookupABI, IUID_LOOKUP_ADDRESS } from "../src/contracts/uidLookup" import { keccak256 } from 'ethers'; -import { addNewSubnetwork, forceSetBalanceToSs58Address, startCall } from "../src/subtensor"; +import { forceSetBalanceToSs58Address, startCall } from "../src/subtensor"; describe("Test the UID Lookup precompile", () => { const hotkey = getRandomSubstrateKeypair(); @@ -37,7 +37,7 @@ describe("Test the UID Lookup precompile", () => { await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) - netuid = await addNewSubnetwork(api, hotkey, coldkey) + netuid = (await api.query.SubtensorModule.TotalNetworks.getValue()) - 1; await startCall(api, netuid, coldkey) const maybeUid = await api.query.SubtensorModule.Uids.getValue(netuid, convertPublicKeyToSs58(hotkey.publicKey)) From 9a7487b6a669454ea190f66fad22235c2329f5a8 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 20 Aug 2025 21:13:14 +0800 Subject: [PATCH 07/10] revert the test case --- evm-tests/test/uid.precompile.lookup.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm-tests/test/uid.precompile.lookup.test.ts b/evm-tests/test/uid.precompile.lookup.test.ts index 648262cb02..f6e22ce032 100644 --- a/evm-tests/test/uid.precompile.lookup.test.ts +++ b/evm-tests/test/uid.precompile.lookup.test.ts @@ -11,7 +11,7 @@ import { PolkadotSigner, TypedApi } from "polkadot-api"; import { toViemAddress, convertPublicKeyToSs58 } from "../src/address-utils" import { IUIDLookupABI, IUID_LOOKUP_ADDRESS } from "../src/contracts/uidLookup" import { keccak256 } from 'ethers'; -import { forceSetBalanceToSs58Address, startCall } from "../src/subtensor"; +import { addNewSubnetwork, forceSetBalanceToSs58Address, startCall } from "../src/subtensor"; describe("Test the UID Lookup precompile", () => { const hotkey = getRandomSubstrateKeypair(); @@ -37,7 +37,7 @@ describe("Test the UID Lookup precompile", () => { await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) - netuid = (await api.query.SubtensorModule.TotalNetworks.getValue()) - 1; + netuid = await addNewSubnetwork(api, hotkey, coldkey) await startCall(api, netuid, coldkey) const maybeUid = await api.query.SubtensorModule.Uids.getValue(netuid, convertPublicKeyToSs58(hotkey.publicKey)) From b8c2e3064c61aa11af8a1c0db5f507060557f411 Mon Sep 17 00:00:00 2001 From: open-junius Date: Thu, 21 Aug 2025 22:17:11 +0800 Subject: [PATCH 08/10] bump version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 1d8e658f1c..7185922a9e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -215,7 +215,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: 303, + spec_version: 304, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 9760e009ace511755bd1378866c9c0000cc27fac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 29 Aug 2025 10:53:32 +0000 Subject: [PATCH 09/10] auto-update benchmark weights --- pallets/subtensor/src/macros/dispatches.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index aed0c150de..d9277d2c8e 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -120,9 +120,9 @@ mod dispatches { /// - On failure for each failed item in the batch. /// #[pallet::call_index(80)] - #[pallet::weight((Weight::from_parts(95_160_000, 0) - .saturating_add(T::DbWeight::get().reads(14)) - .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(18_930_000, 0) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(0_u64)), DispatchClass::Normal, Pays::No))] pub fn batch_set_weights( origin: OriginFor, netuids: Vec>, @@ -2201,7 +2201,7 @@ mod dispatches { /// * commit_reveal_version (`u16`): /// - The client (bittensor-drand) version #[pallet::call_index(113)] - #[pallet::weight((Weight::from_parts(64_530_000, 0) + #[pallet::weight((Weight::from_parts(80_110_000, 0) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))] pub fn commit_timelocked_weights( From 7626e0caa40b443fe2f2da9256be86225da9cc44 Mon Sep 17 00:00:00 2001 From: open-junius Date: Wed, 10 Sep 2025 13:06:32 +0800 Subject: [PATCH 10/10] commit Cargo.lock --- pallets/subtensor/src/macros/dispatches.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 526ecca278..f069ff0aa5 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -120,15 +120,9 @@ mod dispatches { /// - On failure for each failed item in the batch. /// #[pallet::call_index(80)] -<<<<<<< HEAD - #[pallet::weight((Weight::from_parts(18_930_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(0_u64)), DispatchClass::Normal, Pays::No))] -======= #[pallet::weight((Weight::from_parts(95_460_000, 0) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)), DispatchClass::Normal, Pays::No))] ->>>>>>> devnet-ready pub fn batch_set_weights( origin: OriginFor, netuids: Vec>,