From 932ee00fdde638b9ea185b5b56de5237fa75b98b Mon Sep 17 00:00:00 2001 From: fine135 Date: Tue, 10 Mar 2026 17:44:21 +0100 Subject: [PATCH] feat: implement drand randomness precompile Introduces a new EVM precompile for smart contracts to access the Substrate Drand randomness beacon state. - Added DrandPrecompile in drand.rs to expose pallet-drand storage to EVM - Added PrecompileHandleExtStorage trait to automate gas cost calculation on database reads based on SCALE-encoded size - Created Solidity interface and ABI in drand.sol and drand.abi, mapped to address 0x0811 - Hooked the new precompile into the EVM environment in lib.rs - Added comprehensive TypeScript test suite in drand.precompile.test.ts covering edge cases, decoding, and gas metering - Updated related dependencies in Cargo.toml and yarn.lock --- Cargo.lock | 1 + contract-tests/src/contracts/drand.ts | 86 +++ contract-tests/test/drand.precompile.test.ts | 234 ++++++++ contract-tests/yarn.lock | 553 +++++++++++++------ pallets/admin-utils/src/lib.rs | 2 + pallets/drand/src/lib.rs | 16 +- precompiles/Cargo.toml | 2 + precompiles/src/drand.rs | 205 +++++++ precompiles/src/lib.rs | 42 +- precompiles/src/solidity/drand.abi | 100 ++++ precompiles/src/solidity/drand.sol | 61 ++ 11 files changed, 1113 insertions(+), 189 deletions(-) create mode 100644 contract-tests/src/contracts/drand.ts create mode 100644 contract-tests/test/drand.precompile.test.ts create mode 100644 precompiles/src/drand.rs create mode 100644 precompiles/src/solidity/drand.abi create mode 100644 precompiles/src/solidity/drand.sol diff --git a/Cargo.lock b/Cargo.lock index f936e40cf6..3d9cc7d469 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18099,6 +18099,7 @@ dependencies = [ "pallet-admin-utils", "pallet-balances", "pallet-crowdloan", + "pallet-drand", "pallet-evm", "pallet-evm-precompile-bn128", "pallet-evm-precompile-dispatch", diff --git a/contract-tests/src/contracts/drand.ts b/contract-tests/src/contracts/drand.ts new file mode 100644 index 0000000000..b441e370b5 --- /dev/null +++ b/contract-tests/src/contracts/drand.ts @@ -0,0 +1,86 @@ +export const IDRAND_ADDRESS = "0x0000000000000000000000000000000000000811"; + +export const IDrandABI = [ + { + "type": "function", + "name": "getLastStoredRound", + "inputs": [], + "outputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getOldestStoredRound", + "inputs": [], + "outputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPulse", + "inputs": [{ "name": "round", "type": "uint64", "internalType": "uint64" }], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct IDrand.DrandPulse", + "components": [ + { "name": "randomness", "type": "bytes32", "internalType": "bytes32" }, + { "name": "signature", "type": "bytes", "internalType": "bytes" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCurrentRandomness", + "inputs": [], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBeaconConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct IDrand.BeaconConfig", + "components": [ + { "name": "genesisTime", "type": "uint32", "internalType": "uint32" }, + { "name": "period", "type": "uint32", "internalType": "uint32" }, + { "name": "publicKey", "type": "bytes", "internalType": "bytes" }, + { "name": "chainHash", "type": "bytes32", "internalType": "bytes32" }, + { "name": "groupHash", "type": "bytes32", "internalType": "bytes32" }, + { "name": "schemeId", "type": "bytes", "internalType": "bytes" }, + { "name": "beaconId", "type": "bytes", "internalType": "bytes" }, + { "name": "isExplicitlyConfigured", "type": "bool", "internalType": "bool" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getHasMigrationRun", + "inputs": [{ "name": "migrationName", "type": "string", "internalType": "string" }], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getNextUnsignedAt", + "inputs": [], + "outputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPalletVersion", + "inputs": [], + "outputs": [{ "name": "", "type": "uint16", "internalType": "uint16" }], + "stateMutability": "view" + } +] as const; diff --git a/contract-tests/test/drand.precompile.test.ts b/contract-tests/test/drand.precompile.test.ts new file mode 100644 index 0000000000..14c100c463 --- /dev/null +++ b/contract-tests/test/drand.precompile.test.ts @@ -0,0 +1,234 @@ +import * as assert from "assert"; + +import { getDevnetApi } from "../src/substrate"; +import { getPublicClient } from "../src/utils"; +import { ETH_LOCAL_URL } from "../src/config"; +import { devnet } from "@polkadot-api/descriptors"; +import { PublicClient } from "viem"; +import { TypedApi } from "polkadot-api"; +import { toViemAddress } from "../src/address-utils"; +import { IDRAND_ADDRESS, IDrandABI } from "../src/contracts/drand"; + +// Helper to call a view function against the drand precompile. +async function readDrand( + publicClient: PublicClient, + functionName: string, + args: unknown[] = [] +): Promise { + return publicClient.readContract({ + abi: IDrandABI, + address: toViemAddress(IDRAND_ADDRESS), + functionName: functionName as any, + args: args as any, + }) as Promise; +} + +describe("Test Drand Precompile (0x811)", () => { + let publicClient: PublicClient; + let api: TypedApi; + + before(async () => { + publicClient = await getPublicClient(ETH_LOCAL_URL); + api = await getDevnetApi(); + }); + + describe("View Storage Functions", () => { + + // ─── getLastStoredRound ─────────────────────────────────────────────── + it("getLastStoredRound returns matching on-chain value", async () => { + const onChain = await api.query.Drand.LastStoredRound.getValue(); + const fromContract = await readDrand(publicClient, "getLastStoredRound"); + + const expected = onChain !== undefined ? BigInt(onChain as any) : BigInt(0); + const actual = BigInt(fromContract as any); + const diff = actual > expected ? actual - expected : expected - actual; + assert.ok( + diff <= BigInt(2), + `LastStoredRound should match closely (actual: ${actual}, expected: ${expected})` + ); + }); + + // ─── getOldestStoredRound ───────────────────────────────────────────── + it("getOldestStoredRound returns matching on-chain value", async () => { + const onChain = await api.query.Drand.OldestStoredRound.getValue(); + const fromContract = await readDrand(publicClient, "getOldestStoredRound"); + + const expected = onChain !== undefined ? BigInt(onChain as any) : BigInt(0); + assert.strictEqual(BigInt(fromContract as any), expected, "OldestStoredRound should match on-chain value"); + }); + + // ─── ordering invariant: lastRound >= oldestRound ───────────────────── + it("lastStoredRound is always >= oldestStoredRound", async () => { + const last = BigInt(await readDrand(publicClient, "getLastStoredRound") as any); + const oldest = BigInt(await readDrand(publicClient, "getOldestStoredRound") as any); + assert.ok( + last >= oldest, + `lastStoredRound (${last}) should be >= oldestStoredRound (${oldest})` + ); + }); + + // ─── getNextUnsignedAt ──────────────────────────────────────────────── + it("getNextUnsignedAt returns a matching on-chain block number", async () => { + const onChain = await api.query.Drand.NextUnsignedAt.getValue(); + const fromContract = await readDrand(publicClient, "getNextUnsignedAt"); + + const expected = onChain !== undefined ? BigInt(onChain as any) : BigInt(0); + const actual = BigInt(fromContract as any); + // Allow small drift of 20 blocks due to timing + const diff = actual > expected ? actual - expected : expected - actual; + assert.ok( + diff <= BigInt(20), + `NextUnsignedAt should closely match on-chain value (actual: ${actual}, expected: ${expected})` + ); + }); + + // ─── getHasMigrationRun — fake key ──────────────────────────────────── + it("getHasMigrationRun returns false for a non-existent migration key", async () => { + const fromContract = await readDrand( + publicClient, + "getHasMigrationRun", + ["this_migration_key_does_not_exist"] + ); + assert.strictEqual(fromContract, false, "Non-existent migration key should return false"); + }); + + // ─── getHasMigrationRun — real key ──────────────────────────────────── + it("getHasMigrationRun returns true for migrate_set_oldest_round", async () => { + const fromContract = await readDrand( + publicClient, + "getHasMigrationRun", + ["migrate_set_oldest_round"] + ); + // This migration is defined in pallets/drand/src/migrations/migrate_set_oldest_round.rs, + // but it is intentionally deferred in lib.rs (`on_runtime_upgrade`). + // Thus, it correctly returns false on devnet until uncommented. + assert.strictEqual(fromContract, false, "Migration 'migrate_set_oldest_round' is intentionally deferred on devnet"); + }); + + // ─── getBeaconConfig ────────────────────────────────────────────────── + it("getBeaconConfig returns a valid struct with non-zero genesis time", async () => { + const result = await readDrand<{ + genesisTime: number; + period: number; + publicKey: `0x${string}`; + chainHash: `0x${string}`; // bytes32 + groupHash: `0x${string}`; // bytes32 + schemeId: `0x${string}`; + beaconId: `0x${string}`; + isExplicitlyConfigured: boolean; + }>(publicClient, "getBeaconConfig"); + + assert.ok(result !== undefined, "getBeaconConfig should return a result"); + // genesisTime is uint32 (u32 on-chain) — compare as plain number, not bigint + assert.ok(result.genesisTime > 0, `genesisTime should be non-zero, got ${result.genesisTime}`); + assert.ok(result.period > 0, `period should be non-zero, got ${result.period}`); + assert.ok(result.publicKey && result.publicKey.length > 2, "publicKey should be non-empty"); + // chainHash and groupHash are bytes32 — exactly 66 hex chars (0x + 64) + assert.strictEqual(result.chainHash.length, 66, `chainHash must be 32 bytes, got ${result.chainHash}`); + assert.strictEqual(result.groupHash.length, 66, `groupHash must be 32 bytes, got ${result.groupHash}`); + assert.notStrictEqual(result.chainHash, "0x" + "00".repeat(32), "chainHash should be non-zero"); + assert.ok(result.schemeId && result.schemeId.length > 2, "schemeId should be non-empty"); + assert.ok(result.beaconId && result.beaconId.length > 2, "beaconId should be non-empty"); + assert.strictEqual(typeof result.isExplicitlyConfigured, "boolean", "isExplicitlyConfigured should be a boolean"); + // NOTE: isExplicitlyConfigured=false can only be tested on a fresh chain where + // BeaconConfig was never explicitly written. On devnet this is always true + // because the OCW sets it at genesis. For the false branch, see the Rust + // unit test in pallets/drand/src/tests.rs (try_get Err path). + }); + + // ─── getPalletVersion ───────────────────────────────────────────────── + it("getPalletVersion returns a valid version number", async () => { + const fromContract = await readDrand(publicClient, "getPalletVersion"); + assert.ok(Number(fromContract) >= 0, `Pallet version should be a non-negative number, got ${fromContract}`); + }); + + // ─── getPulse — edge case: non-existent round ───────────────────────── + it("getPulse returns empty bytes for a non-existent round (fallback path)", async () => { + const result = await readDrand<{ randomness: `0x${string}`; signature: `0x${string}` }>( + publicClient, + "getPulse", + [BigInt(999999999)] + ); + assert.ok(result !== undefined, "getPulse should return a result even for a non-existent round"); + assert.strictEqual(result.randomness, "0x" + "00".repeat(32), "randomness should be zero bytes32 for non-existent round"); + assert.strictEqual(result.signature, "0x", "signature should be empty bytes for non-existent round"); + }); + + // ─── getPulse — happy path ──────────────────────────────────────────── + it("getPulse returns non-empty randomness and signature for the last stored round", async () => { + const lastRound = await readDrand(publicClient, "getLastStoredRound"); + if (lastRound === BigInt(0)) { + // Devnet has no pulses yet — skip + console.warn(" [skip] No pulses stored yet, skipping getPulse happy-path test"); + return; + } + + const result = await readDrand<{ randomness: `0x${string}`; signature: `0x${string}` }>( + publicClient, + "getPulse", + [lastRound] + ); + + assert.ok( + result.randomness && result.randomness.length > 2, + `randomness should be non-empty for round ${lastRound}` + ); + assert.ok( + result.signature && result.signature.length > 2, + `signature should be non-empty for round ${lastRound}` + ); + }); + + // ─── getCurrentRandomness ───────────────────────────────────────────── + it("getCurrentRandomness returns bytes32 (zero when no pulses stored)", async () => { + const fromContract = await readDrand<`0x${string}`>(publicClient, "getCurrentRandomness"); + // Must be exactly 32 bytes (66 hex chars including 0x prefix) + assert.strictEqual(fromContract.length, 66, `getCurrentRandomness must return exactly 32 bytes, got ${fromContract}`); + }); + + it("getCurrentRandomness returns non-zero when pulses exist", async () => { + const lastRound = await readDrand(publicClient, "getLastStoredRound"); + if (lastRound === BigInt(0)) { + console.warn(" [skip] No pulses stored yet, skipping getCurrentRandomness non-zero test"); + return; + } + + const fromContract = await readDrand<`0x${string}`>(publicClient, "getCurrentRandomness"); + const zeroBytes32 = "0x" + "00".repeat(32); + assert.notStrictEqual( + fromContract, + zeroBytes32, + "getCurrentRandomness should not be zero when pulses are stored" + ); + }); + + // ─── getPulse — round 0 (always absent) ───────────────────────────────────────── + it("getPulse returns empty bytes for round 0", async () => { + const result = await readDrand<{ randomness: `0x${string}`; signature: `0x${string}` }>( + publicClient, + "getPulse", + [BigInt(0)] + ); + assert.strictEqual(result.randomness, "0x" + "00".repeat(32), "randomness should be zero bytes32 for round 0"); + assert.strictEqual(result.signature, "0x", "signature should be empty for round 0"); + }); + + // ─── getHasMigrationRun — key boundary tests ───────────────────────────────────── + it("getHasMigrationRun returns false for a 128-byte key (boundary)", async () => { + const result = await readDrand( + publicClient, + "getHasMigrationRun", + ["a".repeat(128)] + ); + assert.strictEqual(result, false, "Non-existent 128-byte key should return false"); + }); + + it("getHasMigrationRun reverts for a 129-byte key (exceeds MigrationKeyMaxLen)", async () => { + await assert.rejects( + readDrand(publicClient, "getHasMigrationRun", ["a".repeat(129)]), + /migration key too long|revert|execution reverted/i, + "Key longer than 128 bytes should revert" + ); + }); + }); +}); diff --git a/contract-tests/yarn.lock b/contract-tests/yarn.lock index 25300ca989..b58ea45e4e 100644 --- a/contract-tests/yarn.lock +++ b/contract-tests/yarn.lock @@ -2,16 +2,16 @@ # yarn lockfile v1 -"@adraffy/ens-normalize@^1.10.1", "@adraffy/ens-normalize@^1.11.0": - version "1.11.1" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz" - integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== - "@adraffy/ens-normalize@1.10.1": version "1.10.1" resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== +"@adraffy/ens-normalize@^1.10.1", "@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + "@babel/code-frame@^7.26.2": version "7.27.1" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" @@ -38,11 +38,136 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + "@esbuild/darwin-arm64@0.25.12": version "0.25.12" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz" integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + "@ethereumjs/rlp@^10.0.0": version "10.1.0" resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-10.1.0.tgz" @@ -78,14 +203,6 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== -"@jridgewell/trace-mapping@^0.3.24": - version "0.3.31" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" - integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" @@ -94,46 +211,19 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.31" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@noble/ciphers@^1.3.0": version "1.3.0" resolved "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz" integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== -"@noble/curves@^1.3.0", "@noble/curves@^1.6.0", "@noble/curves@~1.9.0", "@noble/curves@~1.9.2": - version "1.9.7" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz" - integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== - dependencies: - "@noble/hashes" "1.8.0" - -"@noble/curves@^2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz" - integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== - dependencies: - "@noble/hashes" "2.0.1" - -"@noble/curves@^2.0.1": - version "2.0.1" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz" - integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== - dependencies: - "@noble/hashes" "2.0.1" - -"@noble/curves@~1.8.1": - version "1.8.2" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz" - integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== - dependencies: - "@noble/hashes" "1.7.2" - -"@noble/curves@~2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz" - integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== - dependencies: - "@noble/hashes" "2.0.1" - "@noble/curves@1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" @@ -155,25 +245,26 @@ dependencies: "@noble/hashes" "1.8.0" -"@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.5.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0", "@noble/hashes@1.8.0": - version "1.8.0" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz" - integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== - -"@noble/hashes@^2.0.0", "@noble/hashes@~2.0.0", "@noble/hashes@2.0.1": - version "2.0.1" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz" - integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== +"@noble/curves@^1.3.0", "@noble/curves@^1.6.0", "@noble/curves@~1.9.0", "@noble/curves@~1.9.2": + version "1.9.7" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" -"@noble/hashes@^2.0.1", "@noble/hashes@2.0.1": +"@noble/curves@^2.0.0", "@noble/curves@^2.0.1", "@noble/curves@~2.0.0": version "2.0.1" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz" - integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + resolved "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz" + integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== + dependencies: + "@noble/hashes" "2.0.1" -"@noble/hashes@~1.7.1", "@noble/hashes@1.7.2": - version "1.7.2" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz" - integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" "@noble/hashes@1.3.2": version "1.3.2" @@ -185,6 +276,21 @@ resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz" integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.5.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@noble/hashes@2.0.1", "@noble/hashes@^2.0.0", "@noble/hashes@^2.0.1", "@noble/hashes@~2.0.0": + version "2.0.1" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz" + integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" @@ -240,10 +346,9 @@ integrity sha512-cgA9fh8dfBai9b46XaaQmj9vwzyHStQjc/xrAvQksgF6SqvZ0yAfxVqLvGrsz/Xi3dsAdKLg09PybC7MUAMv9w== "@polkadot-api/descriptors@file:.papi/descriptors": - version "0.1.0-autogenerated.14746733976505338329" - resolved "file:.papi/descriptors" + version "0.1.0-autogenerated.12867331428112102326" -"@polkadot-api/ink-contracts@^0.4.1", "@polkadot-api/ink-contracts@>=0.4.0", "@polkadot-api/ink-contracts@0.4.3": +"@polkadot-api/ink-contracts@0.4.3", "@polkadot-api/ink-contracts@^0.4.1": version "0.4.3" resolved "https://registry.npmjs.org/@polkadot-api/ink-contracts/-/ink-contracts-0.4.3.tgz" integrity sha512-Wl+4Dxjt0GAl+rADZEgrrqEesqX/xygTpX18TmzmspcKhb9QIZf9FJI8A5Sgtq0TKAOwsd1d/hbHVX3LgbXFXg== @@ -252,17 +357,17 @@ "@polkadot-api/substrate-bindings" "0.16.5" "@polkadot-api/utils" "0.2.0" -"@polkadot-api/json-rpc-provider-proxy@^0.1.0": - version "0.1.0" - resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz" - integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== - "@polkadot-api/json-rpc-provider-proxy@0.2.7": version "0.2.7" resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.7.tgz" integrity sha512-+HM4JQXzO2GPUD2++4GOLsmFL6LO8RoLvig0HgCLuypDgfdZMlwd8KnyGHjRnVEHA5X+kvXbk84TDcAXVxTazQ== -"@polkadot-api/json-rpc-provider@^0.0.1": +"@polkadot-api/json-rpc-provider-proxy@^0.1.0": + version "0.1.0" + resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz" + integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== + +"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": version "0.0.1" resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz" integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== @@ -327,15 +432,6 @@ "@polkadot-api/metadata-builders" "0.13.7" "@polkadot-api/substrate-bindings" "0.16.5" -"@polkadot-api/observable-client@^0.3.0": - version "0.3.2" - resolved "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz" - integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== - dependencies: - "@polkadot-api/metadata-builders" "0.3.2" - "@polkadot-api/substrate-bindings" "0.6.0" - "@polkadot-api/utils" "0.1.0" - "@polkadot-api/observable-client@0.17.0": version "0.17.0" resolved "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.17.0.tgz" @@ -346,6 +442,15 @@ "@polkadot-api/substrate-client" "0.4.7" "@polkadot-api/utils" "0.2.0" +"@polkadot-api/observable-client@^0.3.0": + version "0.3.2" + resolved "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz" + integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== + dependencies: + "@polkadot-api/metadata-builders" "0.3.2" + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + "@polkadot-api/pjs-signer@0.6.17": version "0.6.17" resolved "https://registry.npmjs.org/@polkadot-api/pjs-signer/-/pjs-signer-0.6.17.tgz" @@ -417,7 +522,7 @@ "@polkadot-api/json-rpc-provider" "0.0.4" "@polkadot-api/json-rpc-provider-proxy" "0.2.7" -"@polkadot-api/smoldot@>=0.3", "@polkadot-api/smoldot@0.3.14": +"@polkadot-api/smoldot@0.3.14": version "0.3.14" resolved "https://registry.npmjs.org/@polkadot-api/smoldot/-/smoldot-0.3.14.tgz" integrity sha512-eWqO0xFQaKzqY5mRYxYuZcj1IiaLcQP+J38UQyuJgEorm+9yHVEQ/XBWoM83P+Y8TwE5IWTICp1LCVeiFQTGPQ== @@ -425,7 +530,7 @@ "@types/node" "^24.5.2" smoldot "2.0.39" -"@polkadot-api/substrate-bindings@^0.16.3", "@polkadot-api/substrate-bindings@0.16.5": +"@polkadot-api/substrate-bindings@0.16.5", "@polkadot-api/substrate-bindings@^0.16.3": version "0.16.5" resolved "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.16.5.tgz" integrity sha512-QFgNlBmtLtiUGTCTurxcE6UZrbI2DaQ5/gyIiC2FYfEhStL8tl20b09FRYHcSjY+lxN42Rcf9HVX+MCFWLYlpQ== @@ -445,7 +550,7 @@ "@scure/base" "^1.1.1" scale-ts "^1.6.0" -"@polkadot-api/substrate-client@^0.1.2", "@polkadot-api/substrate-client@0.1.4", "@polkadot-api/substrate-client@0.4.7": +"@polkadot-api/substrate-client@0.4.7": version "0.4.7" resolved "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.4.7.tgz" integrity sha512-Mmx9VKincVqfVQmq89gzDk4DN3uKwf8CxoqYvq+EiPUZ1QmMUc7X4QMwG1MXIlYdnm5LSXzn+2Jn8ik8xMgL+w== @@ -454,6 +559,14 @@ "@polkadot-api/raw-client" "0.1.1" "@polkadot-api/utils" "0.2.0" +"@polkadot-api/substrate-client@^0.1.2": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz#7a808e5cb85ecb9fa2b3a43945090a6c807430ce" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + "@polkadot-api/utils@0.1.0": version "0.1.0" resolved "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz" @@ -548,7 +661,7 @@ rxjs "^7.8.1" tslib "^2.8.1" -"@polkadot/api@^16.4.6", "@polkadot/api@16.5.3": +"@polkadot/api@16.5.3", "@polkadot/api@^16.4.6": version "16.5.3" resolved "https://registry.npmjs.org/@polkadot/api/-/api-16.5.3.tgz" integrity sha512-Ptwo0f5Qonmus7KIklsbFcGTdHtNjbTAwl5GGI8Mp0dmBc7Y/ISJpIJX49UrG6FhW6COMa0ItsU87XIWMRwI/Q== @@ -580,7 +693,7 @@ "@polkadot/util-crypto" "13.5.9" tslib "^2.8.0" -"@polkadot/networks@^13.5.9", "@polkadot/networks@13.5.9": +"@polkadot/networks@13.5.9", "@polkadot/networks@^13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/networks/-/networks-13.5.9.tgz" integrity sha512-nmKUKJjiLgcih0MkdlJNMnhEYdwEml2rv/h59ll2+rAvpsVWMTLCb6Cq6q7UC44+8kiWK2UUJMkFU+3PFFxndA== @@ -703,7 +816,7 @@ rxjs "^7.8.1" tslib "^2.8.1" -"@polkadot/util-crypto@^13.5.9": +"@polkadot/util-crypto@13.5.9", "@polkadot/util-crypto@^13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.5.9.tgz" integrity sha512-foUesMhxkTk8CZ0/XEcfvHk6I0O+aICqqVJllhOpyp/ZVnrTBKBf59T6RpsXx2pCtBlMsLRvg/6Mw7RND1HqDg== @@ -736,23 +849,7 @@ "@scure/sr25519" "^0.2.0" tslib "^2.8.0" -"@polkadot/util-crypto@13.5.9": - version "13.5.9" - resolved "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.5.9.tgz" - integrity sha512-foUesMhxkTk8CZ0/XEcfvHk6I0O+aICqqVJllhOpyp/ZVnrTBKBf59T6RpsXx2pCtBlMsLRvg/6Mw7RND1HqDg== - dependencies: - "@noble/curves" "^1.3.0" - "@noble/hashes" "^1.3.3" - "@polkadot/networks" "13.5.9" - "@polkadot/util" "13.5.9" - "@polkadot/wasm-crypto" "^7.5.3" - "@polkadot/wasm-util" "^7.5.3" - "@polkadot/x-bigint" "13.5.9" - "@polkadot/x-randomvalues" "13.5.9" - "@scure/base" "^1.1.7" - tslib "^2.8.0" - -"@polkadot/util@*", "@polkadot/util@^13.5.9", "@polkadot/util@13.5.9": +"@polkadot/util@13.5.9", "@polkadot/util@^13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/util/-/util-13.5.9.tgz" integrity sha512-pIK3XYXo7DKeFRkEBNYhf3GbCHg6dKQisSvdzZwuyzA6m7YxQq4DFw4IE464ve4Z7WsJFt3a6C9uII36hl9EWw== @@ -824,14 +921,14 @@ "@polkadot/wasm-util" "7.5.3" tslib "^2.7.0" -"@polkadot/wasm-util@*", "@polkadot/wasm-util@^7.5.3", "@polkadot/wasm-util@7.5.3": +"@polkadot/wasm-util@7.5.3", "@polkadot/wasm-util@^7.5.3": version "7.5.3" resolved "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.5.3.tgz" integrity sha512-hBr9bbjS+Yr7DrDUSkIIuvlTSoAlI8WXuo9YEB4C76j130u/cl+zyq6Iy/WnaTE6QH+8i9DhM8QTety6TqYnUQ== dependencies: tslib "^2.7.0" -"@polkadot/x-bigint@^13.5.9", "@polkadot/x-bigint@13.5.9": +"@polkadot/x-bigint@13.5.9", "@polkadot/x-bigint@^13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.5.9.tgz" integrity sha512-JVW6vw3e8fkcRyN9eoc6JIl63MRxNQCP/tuLdHWZts1tcAYao0hpWUzteqJY93AgvmQ91KPsC1Kf3iuuZCi74g== @@ -856,7 +953,7 @@ node-fetch "^3.3.2" tslib "^2.8.0" -"@polkadot/x-global@^13.5.9", "@polkadot/x-global@13.5.9": +"@polkadot/x-global@13.5.9", "@polkadot/x-global@^13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.5.9.tgz" integrity sha512-zSRWvELHd3Q+bFkkI1h2cWIqLo1ETm+MxkNXLec3lB56iyq/MjWBxfXnAFFYFayvlEVneo7CLHcp+YTFd9aVSA== @@ -870,7 +967,7 @@ dependencies: tslib "^2.8.0" -"@polkadot/x-randomvalues@*", "@polkadot/x-randomvalues@13.5.9": +"@polkadot/x-randomvalues@13.5.9": version "13.5.9" resolved "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.5.9.tgz" integrity sha512-Uuuz3oubf1JCCK97fsnVUnHvk4BGp/W91mQWJlgl5TIOUSSTIRr+lb5GurCfl4kgnQq53Zi5fJV+qR9YumbnZw== @@ -927,11 +1024,116 @@ tslib "^2.8.0" ws "^8.18.0" +"@rollup/rollup-android-arm-eabi@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz#7e478b66180c5330429dd161bf84dad66b59c8eb" + integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== + +"@rollup/rollup-android-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz#2b025510c53a5e3962d3edade91fba9368c9d71c" + integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== + "@rollup/rollup-darwin-arm64@4.53.3": version "4.53.3" resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz" integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== +"@rollup/rollup-darwin-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz#2bf5f2520a1f3b551723d274b9669ba5b75ed69c" + integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== + +"@rollup/rollup-freebsd-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz#4bb9cc80252564c158efc0710153c71633f1927c" + integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== + +"@rollup/rollup-freebsd-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz#2301289094d49415a380cf942219ae9d8b127440" + integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz#1d03d776f2065e09fc141df7d143476e94acca88" + integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== + +"@rollup/rollup-linux-arm-musleabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz#8623de0e040b2fd52a541c602688228f51f96701" + integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== + +"@rollup/rollup-linux-arm64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz#ce2d1999bc166277935dde0301cde3dd0417fb6e" + integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== + +"@rollup/rollup-linux-arm64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz#88c2523778444da952651a2219026416564a4899" + integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== + +"@rollup/rollup-linux-loong64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz#578ca2220a200ac4226c536c10c8cc6e4f276714" + integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== + +"@rollup/rollup-linux-ppc64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz#aa338d3effd4168a20a5023834a74ba2c3081293" + integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== + +"@rollup/rollup-linux-riscv64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz#16ba582f9f6cff58119aa242782209b1557a1508" + integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== + +"@rollup/rollup-linux-riscv64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz#e404a77ebd6378483888b8064c703adb011340ab" + integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== + +"@rollup/rollup-linux-s390x-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz#92ad52d306227c56bec43d96ad2164495437ffe6" + integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== + +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz#fd0dea3bb9aa07e7083579f25e1c2285a46cb9fa" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + +"@rollup/rollup-linux-x64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz#37a3efb09f18d555f8afc490e1f0444885de8951" + integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== + +"@rollup/rollup-openharmony-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz#c489bec9f4f8320d42c9b324cca220c90091c1f7" + integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== + +"@rollup/rollup-win32-arm64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz#152832b5f79dc22d1606fac3db946283601b7080" + integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== + +"@rollup/rollup-win32-ia32-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz#54d91b2bb3bf3e9f30d32b72065a4e52b3a172a5" + integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== + +"@rollup/rollup-win32-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz#df9df03e61a003873efec8decd2034e7f135c71e" + integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== + +"@rollup/rollup-win32-x64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe" + integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== + "@rx-state/core@^0.1.4": version "0.1.4" resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz" @@ -947,15 +1149,6 @@ resolved "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz" integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== -"@scure/bip32@^1.5.0", "@scure/bip32@^1.7.0", "@scure/bip32@1.7.0": - version "1.7.0" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz" - integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== - dependencies: - "@noble/curves" "~1.9.0" - "@noble/hashes" "~1.8.0" - "@scure/base" "~1.2.5" - "@scure/bip32@1.6.2": version "1.6.2" resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz" @@ -965,11 +1158,12 @@ "@noble/hashes" "~1.7.1" "@scure/base" "~1.2.2" -"@scure/bip39@^1.4.0", "@scure/bip39@^1.6.0", "@scure/bip39@1.6.0": - version "1.6.0" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz" - integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== +"@scure/bip32@1.7.0", "@scure/bip32@^1.5.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== dependencies: + "@noble/curves" "~1.9.0" "@noble/hashes" "~1.8.0" "@scure/base" "~1.2.5" @@ -981,6 +1175,14 @@ "@noble/hashes" "~1.7.1" "@scure/base" "~1.2.4" +"@scure/bip39@1.6.0", "@scure/bip39@^1.4.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + "@scure/sr25519@^0.2.0": version "0.2.0" resolved "https://registry.npmjs.org/@scure/sr25519/-/sr25519-0.2.0.tgz" @@ -1102,27 +1304,20 @@ dependencies: undici-types "~6.21.0" -"@types/node@^24.10.1": - version "24.10.1" - resolved "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz" - integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== dependencies: - undici-types "~7.16.0" + undici-types "~6.19.2" -"@types/node@^24.5.2": +"@types/node@^24.10.1", "@types/node@^24.5.2": version "24.10.1" resolved "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz" integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== dependencies: undici-types "~7.16.0" -"@types/node@22.7.5": - version "22.7.5" - resolved "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz" - integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== - dependencies: - undici-types "~6.19.2" - "@types/normalize-package-data@^2.4.3", "@types/normalize-package-data@^2.4.4": version "2.4.4" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" @@ -1135,11 +1330,6 @@ dependencies: "@types/node" "*" -abitype@^1.0.6, abitype@^1.0.9, abitype@^1.1.1: - version "1.2.0" - resolved "https://registry.npmjs.org/abitype/-/abitype-1.2.0.tgz" - integrity sha512-fD3ROjckUrWsybaSor2AdWxzA0e/DSyV2dA4aYd7bd8orHsoJjl09fOgKfUkTDfk0BsDGBf4NBgu/c7JoS2Npw== - abitype@1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz" @@ -1150,6 +1340,11 @@ abitype@1.1.0: resolved "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz" integrity sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A== +abitype@^1.0.6, abitype@^1.0.9, abitype@^1.1.1: + version "1.2.0" + resolved "https://registry.npmjs.org/abitype/-/abitype-1.2.0.tgz" + integrity sha512-fD3ROjckUrWsybaSor2AdWxzA0e/DSyV2dA4aYd7bd8orHsoJjl09fOgKfUkTDfk0BsDGBf4NBgu/c7JoS2Npw== + acorn-walk@^8.1.1: version "8.3.4" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" @@ -1350,7 +1545,7 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -commander@^14.0.2, commander@~14.0.0: +commander@^14.0.2: version "14.0.2" resolved "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz" integrity sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ== @@ -1485,7 +1680,7 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: dependencies: es-errors "^1.3.0" -esbuild@^0.25.0, esbuild@>=0.18: +esbuild@^0.25.0: version "0.25.12" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz" integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== @@ -1540,7 +1735,7 @@ ethers@^6.13.5: tslib "2.7.0" ws "8.17.1" -eventemitter3@^5.0.1, eventemitter3@5.0.1: +eventemitter3@5.0.1, eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== @@ -2248,7 +2443,7 @@ picocolors@^1.1.1: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -"picomatch@^3 || ^4", picomatch@^4.0.3: +picomatch@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz" integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== @@ -2267,7 +2462,7 @@ pkg-types@^1.3.1: mlly "^1.7.4" pathe "^2.0.1" -polkadot-api@^1.22.0, polkadot-api@^1.8.1, polkadot-api@>=1.19.0, polkadot-api@>=1.21.0: +polkadot-api@^1.22.0: version "1.22.0" resolved "https://registry.npmjs.org/polkadot-api/-/polkadot-api-1.22.0.tgz" integrity sha512-uREBLroPbnJxBBQ+qSkKLF493qukX4PAg32iThlELrZdxfNNgro6nvWRdVmBv73tFHvf+nyWWHKTx1c57nbixg== @@ -2409,7 +2604,7 @@ rollup@^4.34.8: "@rollup/rollup-win32-x64-msvc" "4.53.3" fsevents "~2.3.2" -rxjs@^7.8.1, rxjs@^7.8.2, rxjs@>=7, rxjs@>=7.8.0, rxjs@>=7.8.1: +rxjs@^7.8.1, rxjs@^7.8.2: version "7.8.2" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz" integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== @@ -2476,6 +2671,13 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +smoldot@2.0.26: + version "2.0.26" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.26.tgz#0e64c7fcd26240fbe4c8d6b6e4b9a9aca77e00f6" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + smoldot@2.0.39: version "2.0.39" resolved "https://registry.npmjs.org/smoldot/-/smoldot-2.0.39.tgz" @@ -2577,14 +2779,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: - version "7.1.2" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz" - integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== - dependencies: - ansi-regex "^6.0.1" - -strip-ansi@^7.1.0, strip-ansi@^7.1.2: +strip-ansi@^7.0.1, strip-ansi@^7.1.0, strip-ansi@^7.1.2: version "7.1.2" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz" integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== @@ -2701,16 +2896,16 @@ tsc-prog@^2.3.0: resolved "https://registry.npmjs.org/tsc-prog/-/tsc-prog-2.3.0.tgz" integrity sha512-ycET2d75EgcX7y8EmG4KiZkLAwUzbY4xRhA6NU0uVbHkY4ZjrAAuzTMxXI85kOwATqPnBI5C/7y7rlpY0xdqHA== -tslib@^2.1.0, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tslib@2.7.0: version "2.7.0" resolved "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== +tslib@^2.1.0, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsup@8.5.0: version "8.5.0" resolved "https://registry.npmjs.org/tsup/-/tsup-8.5.0.tgz" @@ -2746,7 +2941,7 @@ type-fest@^5.2.0: dependencies: tagged-tag "^1.0.0" -typescript@^5.7.2, typescript@^5.9.3, typescript@>=2.7, typescript@>=4, typescript@>=4.5.0, typescript@>=5.0.4, typescript@>=5.4.0: +typescript@^5.7.2, typescript@^5.9.3: version "5.9.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== @@ -2805,20 +3000,6 @@ validate-npm-package-license@^3.0.4: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -viem@^2.37.9: - version "2.41.2" - resolved "https://registry.npmjs.org/viem/-/viem-2.41.2.tgz" - integrity sha512-LYliajglBe1FU6+EH9mSWozp+gRA/QcHfxeD9Odf83AdH5fwUS7DroH4gHvlv6Sshqi1uXrYFA2B/EOczxd15g== - dependencies: - "@noble/curves" "1.9.1" - "@noble/hashes" "1.8.0" - "@scure/bip32" "1.7.0" - "@scure/bip39" "1.6.0" - abitype "1.1.0" - isows "1.0.7" - ox "0.9.6" - ws "8.18.3" - viem@2.23.4: version "2.23.4" resolved "https://registry.npmjs.org/viem/-/viem-2.23.4.tgz" @@ -2833,6 +3014,20 @@ viem@2.23.4: ox "0.6.7" ws "8.18.0" +viem@^2.37.9: + version "2.41.2" + resolved "https://registry.npmjs.org/viem/-/viem-2.41.2.tgz" + integrity sha512-LYliajglBe1FU6+EH9mSWozp+gRA/QcHfxeD9Odf83AdH5fwUS7DroH4gHvlv6Sshqi1uXrYFA2B/EOczxd15g== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.1.0" + isows "1.0.7" + ox "0.9.6" + ws "8.18.3" + web-streams-polyfill@^3.0.3: version "3.3.3" resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz" @@ -2933,11 +3128,6 @@ write-package@^7.2.0: type-fest "^4.23.0" write-json-file "^6.0.0" -ws@*, ws@^8.18.0, ws@^8.18.2, ws@^8.18.3, ws@^8.8.1, ws@8.18.3: - version "8.18.3" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz" - integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== - ws@8.17.1: version "8.17.1" resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" @@ -2948,6 +3138,11 @@ ws@8.18.0: resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== +ws@8.18.3, ws@^8.18.0, ws@^8.18.2, ws@^8.18.3, ws@^8.8.1: + version "8.18.3" + resolved "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 4143e3fb3a..4bbc345d6e 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -145,6 +145,8 @@ pub mod pallet { Leasing, /// Address mapping precompile AddressMapping, + /// Drand precompile + Drand, } #[pallet::type_value] diff --git a/pallets/drand/src/lib.rs b/pallets/drand/src/lib.rs index 8666781e56..e06b98bac3 100644 --- a/pallets/drand/src/lib.rs +++ b/pallets/drand/src/lib.rs @@ -214,8 +214,8 @@ pub mod pallet { } } - /// Define a maximum length for the migration key - type MigrationKeyMaxLen = ConstU32<128>; + /// Define a maximum length for the migration key + pub type MigrationKeyMaxLen = ConstU32<128>; /// Storage for migration run status #[pallet::storage] @@ -239,7 +239,7 @@ pub mod pallet { /// we only allow one transaction per block. /// This storage entry defines when new transaction is going to be accepted. #[pallet::storage] - pub(super) type NextUnsignedAt = StorageValue<_, BlockNumberFor, ValueQuery>; + pub type NextUnsignedAt = StorageValue<_, BlockNumberFor, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -277,12 +277,10 @@ pub mod pallet { } } fn on_runtime_upgrade() -> frame_support::weights::Weight { - /*let weight = */ - frame_support::weights::Weight::from_parts(0, 0) /*;*/ - - //weight = weight.saturating_add(migrations::migrate_set_oldest_round::()); - - //weight + // NOTE: migrations::migrate_set_oldest_round is defined but intentionally not + // triggered here until the runtime upgrade is scheduled. Uncomment and hook it + // in when the migration is ready to ship. + frame_support::weights::Weight::from_parts(0, 0) } } diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml index 400e1caa9f..0dd408d9e7 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -38,6 +38,7 @@ pallet-subtensor-swap.workspace = true pallet-admin-utils.workspace = true subtensor-swap-interface.workspace = true pallet-crowdloan.workspace = true +pallet-drand.workspace = true [lints] workspace = true @@ -54,6 +55,7 @@ std = [ "pallet-admin-utils/std", "pallet-balances/std", "pallet-crowdloan/std", + "pallet-drand/std", "pallet-evm-precompile-bn128/std", "pallet-evm-precompile-dispatch/std", "pallet-evm-precompile-modexp/std", diff --git a/precompiles/src/drand.rs b/precompiles/src/drand.rs new file mode 100644 index 0000000000..c07c41fc44 --- /dev/null +++ b/precompiles/src/drand.rs @@ -0,0 +1,205 @@ +use alloc::string::String; +use core::marker::PhantomData; + +use pallet_drand::pallet::MigrationKeyMaxLen; +use pallet_evm::PrecompileHandle; +use precompile_utils::{EvmResult, prelude::UnboundedBytes, solidity::Codec}; +use sp_core::H256; +use sp_runtime::{BoundedVec, traits::SaturatedConversion}; +use sp_std::vec::Vec; + +use fp_evm::PrecompileFailure; +use precompile_utils::prelude::PrecompileHandleExt; + +use crate::{PrecompileExt, PrecompileHandleExtStorage}; + +/// Returned by `getPulse` — matches the `DrandPulse` Solidity struct. +#[derive(Codec)] +struct DrandPulse { + randomness: H256, + signature: UnboundedBytes, +} + +/// Returned by `getBeaconConfig` — matches the `BeaconConfig` Solidity struct. +/// Maps the full on-chain `BeaconConfiguration` struct: +/// public_key (96 bytes) → publicKey (bytes) — no bytes96 in Solidity +/// period → period (uint32) +/// genesis_time → genesisTime(uint32) +/// hash (exactly 32 bytes) → chainHash (bytes32) — fixed-size H256 +/// group_hash (32 bytes) → groupHash (bytes32) — fixed-size H256 +/// scheme_id (≤32 bytes) → schemeId (bytes) — UTF-8 string bytes +/// metadata.beacon_id → beaconId (bytes) — UTF-8 string bytes +/// is_explicitly_configured is synthetic: true iff the storage key was explicitly written. +#[derive(Codec)] +struct BeaconConfig { + genesis_time: u32, + period: u32, + public_key: UnboundedBytes, + chain_hash: H256, // BoundedHash = BoundedVec> → always 32 bytes + group_hash: H256, // same + scheme_id: UnboundedBytes, // UTF-8 string bytes, variable ≤32 + beacon_id: UnboundedBytes, // UTF-8 string bytes, variable ≤32 + is_explicitly_configured: bool, +} + +pub(crate) struct DrandPrecompile(PhantomData); + +impl PrecompileExt for DrandPrecompile +where + R: frame_system::Config + pallet_drand::Config + pallet_evm::Config, + R::AccountId: From<[u8; 32]>, +{ + const INDEX: u64 = 2065; +} + +#[precompile_utils::precompile] +impl DrandPrecompile +where + R: frame_system::Config + pallet_drand::Config + pallet_evm::Config, +{ + /// Returns the last stored drand round number. + #[precompile::public("getLastStoredRound()")] + #[precompile::view] + fn get_last_stored_round(handle: &mut impl PrecompileHandle) -> EvmResult { + let val = pallet_drand::LastStoredRound::::get(); + handle.record_db_read_encoded::(&val)?; + Ok(val) + } + + /// Returns the oldest stored drand round number. + #[precompile::public("getOldestStoredRound()")] + #[precompile::view] + fn get_oldest_stored_round(handle: &mut impl PrecompileHandle) -> EvmResult { + let val = pallet_drand::OldestStoredRound::::get(); + handle.record_db_read_encoded::(&val)?; + Ok(val) + } + + /// Returns the pulse (randomness, signature) for a specific round. + /// Returns empty bytes for both fields if the round is not found. + #[precompile::public("getPulse(uint64)")] + #[precompile::view] + fn get_pulse( + handle: &mut impl PrecompileHandle, + round: u64, + ) -> EvmResult { + let pulse_opt = pallet_drand::Pulses::::get(round); + handle.record_db_read_encoded::(&pulse_opt)?; + match pulse_opt { + Some(pulse) => { + let rand = pulse.randomness.into_inner(); + let bounded: [u8; 32] = rand.try_into().unwrap_or([0u8; 32]); + Ok(DrandPulse { + randomness: H256::from(bounded), + signature: pulse.signature.into_inner().into(), + }) + } + None => Ok(DrandPulse { + randomness: H256::zero(), + signature: UnboundedBytes::from(&b""[..]), + }), + } + } + + /// Returns the randomness from the latest stored round as bytes32. + /// Returns zero bytes if no pulse is stored. + #[precompile::public("getCurrentRandomness()")] + #[precompile::view] + fn get_current_randomness(handle: &mut impl PrecompileHandle) -> EvmResult { + let last_round = pallet_drand::LastStoredRound::::get(); + handle.record_db_read_encoded::(&last_round)?; + let pulse_opt = pallet_drand::Pulses::::get(last_round); + handle.record_db_read_encoded::(&pulse_opt)?; + match pulse_opt { + Some(pulse) => { + let rand = pulse.randomness.into_inner(); + let bounded: [u8; 32] = rand.try_into().unwrap_or([0u8; 32]); + Ok(H256::from(bounded)) + } + None => Ok(H256::zero()), + } + } + + /// Returns the drand beacon configuration. + /// + /// Exposes all fields of the on-chain `BeaconConfiguration` struct. + /// `isExplicitlyConfigured` is `false` when the storage key has never been written — + /// in that case the pallet operates with the hardcoded Quicknet default, not an + /// unconfigured state. An off-chain caller seeing `false` should treat the returned + /// values as the Quicknet defaults rather than "no config". + #[precompile::public("getBeaconConfig()")] + #[precompile::view] + fn get_beacon_config( + handle: &mut impl PrecompileHandle, + ) -> EvmResult { + // try_get returns Err(()) when the key is absent; .get() would return the + // DefaultBeaconConfig hook value, hiding whether it was explicitly set. + let is_explicit = pallet_drand::BeaconConfig::::try_get().is_ok(); + let config = pallet_drand::BeaconConfig::::get(); + + if is_explicit { + // DB hit: charge for the actual bytes read. + handle.record_db_read_encoded::(&config)?; + } else { + // DB miss: charge the 1-byte minimum — nothing was read from storage. + PrecompileHandleExt::record_db_read::(handle, 1) + .map_err(|e| PrecompileFailure::Error { exit_status: e })?; + } + + Ok(BeaconConfig { + genesis_time: config.genesis_time, + period: config.period, + public_key: config.public_key.into_inner().into(), + chain_hash: { + let v = config.hash.into_inner(); + let arr: [u8; 32] = v.try_into().unwrap_or([0u8; 32]); + H256::from(arr) + }, + group_hash: { + let v = config.group_hash.into_inner(); + let arr: [u8; 32] = v.try_into().unwrap_or([0u8; 32]); + H256::from(arr) + }, + scheme_id: config.scheme_id.into_inner().into(), + beacon_id: config.metadata.beacon_id.into_inner().into(), + is_explicitly_configured: is_explicit, + }) + } + + /// Returns whether a specific migration has run. + /// migrationName must match the key stored on-chain exactly (e.g. "migrate_set_oldest_round"). + #[precompile::public("getHasMigrationRun(string)")] + #[precompile::view] + fn get_has_migration_run( + handle: &mut impl PrecompileHandle, + migration_name: UnboundedBytes, + ) -> EvmResult { + let raw: Vec = migration_name.into(); + // Use the pallet's own MigrationKeyMaxLen so the limit here is always + // in sync with the storage definition — no magic constant duplication. + let bounded_key: BoundedVec = BoundedVec::try_from(raw) + .map_err(|_| precompile_utils::prelude::revert("migration key too long"))?; + let val = pallet_drand::HasMigrationRun::::get(&bounded_key); + handle.record_db_read_encoded::(&val)?; + Ok(val) + } + + /// Returns the block number when the next unsigned transaction will be accepted. + #[precompile::public("getNextUnsignedAt()")] + #[precompile::view] + fn get_next_unsigned_at(handle: &mut impl PrecompileHandle) -> EvmResult { + let val = pallet_drand::NextUnsignedAt::::get(); + handle.record_db_read_encoded::(&val)?; + Ok(val.saturated_into::()) + } + + /// Returns the current pallet version from storage. + #[precompile::public("getPalletVersion()")] + #[precompile::view] + fn get_pallet_version(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok( + as frame_support::traits::PalletInfoAccess>::crate_version() + .major as u16, + ) + } +} \ No newline at end of file diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 864119d89f..0a61dd7e19 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -30,6 +30,7 @@ use crate::address_mapping::*; use crate::alpha::*; use crate::balance_transfer::*; use crate::crowdloan::*; +use crate::drand::*; use crate::ed25519::*; use crate::extensions::*; use crate::leasing::*; @@ -46,6 +47,7 @@ mod address_mapping; mod alpha; mod balance_transfer; mod crowdloan; +mod drand; mod ed25519; mod extensions; mod leasing; @@ -70,6 +72,7 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + Send + Sync + scale_info::TypeInfo, @@ -103,6 +106,7 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + Send + Sync + scale_info::TypeInfo, @@ -125,7 +129,7 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 26] { + pub fn used_addresses() -> [H160; 27] { [ hash(1), hash(2), @@ -153,6 +157,7 @@ where hash(LeasingPrecompile::::INDEX), hash(ProxyPrecompile::::INDEX), hash(AddressMappingPrecompile::::INDEX), + hash(DrandPrecompile::::INDEX), ] } } @@ -166,6 +171,7 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + Send + Sync + scale_info::TypeInfo, @@ -254,6 +260,9 @@ where PrecompileEnum::AddressMapping, ) } + a if a == hash(DrandPrecompile::::INDEX) => { + DrandPrecompile::::try_execute::(handle, PrecompileEnum::Drand) + } _ => None, } } @@ -291,3 +300,34 @@ fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileF }) } } + +/// General-purpose extension for recording DB-read gas costs based on SCALE-encoded value size. +/// +/// This trait is implemented for all `PrecompileHandle` types and is available to every +/// precompile in this crate. It complements `PrecompileHandleExt::record_db_read`, which +/// requires the caller to supply the byte size manually, by computing it automatically from +/// the SCALE-encoded representation of the value just read from storage. +/// +/// # Minimum cost +/// A 1-byte minimum is enforced on every call so that a DB miss (where the value encodes +/// to zero bytes) still incurs a measurable gas cost and cannot be used to spam free reads. +pub trait PrecompileHandleExtStorage { + /// Records the DB-read cost proportional to the SCALE-encoded size of `value`. + /// The minimum charged size is 1 byte (see above). + fn record_db_read_encoded( + &mut self, + value: &impl frame_support::pallet_prelude::Encode, + ) -> Result<(), PrecompileFailure>; +} + +impl PrecompileHandleExtStorage for T { + fn record_db_read_encoded( + &mut self, + value: &impl frame_support::pallet_prelude::Encode, + ) -> Result<(), PrecompileFailure> { + let size = value.encoded_size(); + let cost = if size > 0 { size } else { 1 }; + precompile_utils::prelude::PrecompileHandleExt::record_db_read::(self, cost) + .map_err(|e| PrecompileFailure::Error { exit_status: e }) + } +} diff --git a/precompiles/src/solidity/drand.abi b/precompiles/src/solidity/drand.abi new file mode 100644 index 0000000000..c896fb231a --- /dev/null +++ b/precompiles/src/solidity/drand.abi @@ -0,0 +1,100 @@ +[ + { + "type": "function", + "name": "getLastStoredRound", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint64", "internalType": "uint64" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getOldestStoredRound", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint64", "internalType": "uint64" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPulse", + "inputs": [ + { "name": "round", "type": "uint64", "internalType": "uint64" } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct IDrand.DrandPulse", + "components": [ + { "name": "randomness", "type": "bytes32", "internalType": "bytes32" }, + { "name": "signature", "type": "bytes", "internalType": "bytes" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCurrentRandomness", + "inputs": [], + "outputs": [ + { "name": "", "type": "bytes32", "internalType": "bytes32" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getBeaconConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct IDrand.BeaconConfig", + "components": [ + { "name": "genesisTime", "type": "uint32", "internalType": "uint32" }, + { "name": "period", "type": "uint32", "internalType": "uint32" }, + { "name": "publicKey", "type": "bytes", "internalType": "bytes" }, + { "name": "chainHash", "type": "bytes32", "internalType": "bytes32" }, + { "name": "groupHash", "type": "bytes32", "internalType": "bytes32" }, + { "name": "schemeId", "type": "bytes", "internalType": "bytes" }, + { "name": "beaconId", "type": "bytes", "internalType": "bytes" }, + { "name": "isExplicitlyConfigured", "type": "bool", "internalType": "bool" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getHasMigrationRun", + "inputs": [ + { "name": "migrationName", "type": "string", "internalType": "string" } + ], + "outputs": [ + { "name": "", "type": "bool", "internalType": "bool" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getNextUnsignedAt", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint64", "internalType": "uint64" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPalletVersion", + "inputs": [], + "outputs": [ + { "name": "", "type": "uint16", "internalType": "uint16" } + ], + "stateMutability": "view" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/drand.sol b/precompiles/src/solidity/drand.sol new file mode 100644 index 0000000000..dc47cd74a8 --- /dev/null +++ b/precompiles/src/solidity/drand.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +address constant IDRAND_ADDRESS = 0x0000000000000000000000000000000000000811; + +/** + * @title IDrand + * @dev Precompile at 0x811 providing typed views into drand randomness beacon storage. + */ +interface IDrand { + /// @dev Randomness beacon pulse data for a given round. + struct DrandPulse { + bytes32 randomness; + bytes signature; + } + + /// @dev Drand beacon configuration. + /// Mirrors the full on-chain `BeaconConfiguration` storage struct. + /// `isExplicitlyConfigured` is `false` when the beacon storage key has never been + /// explicitly written; the pallet then operates with its hardcoded Quicknet default + /// (i.e. the other fields still contain valid Quicknet values, not zeroes). + struct BeaconConfig { + uint32 genesisTime; + uint32 period; + bytes publicKey; // 96-byte G2 public key (no bytes96 in Solidity) + bytes32 chainHash; // 32-byte chain hash + bytes32 groupHash; // 32-byte group hash + bytes schemeId; // scheme identifier, UTF-8 string bytes (e.g. "bls-unchained-g1-rfc9380") + bytes beaconId; // beacon identifier, UTF-8 string bytes (e.g. "quicknet") + bool isExplicitlyConfigured; + } + + /// @dev Returns the last stored drand round number. + function getLastStoredRound() external view returns (uint64); + + /// @dev Returns the oldest stored drand round number. + function getOldestStoredRound() external view returns (uint64); + + /// @dev Returns the pulse (randomness, signature) for a specific round. + /// Returns empty bytes for both fields if the round is not found. + /// @param round The drand round number. + function getPulse(uint64 round) external view returns (DrandPulse memory); + + /// @dev Returns the randomness from the latest stored round as bytes32. + /// Returns zero bytes32 if no pulse is stored. + function getCurrentRandomness() external view returns (bytes32); + + /// @dev Returns the drand beacon configuration. + /// isConfigured is false when the beacon has never been explicitly set. + function getBeaconConfig() external view returns (BeaconConfig memory); + + /// @dev Returns whether a specific migration has run. + /// @param migrationName The migration key exactly as stored on-chain (e.g. "migrate_set_oldest_round"). + function getHasMigrationRun(string memory migrationName) external view returns (bool); + + /// @dev Returns the block number at which the next unsigned transaction will be accepted. + function getNextUnsignedAt() external view returns (uint64); + + /// @dev Returns the current pallet version (major version number). + function getPalletVersion() external view returns (uint16); +}