Skip to content

Commit fc5bdeb

Browse files
committed
Use dryRunExtrinsicsAmortized for proxy call-filtering loop
Replaces the sendTransaction + newBlock per-proxy-action loop with a single dryRunExtrinsicsAmortized batch. Pre-signs every action with the proxy account's current nonce (storage layer pops between extrinsics revert nonce, so sequential nonces would be rejected). Adds eventsFromAmortizedDryRunResult helper that decodes the system events Vec from a per-extrinsic storageDiff and returns a { events: Promise<Codec[]> } shape compatible with checkEvents. Verified locally on Polkadot proxy filtering tests (16 of 16 pass, including AssetHub, BridgeHub, Coretime, People, Collectives, Polkadot itself).
1 parent 4d8f8f3 commit fc5bdeb

2 files changed

Lines changed: 47 additions & 10 deletions

File tree

packages/shared/src/helpers/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,3 +780,22 @@ export async function testCallsViaForceBatch(
780780
}
781781
}
782782
}
783+
784+
/**
785+
* Decode the `system.events` value from a `dryRunExtrinsicsAmortized` storageDiff.
786+
*
787+
* Returns an object shaped like the one `sendTransaction` returns (`{ events: Promise<Codec[]> }`)
788+
* so it can be passed straight to `checkEvents`.
789+
*/
790+
export function eventsFromAmortizedDryRunResult(
791+
api: ApiPromise,
792+
storageDiff: [HexString, HexString | null][],
793+
): { events: Promise<EventRecord[]> } {
794+
const eventsKey = api.query.system.events.key()
795+
const entry = storageDiff.find(([k]) => k.toLowerCase() === eventsKey.toLowerCase())
796+
const decoded =
797+
entry && entry[1] !== null
798+
? (api.createType('Vec<FrameSystemEventRecord>', entry[1]) as unknown as EventRecord[])
799+
: []
800+
return { events: Promise.resolve(decoded) }
801+
}

packages/shared/src/proxy.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@ import type { KeyringPair } from '@polkadot/keyring/types'
1616
import type { Vec } from '@polkadot/types'
1717
import type { PalletProxyProxyDefinition } from '@polkadot/types/lookup'
1818
import type { ISubmittableResult } from '@polkadot/types/types'
19+
import type { HexString } from '@polkadot/util/types'
1920
import { encodeAddress } from '@polkadot/util-crypto'
2021

2122
import { assert, expect } from 'vitest'
2223

2324
import BN from 'bn.js'
24-
import { blockProviderOffset, check, checkEvents, getBlockNumber, type TestConfig } from './helpers/index.js'
25+
import {
26+
blockProviderOffset,
27+
check,
28+
checkEvents,
29+
eventsFromAmortizedDryRunResult,
30+
getBlockNumber,
31+
type TestConfig,
32+
} from './helpers/index.js'
2533

2634
/// -------
2735
/// Helpers
@@ -1244,17 +1252,27 @@ async function proxyCallFilteringSingleTestRunner<
12441252
},
12451253
})
12461254

1247-
// Execute each proxy action in its own block and check its results immediately
1248-
for (const proxyAction of proxyActions) {
1249-
// Execute the proxy action
1250-
const proxyTx = client.api.tx.proxy.proxy(alice.address, proxyTypeIx, proxyAction.call)
1251-
const result = await sendTransaction(proxyTx.signAsync(proxyAccount))
1255+
// Pre-sign each proxy action with the same base nonce. dryRunExtrinsicsAmortized pops
1256+
// the storage layer after each extrinsic, so account state (including nonce) reverts;
1257+
// sequential nonces would be rejected.
1258+
const proxyAccountInfo = await client.api.query.system.account(proxyAccount.address)
1259+
const baseNonce = proxyAccountInfo.nonce.toNumber()
1260+
1261+
const signedExtrinsics = await Promise.all(
1262+
proxyActions.map((proxyAction) =>
1263+
client.api.tx.proxy
1264+
.proxy(alice.address, proxyTypeIx, proxyAction.call)
1265+
.signAsync(proxyAccount, { nonce: baseNonce })
1266+
.then((signed) => signed.toHex() as HexString),
1267+
),
1268+
)
12521269

1253-
// Advance to the next block to ensure events are processed
1254-
await client.dev.newBlock()
1270+
const dryRunResults = await client.chain.dryRunExtrinsicsAmortized(signedExtrinsics)
12551271

1256-
// Check the events for this specific call
1257-
const events = await client.api.query.system.events()
1272+
for (let i = 0; i < proxyActions.length; i++) {
1273+
const proxyAction = proxyActions[i]
1274+
const result = eventsFromAmortizedDryRunResult(client.api, dryRunResults[i].storageDiff)
1275+
const events = await result.events
12581276
const proxyExecutedEvents = events.filter((record) => {
12591277
const { event } = record
12601278
return event.section === 'proxy' && event.method === 'ProxyExecuted'

0 commit comments

Comments
 (0)