Skip to content

Commit 715447e

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).
1 parent 4d8f8f3 commit 715447e

2 files changed

Lines changed: 45 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: 26 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,25 @@ 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+
// Same base nonce for every action: dryRunExtrinsicsAmortized rolls back nonce per call.
1256+
const proxyAccountInfo = await client.api.query.system.account(proxyAccount.address)
1257+
const baseNonce = proxyAccountInfo.nonce.toNumber()
1258+
1259+
const signedExtrinsics = await Promise.all(
1260+
proxyActions.map((proxyAction) =>
1261+
client.api.tx.proxy
1262+
.proxy(alice.address, proxyTypeIx, proxyAction.call)
1263+
.signAsync(proxyAccount, { nonce: baseNonce })
1264+
.then((signed) => signed.toHex() as HexString),
1265+
),
1266+
)
12521267

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

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

0 commit comments

Comments
 (0)