diff --git a/evm-tests/test/runtime.call.precompile.test.ts b/evm-tests/test/runtime.call.precompile.test.ts index 1b96c474a5..dd91ce7f79 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,64 @@ 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; - 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 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 ?? ""; + 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 key = await api.query.SubtensorModule.IsNetworkMember.getKey(convertPublicKeyToSs58(alice.publicKey), netuid); + + // const isNetworkMemberOnChain = await api.query.SubtensorModule.IsNetworkMember.getValue(convertPublicKeyToSs58(alice.publicKey), 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 isNetworkMemberValueCodec = codec.query.SubtensorModule.IsNetworkMember.value; + // const decodedValue = isNetworkMemberValueCodec.dec(rawResultData); + // assert.equal(isNetworkMemberOnChain, decodedValue, "value should be the same as on chain") + // }) + });