Skip to content

Commit 4620c69

Browse files
committed
refactor(stdlib): consolidate find-function-by-selector helpers
The same artifact lookup loop was duplicated three times — as ContractStore's private #findFunctionArtifactBySelector and #findFunctionAbiBySelector, and as a local helper inside ProxiedContractStoreFactory. Hoist the two variants into stdlib/abi as findFunctionArtifactBySelector and findFunctionAbiBySelector so both ContractStore and the proxied store call the same primitive. Also have the existing throwing getFunctionArtifact helper reuse findFunctionArtifactBySelector for its selector branch.
1 parent 97f955a commit 4620c69

3 files changed

Lines changed: 52 additions & 61 deletions

File tree

yarn-project/pxe/src/contract_function_simulator/proxied_contract_data_source.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FunctionSelector } from '@aztec/stdlib/abi';
1+
import { type FunctionSelector, findFunctionArtifactBySelector } from '@aztec/stdlib/abi';
22
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
33
import type { ContractOverrides } from '@aztec/stdlib/tx';
44

@@ -22,22 +22,6 @@ export class ProxiedContractStoreFactory {
2222
return contractStore;
2323
}
2424

25-
const findFunctionInArtifact = async (
26-
artifact: { name: string; functions: { name: string; parameters: any[] }[] },
27-
selector: FunctionSelector,
28-
contractAddress: AztecAddress,
29-
) => {
30-
for (const fn of artifact.functions) {
31-
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
32-
if (fnSelector.equals(selector)) {
33-
return { ...fn, contractName: artifact.name } as any;
34-
}
35-
}
36-
throw new Error(
37-
`Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}.`,
38-
);
39-
};
40-
4125
return new Proxy(contractStore, {
4226
get(target, prop: keyof ContractStore) {
4327
if (prop === 'getContractInstance') {
@@ -59,7 +43,13 @@ export class ProxiedContractStoreFactory {
5943
`at ${contractAddress}. Register it via pxe.registerContractClass(...) before simulating.`,
6044
);
6145
}
62-
return findFunctionInArtifact(artifact, selector, contractAddress);
46+
const fn = await findFunctionArtifactBySelector(artifact, selector);
47+
if (!fn) {
48+
throw new Error(
49+
`Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}.`,
50+
);
51+
}
52+
return { ...fn, contractName: artifact.name };
6353
};
6454
}
6555
const value = Reflect.get(target, prop);

yarn-project/pxe/src/storage/contract_store/contract_store.ts

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
77
import {
88
type ContractArtifact,
99
type FunctionAbi,
10-
type FunctionArtifact,
1110
type FunctionArtifactWithContractName,
1211
FunctionCall,
1312
type FunctionDebugMetadata,
@@ -16,6 +15,8 @@ import {
1615
contractArtifactFromBuffer,
1716
contractArtifactToBuffer,
1817
encodeArguments,
18+
findFunctionAbiBySelector,
19+
findFunctionArtifactBySelector,
1920
getFunctionDebugMetadata,
2021
} from '@aztec/stdlib/abi';
2122
import { AztecAddress } from '@aztec/stdlib/aztec-address';
@@ -290,7 +291,7 @@ export class ContractStore {
290291
if (!artifact) {
291292
return undefined;
292293
}
293-
const fn = await this.#findFunctionArtifactBySelector(artifact, selector);
294+
const fn = await findFunctionArtifactBySelector(artifact, selector);
294295
return fn && { ...fn, contractName: artifact.name };
295296
}
296297

@@ -322,7 +323,7 @@ export class ContractStore {
322323
selector: FunctionSelector,
323324
): Promise<FunctionAbi | undefined> {
324325
const artifact = await this.#getArtifactByAddress(contractAddress);
325-
return artifact && (await this.#findFunctionAbiBySelector(artifact, selector));
326+
return artifact && (await findFunctionAbiBySelector(artifact, selector));
326327
}
327328

328329
/**
@@ -340,7 +341,7 @@ export class ContractStore {
340341
if (!artifact) {
341342
return undefined;
342343
}
343-
const fn = await this.#findFunctionArtifactBySelector(artifact, selector);
344+
const fn = await findFunctionArtifactBySelector(artifact, selector);
344345
return fn && getFunctionDebugMetadata(artifact, fn);
345346
}
346347

@@ -374,34 +375,10 @@ export class ContractStore {
374375

375376
public async getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector) {
376377
const artifact = await this.#getArtifactByAddress(contractAddress);
377-
const fn = artifact && (await this.#findFunctionAbiBySelector(artifact, selector));
378+
const fn = artifact && (await findFunctionAbiBySelector(artifact, selector));
378379
return `${artifact?.name ?? contractAddress}:${fn?.name ?? selector}`;
379380
}
380381

381-
async #findFunctionArtifactBySelector(
382-
artifact: ContractArtifact,
383-
selector: FunctionSelector,
384-
): Promise<FunctionArtifact | undefined> {
385-
for (const fn of artifact.functions) {
386-
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
387-
if (fnSelector.equals(selector)) {
388-
return fn;
389-
}
390-
}
391-
}
392-
393-
async #findFunctionAbiBySelector(
394-
artifact: ContractArtifact,
395-
selector: FunctionSelector,
396-
): Promise<FunctionAbi | undefined> {
397-
for (const fn of [...artifact.functions, ...(artifact.nonDispatchPublicFunctions ?? [])]) {
398-
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
399-
if (fnSelector.equals(selector)) {
400-
return fn;
401-
}
402-
}
403-
}
404-
405382
public async getFunctionCall(functionName: string, args: any[], to: AztecAddress): Promise<FunctionCall> {
406383
const contract = await this.getContract(to);
407384
if (!contract) {

yarn-project/stdlib/src/abi/abi.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -418,20 +418,10 @@ export async function getFunctionArtifact(
418418
artifact: ContractArtifact,
419419
functionNameOrSelector: string | FunctionSelector,
420420
): Promise<FunctionArtifactWithContractName> {
421-
let functionArtifact;
422-
if (typeof functionNameOrSelector === 'string') {
423-
functionArtifact = artifact.functions.find(f => f.name === functionNameOrSelector);
424-
} else {
425-
const functionsAndSelectors = await Promise.all(
426-
artifact.functions.map(async fn => ({
427-
fn,
428-
selector: await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters),
429-
})),
430-
);
431-
functionArtifact = functionsAndSelectors.find(fnAndSelector =>
432-
functionNameOrSelector.equals(fnAndSelector.selector),
433-
)?.fn;
434-
}
421+
const functionArtifact =
422+
typeof functionNameOrSelector === 'string'
423+
? artifact.functions.find(f => f.name === functionNameOrSelector)
424+
: await findFunctionArtifactBySelector(artifact, functionNameOrSelector);
435425
if (!functionArtifact) {
436426
throw new Error(`Unknown function ${functionNameOrSelector}`);
437427
}
@@ -441,6 +431,40 @@ export async function getFunctionArtifact(
441431
return { ...functionArtifact, debug: debugMetadata, contractName: artifact.name };
442432
}
443433

434+
/**
435+
* Finds the function artifact within `artifact.functions` whose selector matches `selector`.
436+
* Returns `undefined` if no match is found.
437+
*/
438+
export async function findFunctionArtifactBySelector(
439+
artifact: ContractArtifact,
440+
selector: FunctionSelector,
441+
): Promise<FunctionArtifact | undefined> {
442+
for (const fn of artifact.functions) {
443+
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
444+
if (fnSelector.equals(selector)) {
445+
return fn;
446+
}
447+
}
448+
return undefined;
449+
}
450+
451+
/**
452+
* Finds the function abi (across both `functions` and `nonDispatchPublicFunctions`) whose selector
453+
* matches `selector`. Returns `undefined` if no match is found.
454+
*/
455+
export async function findFunctionAbiBySelector(
456+
artifact: ContractArtifact,
457+
selector: FunctionSelector,
458+
): Promise<FunctionAbi | undefined> {
459+
for (const fn of getAllFunctionAbis(artifact)) {
460+
const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
461+
if (fnSelector.equals(selector)) {
462+
return fn;
463+
}
464+
}
465+
return undefined;
466+
}
467+
444468
/** Gets all function abis */
445469
export function getAllFunctionAbis(artifact: ContractArtifact): FunctionAbi[] {
446470
return artifact.functions.map(f => f as FunctionAbi).concat(artifact.nonDispatchPublicFunctions || []);

0 commit comments

Comments
 (0)