Skip to content

Instantly share code, notes, and snippets.

@cassc
Created October 29, 2024 07:21
Show Gist options
  • Save cassc/efbf60f4bb5b15bc4d9e5922d1d6667f to your computer and use it in GitHub Desktop.
Save cassc/efbf60f4bb5b15bc4d9e5922d1d6667f to your computer and use it in GitHub Desktop.
Get transation stats by foundry
import json
import subprocess
from web3 import Web3
import os
import plotly.express as px
import plotly.io as pio
import pandas as pd
import concurrent.futures
num_processes = os.cpu_count()
block_numbers = list(range(19036989 + 60000, 19036989 + 60000 + 20)) + list(range(19036989-2160000, 19036989-2160000 + 20)) + list(range(19036989 - 100, 19036989-100 + 20))
rpc_endpoint = os.environ['ETH_RPC_ALCHEMY_ENDPOINT']
no_rate_limit = True
web3 = Web3(Web3.HTTPProvider(rpc_endpoint))
output_dir = f'{os.environ["HOME"]}/tmp/stats'
os.makedirs(output_dir, exist_ok=True)
def transactions_in_block(block_number):
block = web3.eth.get_block(block_number)
return block['transactions']
def process_trace(stats, data):
arena_list = data['arena']
arena_steps = [arena['trace']['steps'] for arena in arena_list]
all_steps = [s for steps in arena_steps for s in steps]
max_stack_size = 0
max_memory_size = 0
max_depth = 0
# storage_read_count = 0
# storage_write_count = 0
# stack_write_count = 0
op_stats = {}
accessed_addresses = set()
for step in all_steps:
op = step['op']
max_depth = max(max_depth, step['depth'])
max_stack_size = max(max_stack_size, len(step['stack']))
max_memory_size = max(max_memory_size, (len(step['memory']) - 2) / 2)
op_stats[op] = op_stats.get(op, 0) + 1
accessed_addresses.add(step.get('contract'))
# if op == 0x55:
# storage_write_count += 1
# elif op == 0x54:
# storage_read_count += 1
# elif op >= 0x5f and op <= 0x9f:
# stack_write_count += 1
stats.append(dict(max_stack_size=max_stack_size,
max_memory_size=max_memory_size,
op_stats=op_stats,
max_depth=max_depth,
num_accessed_addresses=len(accessed_addresses)))
#cast run 0x142a06071c8717c268e0401fe7e97e66cbebacb922e72d625227433bbf356520 -r $ETH_RPC_ALCHEMY_ENDPOINT --decode-internal -j
def run_tx(stats, txhash):
txhash = txhash if isinstance(txhash, str) else f'0x{txhash.hex()}'
print('Loading traces for:', txhash)
cmd = ['cast', 'run', txhash, '-r', rpc_endpoint, '--decode-internal', '-j', '--with-state-changes']
if no_rate_limit:
cmd.append('--no-rate-limit')
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True)
stdout, stderr = proc.communicate()
proc.wait()
print('Trace loaded for:', txhash)
data = None
for line in stdout.splitlines():
try:
data = json.loads(line)
break
except json.JSONDecodeError:
continue
if not data:
print('No trace for transaction:', txhash)
return
process_trace(stats, data)
def gen_out_json_filename(block_number):
return f'{output_dir}/stats-block-{block_number}.json'
def run_block(block_number):
out_json = gen_out_json_filename(block_number)
if os.path.exists(out_json):
print(f'Stats for block {block_number} already exists at {out_json}')
return
txs = transactions_in_block(block_number)
print(f'Processing block {block_number} with {len(txs)} transactions')
stats = []
for tx in txs:
run_tx(stats, tx)
with open(out_json, 'w') as f:
json.dump({block_number: stats}, f)
print(f'Stats for block {block_number} written to {out_json}')
def read_stats(stats_file_name):
with open(f'{output_dir}/{stats_file_name}', 'r') as f:
return json.load(f)
def plot_stats():
files = [f for f in os.listdir(output_dir) if f.endswith('.json')]
block_stats = [read_stats(f) for f in files if f.startswith('stats-block-')]
block_stats = [list(s.values())[0] for s in block_stats if s]
flattened_stats = [s for stats in block_stats for s in stats]
df = pd.DataFrame(flattened_stats)
fig = px.scatter_matrix(df, dimensions=["max_stack_size", "max_memory_size", "max_depth", "num_accessed_addresses"],
title="Scatter Matrix of Metrics",
labels={"max_stack_size": "Max Stack Size", "max_memory_size": "Max Memory Size",
"max_depth": "Max Depth", "num_accessed_addresses": "Num Accessed Addresses"})
fig.update_layout(width=1900, height=1050)
pio.write_html(fig, file=f"{output_dir}/scatter_matrix.html", auto_open=False)
def print_stats():
files = [f for f in os.listdir(output_dir) if f.endswith('.json')]
block_stats = [read_stats(f) for f in files if f.startswith('stats-block-')]
block_stats = [list(s.values())[0] for s in block_stats if s]
stats_data = [s for stats in block_stats for s in stats]
flattened_stats = []
for item in stats_data:
flat_item = item.copy()
for op, value in item["op_stats"].items():
op = int(op)
key = f"op_{op:02X}"
flat_item[key] = value
del flat_item["op_stats"]
flattened_stats.append(flat_item)
# median of max_stack_size, etc
df = pd.DataFrame(flattened_stats)
with pd.option_context('display.max_rows', None, 'display.max_columns', None):
print('Median of all stats')
print(df.median())
print()
print('Mean of all stats')
print(df.mean())
print()
print('Max of all stats')
print(df.max())
print()
def process_blocks(block_numbers):
with concurrent.futures.ThreadPoolExecutor(max_workers=num_processes) as executor:
future_to_block = {executor.submit(run_block, block_number): block_number for block_number in block_numbers}
for future in concurrent.futures.as_completed(future_to_block):
block_number = future_to_block[future]
try:
future.result() # This will raise an exception if the block failed to run
except Exception as e:
print(f'Error processing block {block_number}:', e)
if __name__ == '__main__':
process_blocks(block_numbers)
plot_stats()
print_stats()
@cassc
Copy link
Author

cassc commented Oct 29, 2024

Median of all stats
max_stack_size             22.0
max_memory_size           160.0
max_depth                   1.0
num_accessed_addresses      1.0
op_60                     153.0
op_52                      32.5
op_36                       5.0
op_10                       7.0
op_61                     101.5
op_57                      49.0
op_35                       7.0
op_1C                       4.0
op_80                      44.0
op_63                      28.0
op_11                      11.0
op_14                      24.0
op_5B                      80.0
op_03                      21.0
op_81                      52.0
op_01                      40.0
op_90                      61.0
op_91                      28.0
op_56                      47.0
op_88                       9.0
op_8A                       8.0
op_12                       4.0
op_15                      29.0
op_82                      31.0
op_8B                       7.0
op_50                      80.0
op_73                      16.0
op_16                      29.0
op_92                      17.0
op_97                       5.0
op_96                       6.0
op_95                      11.0
op_94                       9.0
op_93                      17.0
op_98                       5.0
op_33                       4.0
op_20                       8.0
op_54                      13.0
op_86                      18.0
op_83                      23.0
op_43                       1.0
op_42                       2.0
op_87                       8.0
op_51                      19.0
op_1B                      23.0
op_3B                       4.0
op_5A                       7.0
op_FA                       4.0
op_3D                      10.0
op_19                       6.0
op_0B                      38.0
op_89                      12.0
op_85                      10.0
op_84                      16.0
op_7E                       1.0
op_1A                       3.0
op_53                      15.0
op_8C                       4.0
op_30                       4.0
op_8F                       2.0
op_8E                       2.0
op_F1                       4.0
op_00                       1.0
op_34                       2.0
op_04                       8.0
op_F3                       2.0
op_64                       4.0
op_02                      14.0
op_17                       9.0
op_7F                       5.0
op_55                       3.0
op_13                       4.0
op_05                       1.0
op_07                       2.0
op_1D                       3.0
op_67                       7.0
op_62                       2.0
op_70                       2.0
op_6F                      16.0
op_6E                       5.0
op_06                       4.0
op_8D                       5.0
op_09                       9.0
op_7B                       6.0
op_77                       1.0
op_9C                       4.0
op_9E                       1.0
op_9D                       2.0
op_9B                       2.0
op_9A                       3.0
op_99                       3.0
op_66                       7.0
op_69                       1.0
op_6A                       1.0
op_0A                       3.0
op_3E                       2.0
op_37                       3.0
op_A3                       1.0
op_7C                       3.0
op_32                       1.0
op_38                       4.0
op_74                       1.0
op_18                       2.0
op_39                       1.0
op_6D                      18.0
op_A1                       1.0
op_F4                       1.0
op_6C                       2.0
op_3F                       1.0
op_68                       1.0
op_47                       1.0
op_A2                       1.0
op_FD                       1.0
op_46                       1.0
op_65                       2.0
op_A4                       1.0
op_6B                       1.0
op_58                       8.0
op_7D                       1.0
op_71                       1.0
op_79                       1.0
op_75                       1.0
op_76                       1.0
op_78                       2.0
op_3A                       1.0
op_9F                       2.0
op_31                       1.0
op_08                      18.0
op_48                       1.0
op_5F                      38.0
op_72                       1.0
op_F5                       1.0
op_40                       1.0
op_7A                       2.0
op_45                       1.0
op_41                       1.0
op_44                       1.0
op_59                       5.0
op_FE                       1.0
op_F0                     100.0
op_FF                       1.0
dtype: float64

Mean of all stats
max_stack_size              22.616238
max_memory_size           1001.563823
max_depth                    1.738952
num_accessed_addresses       1.766084
op_60                      475.004015
op_52                      113.052965
op_36                       14.611309
op_10                       44.902261
op_61                      380.291345
op_57                      190.699660
op_35                       28.748172
op_1C                       20.006122
op_80                      163.987616
op_63                       54.504513
op_11                       37.085567
op_14                       51.606433
op_5B                      296.769159
op_03                       63.227844
op_81                      200.925570
op_01                      178.431190
op_90                      214.942379
op_91                      116.320292
op_56                      169.133613
op_88                       14.348539
op_8A                       13.844460
op_12                       13.434380
op_15                      109.383009
op_82                      135.911792
op_8B                       10.333333
op_50                      275.864067
op_73                       41.922600
op_16                      106.987201
op_92                       64.837666
op_97                        9.389678
op_96                       11.819178
op_95                       19.273390
op_94                       20.280475
op_93                       36.494171
op_98                        6.890946
op_33                        6.533048
op_20                       17.984810
op_54                       24.914516
op_86                       34.201302
op_83                       88.336920
op_43                        2.054987
op_42                        2.904430
op_87                       21.111090
op_51                       85.808461
op_1B                       52.524217
op_3B                        5.370343
op_5A                        9.575581
op_FA                        5.453381
op_3D                       13.546899
op_19                       19.420674
op_0B                       43.550505
op_89                       17.436978
op_85                       32.022204
op_84                       57.797672
op_7E                        5.422430
op_1A                       17.774566
op_53                       31.644231
op_8C                        7.874520
op_30                        5.603103
op_8F                        4.451282
op_8E                        4.713873
op_F1                        5.159475
op_00                        2.219982
op_34                        5.437481
op_04                       23.586543
op_F3                        6.104027
op_64                        5.980286
op_02                       29.535129
op_17                       19.202503
op_7F                       21.763058
op_55                        7.294202
op_13                       12.634831
op_05                       10.190801
op_07                        2.292343
op_1D                       18.847397
op_67                       16.853191
op_62                       12.747950
op_70                        2.887543
op_6F                       20.018492
op_6E                        4.745558
op_06                        5.910400
op_8D                        6.889360
op_09                       68.010101
op_7B                        5.920732
op_77                        1.371308
op_9C                        4.750000
op_9E                        1.928910
op_9D                        3.121669
op_9B                        4.119310
op_9A                        3.837922
op_99                        5.426379
op_66                        6.721893
op_69                        2.117864
op_6A                        1.545455
op_0A                        6.946648
op_3E                        3.065469
op_37                        5.135438
op_A3                        2.348387
op_7C                        4.675381
op_32                        1.739785
op_38                        4.406504
op_74                        1.617925
op_18                       13.083333
op_39                        2.658349
op_6D                       17.113025
op_A1                        1.374108
op_F4                        2.740308
op_6C                        4.727273
op_3F                        1.981013
op_68                        5.823105
op_47                        1.941414
op_A2                        1.327225
op_FD                        1.959596
op_46                        1.568182
op_65                        4.774869
op_A4                        1.918390
op_6B                        4.506510
op_58                       10.954545
op_7D                        1.765432
op_71                        1.182692
op_79                        1.218447
op_75                        1.545455
op_76                        1.612245
op_78                        2.264706
op_3A                        1.292135
op_9F                        2.619048
op_31                        2.026667
op_08                     1219.933333
op_48                        2.024390
op_5F                       64.268797
op_72                        1.957143
op_F5                        1.000000
op_40                        1.000000
op_7A                        2.388889
op_45                        1.000000
op_41                        1.142857
op_44                        1.000000
op_59                        5.000000
op_FE                        1.000000
op_F0                      100.000000
op_FF                        4.000000
dtype: float64

Max of all stats
max_stack_size               124.0
max_memory_size           142432.0
max_depth                     14.0
num_accessed_addresses       102.0
op_60                      22782.0
op_52                       4733.0
op_36                       1499.0
op_10                       4965.0
op_61                      19289.0
op_57                       9159.0
op_35                       3457.0
op_1C                       5301.0
op_80                      26753.0
op_63                       2042.0
op_11                       3014.0
op_14                       1700.0
op_5B                      17242.0
op_03                       5076.0
op_81                      12391.0
op_01                      13260.0
op_90                      17767.0
op_91                       8946.0
op_56                      10103.0
op_88                        699.0
op_8A                       1944.0
op_12                       1622.0
op_15                       9982.0
op_82                      26484.0
op_8B                        970.0
op_50                      14465.0
op_73                        908.0
op_16                       3295.0
op_92                       3689.0
op_97                        437.0
op_96                        974.0
op_95                        988.0
op_94                        566.0
op_93                       5624.0
op_98                        274.0
op_33                        201.0
op_20                       1021.0
op_54                        996.0
op_86                       1454.0
op_83                      17845.0
op_43                         26.0
op_42                         85.0
op_87                        990.0
op_51                       6129.0
op_1B                       2820.0
op_3B                         59.0
op_5A                        221.0
op_FA                        113.0
op_3D                        300.0
op_19                       1156.0
op_0B                        600.0
op_89                       1945.0
op_85                       2016.0
op_84                       3212.0
op_7E                        108.0
op_1A                        212.0
op_53                        144.0
op_8C                        202.0
op_30                        101.0
op_8F                        302.0
op_8E                        200.0
op_F1                        134.0
op_00                         81.0
op_34                        119.0
op_04                       1963.0
op_F3                        143.0
op_64                        106.0
op_02                       5400.0
op_17                        808.0
op_7F                       8765.0
op_55                        380.0
op_13                       2740.0
op_05                        681.0
op_07                         18.0
op_1D                       2820.0
op_67                       1714.0
op_62                       2150.0
op_70                         39.0
op_6F                       1400.0
op_6E                        116.0
op_06                         72.0
op_8D                        157.0
op_09                      26400.0
op_7B                        110.0
op_77                         16.0
op_9C                         40.0
op_9E                         52.0
op_9D                         78.0
op_9B                        130.0
op_9A                        130.0
op_99                        256.0
op_66                         59.0
op_69                         30.0
op_6A                         42.0
op_0A                        201.0
op_3E                         64.0
op_37                        588.0
op_A3                         59.0
op_7C                         71.0
op_32                        101.0
op_38                        100.0
op_74                         38.0
op_18                       2461.0
op_39                        300.0
op_6D                        202.0
op_A1                         17.0
op_F4                        120.0
op_6C                        348.0
op_3F                         26.0
op_68                        520.0
op_47                         22.0
op_A2                         40.0
op_FD                         14.0
op_46                         14.0
op_65                         64.0
op_A4                         65.0
op_6B                        264.0
op_58                         42.0
op_7D                          6.0
op_71                         14.0
op_79                         38.0
op_75                          9.0
op_76                          4.0
op_78                         16.0
op_3A                          4.0
op_9F                         26.0
op_31                          9.0
op_08                      17580.0
op_48                          8.0
op_5F                       1035.0
op_72                          8.0
op_F5                          1.0
op_40                          1.0
op_7A                          4.0
op_45                          1.0
op_41                          2.0
op_44                          1.0
op_59                          6.0
op_FE                          1.0
op_F0                        100.0
op_FF                         10.0
dtype: float64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment