import re
import requests
import difflib

API_KEY = "<TRUFFLEHOG_REDACTED_BSCSCAN>"
BASE_URL = "https://api.bscscan.com/api"
similarity_threshold = 0.9

def remove_comments(source_code):
    source_code = re.sub(r"//.", "", source_code)
    source_code = re.sub(r"/*[\s\S]?*/", "", source_code)
    return source_code

def get_contract_source_code(address):
    params = {
        "module": "contract",
        "action": "getsourcecode",
        "address": address,
        "apiKey": API_KEY
    }

    response = requests.get(BASE_URL, params=params)
    data = response.json()

    if data["status"] == "1":
        source_code = data["result"][0]["SourceCode"]
        return remove_comments(source_code)
    else:
        return None

def jaccard_similarity(str1, str2):
    a = set(str1.split())
    b = set(str2.split())
    c = a.intersection(b)
    return float(len(c)) / (len(a) + len(b) - len(c))

def find_similar_contracts(reference_addresses, candidate_addresses):
    reference_source_codes = {}
    for reference_address in reference_addresses:
        source_code = get_contract_source_code(reference_address)
        if source_code is not None:
            reference_source_codes[reference_address] = source_code

    if not reference_source_codes:
        print("No source code found for reference contracts")
        return []

    similar_contracts = {}
    for address in candidate_addresses:
        candidate_source_code = get_contract_source_code(address)
        if candidate_source_code is not None:
            for reference_address, reference_source_code in reference_source_codes.items():
                similarity = jaccard_similarity(candidate_source_code, reference_source_code)
                if similarity >= similarity_threshold:
                    if reference_address not in similar_contracts:
                        similar_contracts[reference_address] = [(address, similarity)]
                    else:
                        similar_contracts[reference_address].append((address, similarity))

    return similar_contracts

def print_code_difference(reference_code, candidate_code):
    reference_lines = reference_code.splitlines()
    candidate_lines = candidate_code.splitlines()
    diff = difflib.unified_diff(reference_lines, candidate_lines)

    for line in diff:
        print(line)

if __name__ == "__main__":
    reference_addresses = ["0x1f5FbCF2787140b2F05081Fd9f69Bc0F436B13C1"]
    candidate_addresses = ["0xa6C2d7788830E5ef286db79295C533F402Cca734"]

    similar_contracts = find_similar_contracts(reference_addresses, candidate_addresses)
    print("Contracts with similar source code (ignoring comments):")
    for reference_address, similar_addresses in similar_contracts.items():
        reference_code = get_contract_source_code(reference_address)

        print(f"Reference contract: {reference_address}")
        for address, similarity in similar_addresses:
            candidate_code = get_contract_source_code(address)

            print(f"Similar contract: {address} with a similarity of {similarity:.2f}")

            if similarity < 1.0:
                print("Code differences:")
                print_code_difference(reference_code, candidate_code)
                print("\n")

The code above gives an error


C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\venv\Scripts\python.exe C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\main.py 
Traceback (most recent call last):
  File "C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\main.py", line 74, in <module>
    similar_contracts = find_similar_contracts(reference_addresses, candidate_addresses)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\main.py", line 40, in find_similar_contracts
    source_code = get_contract_source_code(reference_address)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\main.py", line 27, in get_contract_source_code
    return remove_comments(source_code)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\PycharmProjects\ByteCodes\CodeDifferences\main.py", line 11, in remove_comments
    source_code = re.sub(r"/*[\s\S]?*/", "", source_code)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\__init__.py", line 185, in sub
    return _compile(pattern, flags).sub(repl, string, count)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\__init__.py", line 294, in _compile
    p = _compiler.compile(pattern, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\_compiler.py", line 743, in compile
    p = _parser.parse(p, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py", line 980, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py", line 455, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\AshotxXx\AppData\Local\Programs\Python\Python311\Lib\re\_parser.py", line 685, in _parse
    raise source.error("multiple repeat",
re.error: multiple repeat at position 9

Process finished with exit code 1

Fix it