-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathechidna_parser.py
executable file
·70 lines (57 loc) · 2.34 KB
/
echidna_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env python3
import re
def parse_echidna_trace(trace):
"""Parse Echidna trace and extract function calls, parameters, delays, and 'from' addresses."""
calls = []
last_address = None # Track the last 'from' address
for line in trace.strip().splitlines():
# Parse function calls, including those with underscores
func_call = re.match(r"Tester\.([a-zA-Z0-9_]+)\(([^)]*)\)", line)
if func_call:
func_name = func_call.group(1)
params = func_call.group(2)
# Check for 'from' address
from_address = re.search(r"from: (0x[a-fA-F0-9]+)", line)
time_delay = re.search(r"Time delay: (\d+)", line)
# If we have a 'from' address, we need to set it up
if from_address:
address = from_address.group(1)
if address != last_address:
# Only set up the actor if the address has changed
calls.append(f"_setUpActor({address});")
last_address = address
# Add the delay if it exists
if time_delay:
delay_time = time_delay.group(1)
calls.append(f"_delay({delay_time});")
# Add the function call
calls.append(f"Tester.{func_name}({params});")
# Handle special case of "*wait*" for a delay
elif "*wait*" in line:
time_delay = re.search(r"Time delay: (\d+)", line)
if time_delay:
delay_time = time_delay.group(1)
calls.append(f"_delay({delay_time});")
return calls
def generate_foundry_test(calls, test_name="test_replay"):
"""Generate the Solidity test function code."""
test_code = [f"function {test_name}() public {{"]
test_code.extend(f" {call}" for call in calls)
test_code.append("}")
return "\n".join(test_code)
# Ask user to paste the Echidna trace
print("Paste your Echidna call trace below. Press Enter twice to finish:")
trace = []
while True:
line = input()
if line:
trace.append(line.strip())
else:
break
trace = "\n".join(trace)
# Parse the trace and generate the test
parsed_calls = parse_echidna_trace(trace)
solidity_test = generate_foundry_test(parsed_calls)
# Output the generated Solidity test
print("\nGenerated Foundry Test Function:\n")
print(solidity_test)