Skip to content
This repository was archived by the owner on Jul 10, 2026. It is now read-only.

feat: add benchmarks - #360

Merged
0xLeopoldo merged 1 commit into
feat/1155from
feat/1155-benchmarks
Jul 7, 2026
Merged

feat: add benchmarks#360
0xLeopoldo merged 1 commit into
feat/1155from
feat/1155-benchmarks

Conversation

@0xLeopoldo

Copy link
Copy Markdown
Contributor

🤖 Linear

Closes AZT-XXX

Description

add benchmarks

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add MultiToken contract benchmark with supporting deploy/event test utilities

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Register a new MultiToken benchmark entry in the workspace benchmark manifest.
• Add a MultiToken benchmark covering mint/transfer/burn and commitment flows.
• Extend test utilities with MultiToken deploy, commitment initialization, and event decoding
 helpers.
Diagram

graph TD
  A["Nargo.toml"] --> B(["Benchmark runner"]) --> C["MultiToken benchmark"] --> D["MultiToken utils"] --> E["MultiToken artifact"] --> F{{"Aztec wallet / PXE node"}}
  subgraph Legend
    direction LR
    _cfg["Config file"] ~~~ _mod["TS module"] ~~~ _ext{{"External runtime"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Avoid wallet-internals by using simulate()+send() APIs
  • ➕ Reduces coupling to WalletWithInternals/privateExecutionResult shapes
  • ➕ Less brittle across Aztec SDK upgrades
  • ➖ May not currently expose the partial-note commitment return value needed for commitment-based benchmarks
  • ➖ Could require changes in benchmark workflow or waiting for SDK support
2. Derive commitments via contract-level observable output
  • ➕ Eliminates dependency on private execution result internals
  • ➖ Would require contract changes (e.g., emitting commitments) that may be undesirable for privacy/semantics
  • ➖ Broadens PR scope beyond benchmarks/utilities

Recommendation: Current approach is reasonable for benchmarking today because commitment values are required and (per TODO) the public APIs may not expose them yet. Keep the internals-based helper tightly scoped (as done), and consider migrating to simulate()+send() once the SDK provides a supported way to obtain private return values.

Files changed (3) +316 / -0

Enhancement (2) +315 / -0
multitoken_contract.benchmark.tsAdd MultiToken contract benchmark suite +134/-0

Add MultiToken contract benchmark suite

• Introduces a 'Benchmark' implementation that deploys a MultiToken contract, pre-initializes transfer commitments, and benchmarks core methods (mint, transfers across privacy domains, burns, and commitment-based transfers). Uses raw u128-style amounts consistent with MultiToken's no-decimals design.

benchmarks/multitoken_contract.benchmark.ts

utils.tsAdd MultiToken deploy, commitment, and TransferSingle event helpers +181/-0

Add MultiToken deploy, commitment, and TransferSingle event helpers

• Adds MultiToken-specific fixtures and helpers: packing short strings into Fields for constructor args, a deploy helper with configurable minter/auth hook, a commitment initializer that extracts the commitment from proven private execution results, and utilities to decode/assert 4-field 'TransferSingle' public events.

src/ts/test/utils.ts

Other (1) +1 / -0
Nargo.tomlRegister MultiToken benchmark in workspace manifest +1/-0

Register MultiToken benchmark in workspace manifest

• Adds a new benchmark entry mapping 'multitoken' to the MultiToken benchmark script so it can be discovered and run alongside existing token/nft/vault/escrow benchmarks.

Nargo.toml

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@qodo-code-review

qodo-code-review Bot commented Jul 7, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Unchecked nested result access 🐞 Bug ☼ Reliability
Description
initializeMultiTokenTransferCommitment blindly indexes nestedExecutionResults[0] and
returnValues[0], which will throw a TypeError if the private execution result has no nested
results/return values (making benchmark setup failures hard to debug). Add explicit shape checks
(and a clear error) before indexing, or search for the first nested result containing return values.
Code

src/ts/test/utils.ts[R867-870]

+  const entrypoint = provenTx.privateExecutionResult.entrypoint;
+  const nestedResults = entrypoint.nestedExecutionResults;
+  const returnValues = nestedResults[0].returnValues;
+  const commitment = returnValues[0].toBigInt();
Evidence
The new helper directly indexes nestedExecutionResults[0] and then returnValues[0] without any
checks, so an empty/malformed execution result will crash at runtime during setup.

src/ts/test/utils.ts[854-875]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`initializeMultiTokenTransferCommitment` assumes `provenTx.privateExecutionResult.entrypoint.nestedExecutionResults[0].returnValues[0]` exists. If that array is empty or the return values are missing (e.g., due to an execution layout change or a failed proof producing a different structure), the helper crashes with a non-actionable `TypeError`.

### Issue Context
This helper is used in benchmark setup to pre-create commitments; when it fails it blocks running the benchmark and the error message won’t indicate what was missing.

### Fix Focus Areas
- src/ts/test/utils.ts[854-878]

### Suggested fix
- Validate that `privateExecutionResult`, `entrypoint`, `nestedExecutionResults.length > 0`, and `returnValues.length > 0` before indexing.
- If invalid, throw an `Error` that includes the function name and a short description of what was missing (e.g. `No nestedExecutionResults in provenTx.privateExecutionResult`).
- Optionally, instead of hard-coding `[0]`, find the first nested execution result with non-empty `returnValues` and use that.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Unsafe bigint normalization 🐞 Bug ☼ Reliability
Description
compressedStringToBigInt will call v.toBigInt() for any non-bigint/number value, which can
crash with an opaque error if the SDK decode result is null/undefined or doesn’t implement
toBigInt(). Add explicit null/shape checks and throw a descriptive conversion error.
Code

src/ts/test/utils.ts[R809-814]

+export function compressedStringToBigInt(result: any): bigint {
+  const v = result?.value ?? result;
+  if (typeof v === 'bigint') return v;
+  if (typeof v === 'number') return BigInt(v);
+  return v.toBigInt();
+}
Evidence
The helper’s fallback path unconditionally calls toBigInt() on the derived value, which is not
guaranteed to exist for all decode shapes.

src/ts/test/utils.ts[809-814]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`compressedStringToBigInt` assumes any non-primitive input has a `toBigInt()` method. Unexpected decode shapes (including `undefined`/`null`) will cause a runtime crash with a low-signal message.

### Issue Context
This helper is meant to tolerate SDK decoding differences; as written it still fails hard on several plausible shapes.

### Fix Focus Areas
- src/ts/test/utils.ts[809-814]

### Suggested fix
- Change parameter type from `any` to `unknown`.
- Handle `null`/`undefined` explicitly.
- Before calling, check `typeof (v as any)?.toBigInt === 'function'`.
- Otherwise throw `new Error('compressedStringToBigInt: unsupported decode shape')` (optionally include `typeof v`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

  • Author self-review: I have reviewed the code review findings, and addressed the relevant ones.

Qodo Logo

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Benchmark Comparison

CPU Cores RAM Arch
AMD EPYC 7763 64-Core Processor 16 63 GiB x64

Contract: escrow

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
(partial) withdraw 536,844 536,844 1,312 1,312 495,400 495,400 6,989 6,953 -36 (-0.5%)
withdraw 536,844 536,844 736 736 483,700 483,700 6,997 6,940 -57 (-0.8%)
withdraw_nft 503,323 503,323 736 736 483,700 483,700 6,817 6,791 -26 (-0.4%)

Contract: logic

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
get_escrow 488,339 488,339 128 128 456,000 456,000 6,688 6,664 -24 (-0.4%)
secret_key_to_public_keys 483,417 483,417 128 128 456,000 456,000 6,643 6,650 +7 (+0.1%)
share_escrow 387,745 387,745 704 704 474,500 474,500 5,883 5,855 -28 (-0.5%)

Contract: multitoken

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
🆕 burn_private 0 409,208 +Inf% 0 736 +Inf% 0 483,700 +Inf% N/A 5,976 +Inf%
🆕 burn_public 0 308,698 +Inf% 0 416 +Inf% 0 638,244 +Inf% N/A 5,215 +Inf%
🆕 initialize_transfer_commitment 0 371,233 +Inf% 0 704 +Inf% 0 474,500 +Inf% N/A 5,736 +Inf%
🆕 mint_to_private 0 396,749 +Inf% 0 704 +Inf% 0 467,700 +Inf% N/A 5,918 +Inf%
🆕 mint_to_public 0 308,698 +Inf% 0 416 +Inf% 0 637,755 +Inf% N/A 5,218 +Inf%
🆕 transfer_private_to_commitment 0 412,636 +Inf% 0 928 +Inf% 0 495,400 +Inf% N/A 6,053 +Inf%
🆕 transfer_private_to_private 0 434,232 +Inf% 0 1,312 +Inf% 0 495,400 +Inf% N/A 6,118 +Inf%
🆕 transfer_private_to_public 0 455,550 +Inf% 0 1,024 +Inf% 0 683,832 +Inf% N/A 6,341 +Inf%
🆕 transfer_public_to_commitment 0 308,698 +Inf% 0 640 +Inf% 0 663,465 +Inf% N/A 5,233 +Inf%
🆕 transfer_public_to_private 0 444,163 +Inf% 0 992 +Inf% 0 653,113 +Inf% N/A 6,254 +Inf%
🆕 transfer_public_to_public 0 308,698 +Inf% 0 480 +Inf% 0 673,454 +Inf% N/A 5,181 +Inf%

Contract: nft

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
burn_private 422,217 422,217 416 416 661,169 661,169 6,180 6,173 -7 (-0.1%)
burn_public 308,698 308,698 448 448 670,145 670,145 5,242 5,183 -59 (-1.1%)
mint_to_private 439,895 439,895 960 960 652,042 652,042 6,259 6,233 -26 (-0.4%)
mint_to_public 308,698 308,698 448 448 670,790 670,790 5,212 5,216 +4 (+0.1%)
transfer_private_to_private 394,899 394,899 736 736 483,700 483,700 5,896 5,898 +2 (+0.0%)
transfer_private_to_public 422,293 422,293 416 416 659,249 659,249 6,127 6,112 -15 (-0.2%)
transfer_public_to_private 436,536 436,536 960 960 652,459 652,459 6,302 6,238 -64 (-1.0%)
transfer_public_to_public 308,698 308,698 384 384 633,270 633,270 5,196 5,243 +47 (+0.9%)

Contract: token

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
burn_private 451,655 451,655 992 992 683,010 683,010 6,431 6,338 -93 (-1.4%)
burn_public 308,698 308,698 448 448 672,479 672,479 5,287 5,174 -113 (-2.1%)
initialize_transfer_commitment 371,233 371,233 704 704 474,500 474,500 5,779 5,765 -14 (-0.2%)
mint_to_private 440,787 440,787 960 960 652,048 652,048 6,361 6,247 -114 (-1.8%)
mint_to_public 308,698 308,698 448 448 672,077 672,077 5,206 5,212 +6 (+0.1%)
transfer_private_to_commitment 408,890 408,890 896 896 495,400 495,400 5,997 6,043 +46 (+0.8%)
transfer_private_to_private 428,414 428,414 1,312 1,312 495,400 495,400 6,181 6,109 -72 (-1.2%)
transfer_private_to_public 451,804 451,804 992 992 683,154 683,154 6,359 6,351 -8 (-0.1%)
transfer_private_to_public_with_commitment 455,247 455,247 1,568 1,568 716,454 716,454 6,377 6,347 -30 (-0.5%)
transfer_public_to_commitment 308,698 308,698 576 576 662,454 662,454 5,212 5,195 -17 (-0.3%)
transfer_public_to_private 442,082 442,082 960 960 652,435 652,435 6,297 6,268 -29 (-0.5%)
transfer_public_to_public 308,698 308,698 448 448 672,473 672,473 5,270 5,203 -67 (-1.3%)

Contract: vault

🚦 Function Gates DA Gas L2 Gas Proving Time (ms)
Base PR Diff Base PR Diff Base PR Diff Base PR Diff
deposit_private_to_private 861,408 861,408 1,280 1,280 846,950 846,950 9,767 9,688 -79 (-0.8%)
deposit_private_to_private_exact 970,252 970,252 1,856 1,856 883,784 883,784 10,651 10,657 +6 (+0.1%)
deposit_private_to_public 679,000 679,000 768 768 861,772 861,772 8,264 8,185 -79 (-1.0%)
deposit_public_to_private 554,293 554,293 1,344 1,344 889,542 889,542 7,221 7,177 -44 (-0.6%)
deposit_public_to_private_exact 709,509 709,509 1,920 1,920 926,538 926,538 8,473 8,494 +21 (+0.2%)
deposit_public_to_public 308,698 308,698 832 832 905,432 905,432 5,207 5,182 -25 (-0.5%)
issue_private_to_private_exact 970,252 970,252 1,856 1,856 884,441 884,441 10,608 10,678 +70 (+0.7%)
issue_private_to_public_exact 834,152 834,152 1,344 1,344 899,488 899,488 9,521 9,503 -18 (-0.2%)
issue_public_to_private 604,635 604,635 1,344 1,344 898,736 898,736 7,616 7,585 -31 (-0.4%)
issue_public_to_public 308,698 308,698 832 832 906,119 906,119 5,217 5,203 -14 (-0.3%)
redeem_private_to_private_exact 971,471 971,471 1,856 1,856 884,288 884,288 10,721 10,671 -50 (-0.5%)
redeem_private_to_public 678,850 678,850 768 768 862,210 862,210 8,201 8,196 -5 (-0.1%)
redeem_public_to_private_exact 710,879 710,879 1,920 1,920 926,862 926,862 8,516 8,552 +36 (+0.4%)
redeem_public_to_public 308,698 308,698 832 832 905,954 905,954 5,226 5,188 -38 (-0.7%)
withdraw_private_to_private 862,627 862,627 1,280 1,280 847,160 847,160 9,777 9,719 -58 (-0.6%)
withdraw_private_to_private_exact 971,471 971,471 1,856 1,856 884,237 884,237 10,661 10,608 -53 (-0.5%)
withdraw_private_to_public_exact 834,001 834,001 1,344 1,344 899,719 899,719 9,516 9,539 +23 (+0.2%)
withdraw_public_to_private 555,653 555,653 1,344 1,344 889,362 889,362 7,194 7,160 -34 (-0.5%)
withdraw_public_to_public 308,698 308,698 832 832 906,257 906,257 5,225 5,211 -14 (-0.3%)

@zkfrov zkfrov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@0xLeopoldo
0xLeopoldo merged commit aa1fc24 into feat/1155 Jul 7, 2026
6 checks passed
@0xLeopoldo
0xLeopoldo deleted the feat/1155-benchmarks branch July 7, 2026 12:49
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants