Detectors and printers output .dot files. All these files are saved in the current directory by default. User can use --dest option to select the destination directory. When user uses this, all the files that are generated in that run will be saved in the selected directory. Most of the times users will not use the --dest option and even if used, user has to select the directory for every run of the tool.
We can use a standard directory structure for tealer output files.
All files will be saved in the default directory tealer-export.
Assuming the users run tealer on multiple contracts, each contract should have a separate sub-directory.
Each of the detectors could generate one or more dot files to represent the output. It makes sense to have a separate directory to save the output files of each of the detectors.
Printers generating multiple files will have a separate directory. Printers generating the single files will save in the main directory.
Directory structure:
root_directory = "tealer-export"
contract_directory = f"teal.contract_name"
main_directory = f"{root_directory}/{contract_directory}"
printer_directory = f"{main_directory}" if printer_outputs_single_file else f"{main_directory}/{printer.NAME}"
detector_directory = f"{main_directory}/{detector.NAME}"
# filenames of detectors
for index, output in enumerate(outputs):
file_location = f"{detector_directory}/{detector.NAME}-{index}.{file-extension}" # file-extension is dot
Contract Name:
# __main__.py fetch_contract function
def fetch_contract(args: argparse.Namespace) -> Tuple[str, str]:
program: str = args.program
network: str = args.network
b32_regex = "[A-Z2-7]+"
if program.isdigit():
# is a number so a app id
print(f'Fetching application using id "{program}"')
# contract_name = f"app_{appid}", ex: app_991196662
return get_application_using_app_id(network, int(program)), f"app_{program}"
if len(program) == 52 and re.fullmatch(b32_regex, program) is not None:
# is a txn id: base32 encoded. length after encoding == 52
print(f'Fetching logic-sig contract that signed the transaction "{program}"')
# contract_name = f"txn_{txn_id[:8].lower()}"
return logic_sig_from_txn_id(network, program), f"txn_{program[:8].lower()}"
if len(program) == 58 and re.fullmatch(b32_regex, program) is not None:
# is a address. base32 encoded. length after encoding == 58
print(f'Fetching logic-sig of contract account "{program}"')
# contract_name = f"lsig_{address[:8].lower()}"
return logic_sig_from_contract_account(network, program), f"lsig_{program[:8].lower()}"
# file path
print(f'Reading contract from file: "{program}"')
try:
contract_name = program[:-len(".teal")] if program.endswith(".teal") else program
contract_name = contract_name.lower()
with open(program, encoding="utf-8") as f:
return f.read(), contract_name
except FileNotFoundError as e:
raise TealerException from e
Its better to remove --dest option if we use this directory structure.
Detectors and printers output
.dot
files. All these files are saved in the current directory by default. User can use--dest
option to select the destination directory. When user uses this, all the files that are generated in that run will be saved in the selected directory. Most of the times users will not use the--dest
option and even if used, user has to select the directory for every run of the tool.We can use a standard directory structure for tealer output files.
All files will be saved in the default directory
tealer-export
. Assuming the users run tealer on multiple contracts, each contract should have a separate sub-directory.Each of the detectors could generate one or more dot files to represent the output. It makes sense to have a separate directory to save the output files of each of the detectors.
Printers either
human-summary
)call-graph
,cfg
)subroutine-cfg
,transaction-context
)Printers generating multiple files will have a separate directory. Printers generating the single files will save in the main directory.
Directory structure:
Contract Name:
Its better to remove
--dest
option if we use this directory structure.