From b27ebbf1cfa4ba15abce912c5c96449cb2a571b7 Mon Sep 17 00:00:00 2001 From: Matty Evans Date: Thu, 12 Feb 2026 09:23:34 +1000 Subject: [PATCH] feat(gas-profiler): add precompile gas parameters and UI support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce two new parameter groups for precompiles: fixed-cost and variable-cost. This lets users simulate the gas impact of every Ethereum precompile (ECRECOVER, SHA256, BN254, BLS12, KZG, etc.). Update UI labels to show friendly names (strip the “PC_” prefix) and rename the “Opcode Breakdown” tab to “Gas Breakdown” to reflect that precompiles are now included. --- .../gas-profiler/SimulatePage.types.ts | 35 +++++++++++++++++++ .../BlockSimulationResultsV2.tsx | 11 +++--- .../GasScheduleDrawer/GasScheduleDrawer.tsx | 12 +++++-- .../gas-profiler/utils/opcodeUtils.ts | 13 +++++++ 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/pages/ethereum/execution/gas-profiler/SimulatePage.types.ts b/src/pages/ethereum/execution/gas-profiler/SimulatePage.types.ts index 920592d22..660c29bd4 100644 --- a/src/pages/ethereum/execution/gas-profiler/SimulatePage.types.ts +++ b/src/pages/ethereum/execution/gas-profiler/SimulatePage.types.ts @@ -265,6 +265,41 @@ export const GAS_PARAMETER_GROUPS: GasParameterGroup[] = [ { key: 'KECCAK256_WORD', label: 'KECCAK256 Word', min: 0, max: 50, step: 1 }, ], }, + { + name: 'Precompiles (Fixed)', + color: '#10b981', // emerald + parameters: [ + { key: 'PC_ECREC', label: 'ECRECOVER', min: 0, max: 20000, step: 100 }, + { key: 'PC_BN254_ADD', label: 'BN254 Add', min: 0, max: 2000, step: 10 }, + { key: 'PC_BN254_MUL', label: 'BN254 Mul', min: 0, max: 30000, step: 500 }, + { key: 'PC_BLS12_G1ADD', label: 'BLS12 G1Add', min: 0, max: 5000, step: 25 }, + { key: 'PC_BLS12_G2ADD', label: 'BLS12 G2Add', min: 0, max: 5000, step: 25 }, + { key: 'PC_BLS12_MAP_FP_TO_G1', label: 'BLS12 MapFpToG1', min: 0, max: 30000, step: 500 }, + { key: 'PC_BLS12_MAP_FP2_TO_G2', label: 'BLS12 MapFp2ToG2', min: 0, max: 100000, step: 1000 }, + { key: 'PC_KZG_POINT_EVALUATION', label: 'KZG Point Eval', min: 0, max: 250000, step: 5000 }, + { key: 'PC_P256VERIFY', label: 'P256 Verify', min: 0, max: 20000, step: 100 }, + ], + }, + { + name: 'Precompiles (Variable)', + color: '#059669', // emerald-600 + parameters: [ + { key: 'PC_SHA256_BASE', label: 'SHA256 Base', min: 0, max: 500, step: 5 }, + { key: 'PC_SHA256_PER_WORD', label: 'SHA256 /Word', min: 0, max: 100, step: 1 }, + { key: 'PC_RIPEMD160_BASE', label: 'RIPEMD160 Base', min: 0, max: 3000, step: 50 }, + { key: 'PC_RIPEMD160_PER_WORD', label: 'RIPEMD160 /Word', min: 0, max: 500, step: 10 }, + { key: 'PC_ID_BASE', label: 'Identity Base', min: 0, max: 100, step: 1 }, + { key: 'PC_ID_PER_WORD', label: 'Identity /Word', min: 0, max: 50, step: 1 }, + { key: 'PC_MODEXP_MIN_GAS', label: 'MODEXP Min Gas', min: 0, max: 2000, step: 10 }, + { key: 'PC_BN254_PAIRING_BASE', label: 'BN254 Pairing Base', min: 0, max: 200000, step: 5000 }, + { key: 'PC_BN254_PAIRING_PER_PAIR', label: 'BN254 Pairing /Pair', min: 0, max: 200000, step: 1000 }, + { key: 'PC_BLAKE2F_PER_ROUND', label: 'BLAKE2F /Round', min: 0, max: 20, step: 1 }, + { key: 'PC_BLS12_PAIRING_CHECK_BASE', label: 'BLS12 Pairing Base', min: 0, max: 200000, step: 5000 }, + { key: 'PC_BLS12_PAIRING_CHECK_PER_PAIR', label: 'BLS12 Pairing /Pair', min: 0, max: 200000, step: 1000 }, + { key: 'PC_BLS12_G1MSM_MUL_GAS', label: 'BLS12 G1MSM /Point', min: 0, max: 50000, step: 1000 }, + { key: 'PC_BLS12_G2MSM_MUL_GAS', label: 'BLS12 G2MSM /Point', min: 0, max: 100000, step: 1000 }, + ], + }, // NOTE: Intrinsic gas (TX_BASE, TX_CREATE, TX_DATA_ZERO, TX_DATA_NONZERO) cannot be // customized - it's calculated at the protocol level before EVM execution begins. ]; diff --git a/src/pages/ethereum/execution/gas-profiler/components/BlockSimulationResultsV2/BlockSimulationResultsV2.tsx b/src/pages/ethereum/execution/gas-profiler/components/BlockSimulationResultsV2/BlockSimulationResultsV2.tsx index a5eee5e0f..65af0689c 100644 --- a/src/pages/ethereum/execution/gas-profiler/components/BlockSimulationResultsV2/BlockSimulationResultsV2.tsx +++ b/src/pages/ethereum/execution/gas-profiler/components/BlockSimulationResultsV2/BlockSimulationResultsV2.tsx @@ -414,7 +414,7 @@ function OpcodeRow({ op, maxGas }: { op: OpcodeRowData; maxGas: number }): JSX.E return ( @@ -442,7 +442,9 @@ function OpcodeRow({ op, maxGas }: { op: OpcodeRowData; maxGas: number }): JSX.E {/* Main row — mirrors category header pattern */}
- {op.opcode} + + {op.opcode.startsWith('PC_') ? op.opcode.slice(3) : op.opcode} + {hasCountChange && ( {formatGas(op.originalCount)} → {formatGas(op.simulatedCount)} execs @@ -551,7 +553,8 @@ function OpcodeBreakdownSection({
{cat.name} - ({cat.opcodes.length} opcode{cat.opcodes.length !== 1 ? 's' : ''}) + ({cat.opcodes.length} {cat.name === 'Precompiles' ? 'contract' : 'opcode'} + {cat.opcodes.length !== 1 ? 's' : ''})
@@ -1033,7 +1036,7 @@ export function BlockSimulationResultsV2({
Summary - Opcode Breakdown + Gas Breakdown Transactions
diff --git a/src/pages/ethereum/execution/gas-profiler/components/GasScheduleDrawer/GasScheduleDrawer.tsx b/src/pages/ethereum/execution/gas-profiler/components/GasScheduleDrawer/GasScheduleDrawer.tsx index ad3217906..904176bf2 100644 --- a/src/pages/ethereum/execution/gas-profiler/components/GasScheduleDrawer/GasScheduleDrawer.tsx +++ b/src/pages/ethereum/execution/gas-profiler/components/GasScheduleDrawer/GasScheduleDrawer.tsx @@ -26,6 +26,8 @@ const CATEGORY_ORDER = [ 'Swap', 'Memory', 'Misc', + 'Precompiles (Fixed)', + 'Precompiles (Variable)', 'Other', ]; @@ -476,10 +478,16 @@ export function GasScheduleDrawer({ 'truncate font-mono text-xs', isModified ? 'font-semibold text-primary' : 'text-foreground' )} + title={key} > - {key} + {key.startsWith('PC_') ? key.slice(3) : key} - {param.description && } + {param.description && ( + + )}
{/* Number Input */} diff --git a/src/pages/ethereum/execution/gas-profiler/utils/opcodeUtils.ts b/src/pages/ethereum/execution/gas-profiler/utils/opcodeUtils.ts index a60e7f544..33375e6af 100644 --- a/src/pages/ethereum/execution/gas-profiler/utils/opcodeUtils.ts +++ b/src/pages/ethereum/execution/gas-profiler/utils/opcodeUtils.ts @@ -138,6 +138,9 @@ export const CATEGORY_COLORS: Record = { Swap: '#84cc16', // lime Log: '#eab308', // yellow Contract: '#0ea5e9', // sky + 'Precompiles (Fixed)': '#10b981', // emerald + 'Precompiles (Variable)': '#059669', // emerald-600 + Precompiles: '#10b981', // emerald - used for opcode breakdown chart Other: '#9ca3af', // gray-400 }; @@ -182,6 +185,11 @@ export function isGasParameter(name: string): boolean { return true; } + // Precompile gas parameters (PC_SHA256_BASE, PC_ECREC, etc.) + if (name.startsWith('PC_')) { + return true; + } + // Known standalone parameters (not opcodes) const standaloneParameters = [ 'MEMORY', // Memory expansion cost @@ -206,6 +214,9 @@ export function getOpcodeCategory(opcode: string): string { // Direct lookup first if (OPCODE_CATEGORIES[opcode]) return OPCODE_CATEGORIES[opcode]; + // Precompile gas entries (PC_SHA256, PC_ECREC, etc.) + if (opcode.startsWith('PC_')) return 'Precompiles'; + // Push opcodes (PUSH0-PUSH32) if (opcode.startsWith('PUSH')) return 'Push'; @@ -263,6 +274,8 @@ const HEX_TO_TAILWIND: Record = { '#84cc16': { bg: 'bg-lime-500', hover: 'hover:bg-lime-400' }, '#eab308': { bg: 'bg-yellow-500', hover: 'hover:bg-yellow-400' }, '#0ea5e9': { bg: 'bg-sky-500', hover: 'hover:bg-sky-400' }, + '#10b981': { bg: 'bg-emerald-500', hover: 'hover:bg-emerald-400' }, + '#059669': { bg: 'bg-emerald-600', hover: 'hover:bg-emerald-500' }, '#9ca3af': { bg: 'bg-gray-400', hover: 'hover:bg-gray-300' }, };