Skip to content

Commit

Permalink
Merge pull request #2616 from nisedo/dev
Browse files Browse the repository at this point in the history
Add entry-points printer to identify all externally accessible state-changing functions
  • Loading branch information
smonicas authored Feb 3, 2025
2 parents cacf6f6 + 0d2d548 commit 61fa9ec
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,11 @@ For more information, see

### Quick Review Printers

* `human-summary`: [Print a human-readable summary of the contracts](https://github.com/crytic/slither/wiki/Printer-documentation#human-summary)
* `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph)
* `contract-summary`: [Print a summary of the contracts](https://github.com/crytic/slither/wiki/Printer-documentation#contract-summary)
* `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/crytic/slither/wiki/Printer-documentation#loc)
* `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary)
* `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph)
* `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary)
* `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc)
* `entry-points`: [Print all the state-changing entry point functions of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#entry-points)

### In-Depth Review Printers

Expand Down
1 change: 1 addition & 0 deletions slither/printers/all_printers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
from .functions.dominator import Dominator
from .summary.martin import Martin
from .summary.cheatcodes import CheatcodePrinter
from .summary.entry_points import PrinterEntryPoints
94 changes: 94 additions & 0 deletions slither/printers/summary/entry_points.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
Module printing all the state-changing entry point functions of the contracts
"""

from slither.printers.abstract_printer import AbstractPrinter
from slither.core.declarations.function_contract import FunctionContract
from slither.utils.colors import Colors
from slither.utils.output import Output
from slither.utils.myprettytable import MyPrettyTable


class PrinterEntryPoints(AbstractPrinter):

ARGUMENT = "entry-points"
HELP = "Print all the state-changing entry point functions of the contracts"

WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#entry-points"

def output(self, _filename) -> Output:
"""
_filename is not used
Args:
_filename(string)
"""
all_contracts = []

for contract in sorted(
(
c
for c in self.contracts
if not c.is_interface
and not c.is_library
and not c.is_abstract
and "lib/" not in c.source_mapping.filename.absolute
and "node_modules/" not in c.source_mapping.filename.absolute
and not any(
mock in c.source_mapping.filename.absolute.lower() for mock in ["mock", "mocks"]
)
),
key=lambda x: x.name,
):
entry_points = [
f
for f in contract.functions
if (
f.visibility in ["public", "external"]
and isinstance(f, FunctionContract)
and not f.is_constructor
and not f.view
and not f.pure
and not f.contract_declarer.is_interface
and not f.contract_declarer.is_library
and not f.is_shadowed
)
]

if not entry_points:
continue

table = MyPrettyTable(["Function", "Modifiers", "Inherited From"])
contract_info = [
f"\nContract {Colors.BOLD}{Colors.YELLOW}{contract.name}{Colors.END}"
f" ({contract.source_mapping})"
]

for f in sorted(
entry_points,
key=lambda x: (x.visibility != "external", x.visibility != "public", x.full_name),
):
modifier_list = [m.name for m in f.modifiers]
if f.payable:
modifier_list.append("payable")
modifiers = ", ".join(modifier_list) if modifier_list else ""
inherited = f"{f.contract_declarer.name}" if f.contract_declarer != contract else ""

name_parts = f.full_name.split("(", 1)
function_name = (
f"{Colors.BOLD}{Colors.RED}{name_parts[0]}{Colors.END}" f"({name_parts[1]}"
)

table.add_row(
[
function_name,
f"{Colors.GREEN}{modifiers}{Colors.END}" if modifiers else "",
f"{Colors.MAGENTA}{inherited}{Colors.END}" if inherited else "",
]
)

contract_info.append(str(table))
all_contracts.append("\n".join(contract_info))

info = "\n".join(all_contracts) if all_contracts else ""
self.info(info)
return self.generate_output(info)

0 comments on commit 61fa9ec

Please sign in to comment.