Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions gas-benchmarks/src/privacy-pools/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,37 @@ export const DEPOSITED_EVENT_ABI = {
* LeafInserted() - To notify the leaf insertion in the merkle tree
* Deposited() - Emitted inside PrivacyPool.sol contract (internal)
* Deposited() - Emitted inside Entrypoint.sol contract (external)
*
* Example:
* https://etherscan.io/tx/0x87320aaae4868c6f5b7c8b31ba2fc82005bdd7522fdf85f9eb8dcc93a34cb475
*/
export const NUMBER_OF_SHIELD_EVENTS = 3;

/**
* Event ABI for the WithdrawalRelayed event emitted by Entrypoint.relay()
*/
export const WITHDRAWAL_RELAYED_EVENT_ABI = {
type: "event",
name: "WithdrawalRelayed",
inputs: [
{ name: "_relayer", type: "address", indexed: true },
Comment thread
JohnGuilding marked this conversation as resolved.
{ name: "_recipient", type: "address", indexed: true },
{ name: "_asset", type: "address", indexed: true },
{ name: "_amount", type: "uint256", indexed: false },
{ name: "_feeAmount", type: "uint256", indexed: false },
],
} as const satisfies AbiEvent;

/**
* Entrypoint.relay (unshield) function call emits:
* LeafInserted() - Emitted inside State.sol -> insert()
* Transfer() - move funds to entrypoint (Emitted inside PrivacyPoolComplex.sol -> _push)
* Withdrawn() - Emitted inside PrivacyPool.sol -> withdraw()
* Transfer() - Net amount to recipient
* Transfer() - Fee to fee recipient
* WithdrawalRelayed() - Emitted inside Entrypoint.relay()
*
* Example:
* https://etherscan.io/tx/0x47e918eda32bc332a5684aa986733eb4fde7a4f8189e21443f23adf0807974b7
*/
export const NUMBER_OF_UNSHIELD_EVENTS = 6;
17 changes: 17 additions & 0 deletions gas-benchmarks/src/privacy-pools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
DEPOSITED_EVENT_ABI,
MAX_OF_LOGS,
NUMBER_OF_SHIELD_EVENTS,
NUMBER_OF_UNSHIELD_EVENTS,
PRIVACY_POOLS_ENTRYPOINT_PROXY,
WITHDRAWAL_RELAYED_EVENT_ABI,
} from "./constants.js";

export class PrivacyPools {
Expand All @@ -15,6 +17,7 @@ export class PrivacyPools {

async benchmark(): Promise<void> {
await this.benchmarkShield();
await this.benchmarkUnshield();
}

async benchmarkShield(): Promise<void> {
Expand All @@ -30,4 +33,18 @@ export class PrivacyPools {

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "shield");
}

async benchmarkUnshield(): Promise<void> {
const logs = await getEventLogs({
contractAddress: PRIVACY_POOLS_ENTRYPOINT_PROXY,
event: WITHDRAWAL_RELAYED_EVENT_ABI,
maxLogs: MAX_OF_LOGS,
});
const uniqueLogs = getUniqueLogs(logs);

const txs = await getTransactionsWithNEvents(uniqueLogs, NUMBER_OF_UNSHIELD_EVENTS);
const metrics = getAverageMetrics(txs);

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "unshield");
}
}
60 changes: 60 additions & 0 deletions gas-benchmarks/src/railgun/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,65 @@ export const SHIELD_EVENT_ABI = {
* Transfer() - Tokens sent to shielded pool
* Transfer() - Shield fee sent to vault
* Shield() - To notify the shield
*
* Example:
* https://etherscan.io/tx/0x5c9bb21f9aa22f636e468bfb19b17093ccc5de7d86aad601b5b4b607f07f1143
*/
export const NUMBER_OF_SHIELD_EVENTS = 3;

/**
* Event ABI for the Unshield event emitted by RailgunLogic in function transferTokenOut
*/
export const UNSHIELD_EVENT_ABI = {
type: "event",
name: "Unshield",
inputs: [
{ name: "to", type: "address", indexed: false },
{
name: "token",
type: "tuple",
indexed: false,
components: [
{ name: "tokenType", type: "uint8" },
{ name: "tokenAddress", type: "address" },
{ name: "tokenSubID", type: "uint256" },
],
},
{ name: "amount", type: "uint256", indexed: false },
{ name: "fee", type: "uint256", indexed: false },
],
} as const satisfies AbiEvent;

/**
* RailgunSmartWallet.transact function call when unshielding emits:
* Nullified() - Nullifier being spent emitted in RailgunLogic.accumulateAndNullifyTransaction
* Transfer() - Transfer unshielded tokens to recipient emitted in RailgunLogic.transferTokenOut
* Transfer() - Transfer unshield fee to vault emitted in RailgunLogic.transferTokenOut
* Unshield() - To notify the unshield process emitted in RailgunLogic.transferTokenOut
*
* Example:
* https://etherscan.io/tx/0x2c3e8738f9d0d3e98b702a6dc375162fe21777e35f19d8b662088b2b6987e722
*/
export const NUMBER_OF_UNSHIELD_EVENTS = 4;

/**
* Event ABI for the Nullified event emitted by RailgunLogic in function accumulateAndNullifyTransaction
*/
export const NULLIFIED_EVENT_ABI = {
type: "event",
name: "Nullified",
inputs: [
{ name: "treeNumber", type: "uint16", indexed: false },
{ name: "nullifier", type: "bytes32[]", indexed: false },
],
} as const satisfies AbiEvent;

/**
* RailgunSmartWallet.transact (private transfer) function call emits:
* Nullified() - Nullifier being spent emitted in RailgunLogic.accumulateAndNullifyTransaction
* Transact() - To notify the commitment state update emitted in RailgunSmartWallet.transact
*
* Example:
* https://etherscan.io/tx/0xb010a8f2babfa78bb6945221817238c58234d06eb56177de6e002e761574fc53
*/
export const NUMBER_OF_TRANSFER_EVENTS = 2;
41 changes: 40 additions & 1 deletion gas-benchmarks/src/railgun/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { getEventLogs, getTransactionsWithNEvents, getUniqueLogs } from "../utils/rpc.js";
import { getAverageMetrics, saveGasMetrics } from "../utils/utils.js";

import { MAX_OF_LOGS, NUMBER_OF_SHIELD_EVENTS, RAILGUN_SMART_WALLET_PROXY, SHIELD_EVENT_ABI } from "./constants.js";
import {
MAX_OF_LOGS,
NULLIFIED_EVENT_ABI,
NUMBER_OF_SHIELD_EVENTS,
NUMBER_OF_TRANSFER_EVENTS,
NUMBER_OF_UNSHIELD_EVENTS,
RAILGUN_SMART_WALLET_PROXY,
SHIELD_EVENT_ABI,
UNSHIELD_EVENT_ABI,
} from "./constants.js";

export class Railgun {
readonly name = "railgun";
Expand All @@ -10,6 +19,8 @@ export class Railgun {

async benchmark(): Promise<void> {
await this.benchmarkShield();
await this.benchmarkUnshield();
await this.benchmarkTransfer();
}

async benchmarkShield(): Promise<void> {
Expand All @@ -25,4 +36,32 @@ export class Railgun {

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "shield");
}

async benchmarkUnshield(): Promise<void> {
const logs = await getEventLogs({
contractAddress: RAILGUN_SMART_WALLET_PROXY,
event: UNSHIELD_EVENT_ABI,
maxLogs: MAX_OF_LOGS,
});
const uniqueLogs = getUniqueLogs(logs);

const txs = await getTransactionsWithNEvents(uniqueLogs, NUMBER_OF_UNSHIELD_EVENTS);
const metrics = getAverageMetrics(txs);

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "unshield");
}

async benchmarkTransfer(): Promise<void> {
const logs = await getEventLogs({
contractAddress: RAILGUN_SMART_WALLET_PROXY,
event: NULLIFIED_EVENT_ABI,
maxLogs: MAX_OF_LOGS,
});
const uniqueLogs = getUniqueLogs(logs);

const txs = await getTransactionsWithNEvents(uniqueLogs, NUMBER_OF_TRANSFER_EVENTS);
const metrics = getAverageMetrics(txs);

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "transfer");
}
}
38 changes: 35 additions & 3 deletions gas-benchmarks/src/tornado-cash/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const MAX_OF_LOGS = NUMBER_OF_TRANSACTIONS * 5;

/**
* Tornado Cash Router contract that directs deposits to different pools (ETH, ERC20 0.1, ERC20 1, ERC20 10, ERC20 100):
* https://github.com/tornadocash/tornado-anonymity-mining/blob/d93d7c8870fc3cd4cb1da698301e737e1606ba9c/contracts/TornadoProxy.sol
* https://github.com/contractscan/etherscan.io-0xd90e2f925da726b50c4ed8d0fb90ad053324f31b/blob/main/TornadoRouter.sol
*/
export const TORNADO_CASH_ROUTER: Hex = "0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b";

Expand All @@ -28,7 +28,39 @@ export const ENCRYPTED_NOTE_EVENT_ABI = {

/**
* A deposit function call emits:
* Deposit() - To notify the token public deposit into the contract
* EncryptedNote() - To notify the encrypted note generation
* Deposit() - To notify the token public deposit emitted by the pool contract
* EncryptedNote() - To notify the encrypted note generation emitted by the router contract
*
* Example:
* https://etherscan.io/tx/0x2e847019a164ebff78700fcd1d19b5ade27b78d3869770905e87eed38494b834
*/
export const NUMBER_OF_SHIELD_EVENTS = 2;

/**
* Tornado Cash Relayer Registry contract that emits a StakeBurned event when a relayed withdrawal is executed.
* After it, a pool (ETH, ERC20 0.1, ERC20 1, ERC20 10, ERC20 100) emits a Withdrawal event.
* https://github.com/contractscan/etherscan.io-0xd90e2f925da726b50c4ed8d0fb90ad053324f31b/blob/main/RelayerRegistry.sol
*/
export const TORNADO_CASH_RELAYER_REGISTRY: Hex = "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2";

/**
* Event ABI for the StakeBurned event emitted by registry during withdraw
*/
export const STAKE_BURNED_EVENT_ABI = {
type: "event",
name: "StakeBurned",
inputs: [
{ name: "relayer", type: "address", indexed: false },
{ name: "amountBurned", type: "uint256", indexed: false },
],
} as const satisfies AbiEvent;

/**
* A withdraw function call emits:
* StakeBurned() - To notify the stake burning of the withdrawal (emitted by the registry)
* Withdrawal() - To notify the withdrawal (emitted by the specific pool)
*
* Example:
* https://etherscan.io/tx/0x99e1f27a5d7e8bfcaadad216a6130f66eedeeca43c5d917acd6952414e388331
*/
export const NUMBER_OF_UNSHIELD_EVENTS = 2;
25 changes: 24 additions & 1 deletion gas-benchmarks/src/tornado-cash/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { getEventLogs, getTransactionsWithNEvents, getUniqueLogs } from "../utils/rpc.js";
import { getAverageMetrics, saveGasMetrics } from "../utils/utils.js";

import { ENCRYPTED_NOTE_EVENT_ABI, MAX_OF_LOGS, NUMBER_OF_SHIELD_EVENTS, TORNADO_CASH_ROUTER } from "./constants.js";
import {
ENCRYPTED_NOTE_EVENT_ABI,
MAX_OF_LOGS,
NUMBER_OF_SHIELD_EVENTS,
NUMBER_OF_UNSHIELD_EVENTS,
STAKE_BURNED_EVENT_ABI,
TORNADO_CASH_RELAYER_REGISTRY,
TORNADO_CASH_ROUTER,
} from "./constants.js";

export class TornadoCash {
readonly name = "tornado-cash";
Expand All @@ -10,6 +18,7 @@ export class TornadoCash {

async benchmark(): Promise<void> {
await this.benchmarkShield();
await this.benchmarkUnshield();
}

async benchmarkShield(): Promise<void> {
Expand All @@ -25,4 +34,18 @@ export class TornadoCash {

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "shield");
}

async benchmarkUnshield(): Promise<void> {
const logs = await getEventLogs({
contractAddress: TORNADO_CASH_RELAYER_REGISTRY,
event: STAKE_BURNED_EVENT_ABI,
maxLogs: MAX_OF_LOGS,
});
const uniqueLogs = getUniqueLogs(logs);

const txs = await getTransactionsWithNEvents(uniqueLogs, NUMBER_OF_UNSHIELD_EVENTS);
const metrics = getAverageMetrics(txs);

await saveGasMetrics(metrics, `${this.name}_${this.version}`, "unshield");
}
}
2 changes: 2 additions & 0 deletions gas-benchmarks/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const ETH_RPC_URL = String(process.env.ETH_RPC_URL);

export const BLOCK_RANGE = 1_000n;

export const MAX_NUMBER_OF_RPC_TRIES = 10;

export const NUMBER_OF_TRANSACTIONS = Number(process.env.NUMBER_OF_TRANSACTIONS);

export const BENCHMARKS_OUTPUT_PATH = "./benchmarks.json";
13 changes: 10 additions & 3 deletions gas-benchmarks/src/utils/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { createPublicClient, http, type Hash, type Log, type TransactionReceipt } from "viem";
import { mainnet } from "viem/chains";

import type { GetShieldEventLogs } from "./types.js";
import type { GetEventLogs } from "./types.js";

import { ETH_RPC_URL, NUMBER_OF_TRANSACTIONS } from "./constants.js";
import { ETH_RPC_URL, MAX_NUMBER_OF_RPC_TRIES, NUMBER_OF_TRANSACTIONS } from "./constants.js";
import { getBlockInRange } from "./utils.js";

export const publicClient = createPublicClient({
transport: http(ETH_RPC_URL),
chain: mainnet,
});

export const getEventLogs = async ({ contractAddress, event, maxLogs }: GetShieldEventLogs): Promise<Log[]> => {
export const getEventLogs = async ({ contractAddress, event, maxLogs }: GetEventLogs): Promise<Log[]> => {
const latestBlock = await publicClient.getBlockNumber();
let toBlock = latestBlock;
let fromBlock = getBlockInRange(toBlock);

let tries = 0;
const logs: Log[] = [];

while (logs.length < maxLogs) {
Expand All @@ -35,6 +36,12 @@ export const getEventLogs = async ({ contractAddress, event, maxLogs }: GetShiel

toBlock = fromBlock - 1n;
fromBlock = getBlockInRange(toBlock);

if (tries >= MAX_NUMBER_OF_RPC_TRIES) {
break;
}

tries += 1;
}

return logs;
Expand Down
2 changes: 1 addition & 1 deletion gas-benchmarks/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface GasMetrics {
averageTxFee: bigint | "no-data";
}

export interface GetShieldEventLogs {
export interface GetEventLogs {
contractAddress: Hex;
event: AbiEvent;
maxLogs: number;
Expand Down