-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from crytic/fix/missing-methods
fix: weight methods correctly to avoid skipping some
- Loading branch information
Showing
6 changed files
with
247 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Debugging and Development | ||
|
||
## Debugging | ||
|
||
The following scripts are available for Medusa developers for debugging changes to the fuzzer. | ||
|
||
### Corpus diff | ||
|
||
The corpus diff script is used to compare two corpora and identify the methods that are present in one but not the other. This is useful for identifying methods that are missing from a corpus that should be present. | ||
|
||
```shell | ||
python3 scripts/corpus_diff.py corpus1 corpus2 | ||
``` | ||
|
||
```shell | ||
Methods only in ~/corpus1: | ||
- clampSplitWeight(uint32,uint32) | ||
|
||
Methods only in ~/corpus2: | ||
<None> | ||
``` | ||
|
||
### Corpus stats | ||
|
||
The corpus stats script is used to generate statistics about a corpus. This includes the number of sequences, the average length of sequences, and the frequency of methods called. | ||
|
||
```shell | ||
python3 scripts/corpus_stats.py corpus | ||
``` | ||
|
||
```shell | ||
Number of Sequences in ~/corpus: 130 | ||
|
||
Average Length of Transactions List: 43 | ||
|
||
Frequency of Methods Called: | ||
- testReceiversReceivedSplit(uint8): 280 | ||
- setMaxEndHints(uint32,uint32): 174 | ||
- setStreamBalanceWithdrawAll(uint8): 139 | ||
- giveClampedAmount(uint8,uint8,uint128): 136 | ||
- receiveStreamsSplitAndCollectToSelf(uint8): 133 | ||
- testSqueezeViewVsActual(uint8,uint8): 128 | ||
- testSqueeze(uint8,uint8): 128 | ||
- testSetStreamBalance(uint8,int128): 128 | ||
- addStreamWithClamping(uint8,uint8,uint160,uint32,uint32,int128): 125 | ||
- removeAllSplits(uint8): 118 | ||
- testSplittableAfterSplit(uint8): 113 | ||
- testSqueezableVsReceived(uint8): 111 | ||
- testBalanceAtInFuture(uint8,uint8,uint160): 108 | ||
- testRemoveStreamShouldNotRevert(uint8,uint256): 103 | ||
- invariantWithdrawAllTokensShouldNotRevert(): 103 | ||
- collect(uint8,uint8): 101 | ||
- invariantAmtPerSecVsMinAmtPerSec(uint8,uint256): 98 | ||
- testSqueezableAmountCantBeWithdrawn(uint8,uint8): 97 | ||
- split(uint8): 97 | ||
- invariantWithdrawAllTokens(): 95 | ||
- testReceiveStreams(uint8,uint32): 93 | ||
- invariantAccountingVsTokenBalance(): 92 | ||
- testSqueezeWithFuzzedHistoryShouldNotRevert(uint8,uint8,uint256,bytes32): 91 | ||
- testSqueezableAmountCantBeUndone(uint8,uint8,uint160,uint32,uint32,int128): 87 | ||
- testCollect(uint8,uint8): 86 | ||
- testSetStreamBalanceWithdrawAllShouldNotRevert(uint8): 86 | ||
- testAddStreamShouldNotRevert(uint8,uint8,uint160,uint32,uint32,int128): 85 | ||
- testReceiveStreamsShouldNotRevert(uint8): 84 | ||
- addSplitsReceiver(uint8,uint8,uint32): 84 | ||
- setStreamBalanceWithClamping(uint8,int128): 82 | ||
- addSplitsReceiverWithClamping(uint8,uint8,uint32): 80 | ||
- testSetStreamBalanceShouldNotRevert(uint8,int128): 80 | ||
- testSplitShouldNotRevert(uint8): 80 | ||
- squeezeAllAndReceiveAndSplitAndCollectToSelf(uint8): 79 | ||
- addStreamImmediatelySqueezable(uint8,uint8,uint160): 79 | ||
- testSetSplitsShouldNotRevert(uint8,uint8,uint32): 78 | ||
- invariantSumAmtDeltaIsZero(uint8): 78 | ||
- testReceiveStreamsViewConsistency(uint8,uint32): 76 | ||
- squeezeToSelf(uint8): 74 | ||
- collectToSelf(uint8): 72 | ||
- setStreams(uint8,uint8,uint160,uint32,uint32,int128): 70 | ||
- receiveStreamsAllCycles(uint8): 69 | ||
- invariantWithdrawShouldAlwaysFail(uint256): 68 | ||
- addStream(uint8,uint8,uint160,uint32,uint32,int128): 68 | ||
- squeezeWithFuzzedHistory(uint8,uint8,uint256,bytes32): 67 | ||
- setStreamsWithClamping(uint8,uint8,uint160,uint32,uint32,int128): 67 | ||
- splitAndCollectToSelf(uint8): 67 | ||
- testSqueezeWithFullyHashedHistory(uint8,uint8): 65 | ||
- give(uint8,uint8,uint128): 65 | ||
- setSplits(uint8,uint8,uint32): 65 | ||
- testSqueezeTwice(uint8,uint8,uint256,bytes32): 65 | ||
- testSetStreamsShouldNotRevert(uint8,uint8,uint160,uint32,uint32,int128): 64 | ||
- squeezeAllSenders(uint8): 63 | ||
- removeStream(uint8,uint256): 62 | ||
- testCollectableAfterSplit(uint8): 58 | ||
- testCollectShouldNotRevert(uint8,uint8): 56 | ||
- testReceiveStreamsViewVsActual(uint8,uint32): 55 | ||
- receiveStreams(uint8,uint32): 55 | ||
- setSplitsWithClamping(uint8,uint8,uint32): 55 | ||
- testGiveShouldNotRevert(uint8,uint8,uint128): 47 | ||
- setStreamBalance(uint8,int128): 47 | ||
- squeezeWithDefaultHistory(uint8,uint8): 45 | ||
- testSplitViewVsActual(uint8): 45 | ||
- testAddSplitsShouldNotRevert(uint8,uint8,uint32): 30 | ||
- testSqueezeWithDefaultHistoryShouldNotRevert(uint8,uint8): 23 | ||
|
||
Number of Unique Methods: 65 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import os | ||
import json | ||
import sys | ||
|
||
def load_json_files_from_subdirectory(subdirectory): | ||
json_data = [] | ||
for root, _, files in os.walk(subdirectory): | ||
for file in files: | ||
if file.endswith('.json'): | ||
with open(os.path.join(root, file), 'r') as f: | ||
data = json.load(f) | ||
json_data.extend(data) | ||
return json_data | ||
|
||
def extract_unique_methods(transactions): | ||
unique_methods = set() | ||
for tx in transactions: | ||
call_data = tx.get('call', {}) | ||
data_abi_values = call_data.get('dataAbiValues', {}) | ||
method_signature = data_abi_values.get('methodSignature', '') | ||
if method_signature: | ||
unique_methods.add(method_signature) | ||
return unique_methods | ||
|
||
def compare_methods(subdirectory1, subdirectory2): | ||
transactions1 = load_json_files_from_subdirectory(subdirectory1) | ||
transactions2 = load_json_files_from_subdirectory(subdirectory2) | ||
|
||
unique_methods1 = extract_unique_methods(transactions1) | ||
unique_methods2 = extract_unique_methods(transactions2) | ||
|
||
only_in_subdir1 = unique_methods1 - unique_methods2 | ||
only_in_subdir2 = unique_methods2 - unique_methods1 | ||
|
||
return only_in_subdir1, only_in_subdir2 | ||
|
||
def main(subdirectory1, subdirectory2): | ||
|
||
only_in_subdir1, only_in_subdir2 = compare_methods(subdirectory1, subdirectory2) | ||
|
||
print(f"Methods only in {subdirectory1}:") | ||
if len(only_in_subdir1) == 0: | ||
print(" <None>") | ||
else: | ||
for method in only_in_subdir1: | ||
print(f"- {method}") | ||
print("\n") | ||
|
||
|
||
print(f"Methods only in {subdirectory2}:") | ||
if len(only_in_subdir2) == 0: | ||
print(" <None>") | ||
else: | ||
for method in only_in_subdir2: | ||
print(f"- {method}") | ||
print("\n") | ||
|
||
if __name__ == '__main__': | ||
if len(sys.argv) != 3: | ||
print("Usage: python3 unique.py <corpus1> <corpus2>") | ||
print("Compares the unique methods in the two given corpora.") | ||
sys.exit(1) | ||
main(sys.argv[1], sys.argv[2]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import os | ||
import json | ||
from collections import Counter | ||
import sys | ||
|
||
def load_json_files_from_subdirectory(subdirectory): | ||
json_data = [] | ||
for root, _, files in os.walk(subdirectory): | ||
for file in files: | ||
if file.endswith('.json'): | ||
with open(os.path.join(root, file), 'r') as f: | ||
data = json.load(f) | ||
json_data.append(data) | ||
return json_data | ||
|
||
|
||
def analyze_transactions(transactions, method_counter): | ||
|
||
for tx in transactions: | ||
call_data = tx.get('call', {}) | ||
data_abi_values = call_data.get('dataAbiValues', {}) | ||
method_signature = data_abi_values.get('methodSignature', '') | ||
|
||
method_counter[method_signature] += 1 | ||
|
||
|
||
|
||
def main(subdirectory): | ||
transaction_seqs = load_json_files_from_subdirectory(subdirectory) | ||
|
||
method_counter = Counter() | ||
total_length = 0 | ||
|
||
for seq in transaction_seqs: | ||
analyze_transactions(seq, method_counter) | ||
total_length += len(seq) | ||
|
||
average_length = total_length // len(transaction_seqs) | ||
|
||
print(f"Number of Sequences in {subdirectory}: {len(transaction_seqs)}") | ||
print("\n") | ||
|
||
print(f"Average Length of Transactions List: {average_length}") | ||
print("\n") | ||
print("Frequency of Methods Called:") | ||
for method, count in method_counter.most_common(): | ||
print(f"- {method}: {count}") | ||
print("\n") | ||
print(f"Number of Unique Methods: {len(method_counter)}") | ||
print("\n") | ||
|
||
if __name__ == '__main__': | ||
if len(sys.argv) != 2: | ||
print("Usage: python3 corpus_stats.py <corpus>") | ||
print("Computes statistics on the transactions in the given corpus.") | ||
sys.exit(1) | ||
main(sys.argv[1]) |