Skip to content

Commit

Permalink
Merge branch 'dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiko7454 authored Feb 20, 2024
2 parents 044c6be + 3163e24 commit c1cd3e5
Show file tree
Hide file tree
Showing 28 changed files with 142 additions and 59 deletions.
6 changes: 3 additions & 3 deletions .github/actions/upload-coverage/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ runs:
# This method has the limitation of 1 coverage file per run, limiting some coverage between online/offline tests.
- run: |
COVERAGE_UUID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "COVERAGE_UUID=${COVERAGE_UUID}" >> $GITHUB_OUTPUT
echo "COVERAGE_UUID=${COVERAGE_UUID}" >> "$GITHUB_OUTPUT"
if [ -f .coverage ]; then
mv .coverage .coverage.${COVERAGE_UUID}
fi
id: coverage-uuid
shell: bash
- uses: actions/upload-artifact@v3.1.0
- uses: actions/upload-artifact@v4
with:
name: coverage-data
name: coverage-data-${{ steps.coverage-uuid.outputs.COVERAGE_UUID }}
path: |
.coverage.*
*.lcov
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- build-release
steps:
- name: fetch dists
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: slither-dists
path: dist/
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ jobs:
- run: pip install coverage[toml]

- name: download coverage data
uses: actions/download-artifact@v3.0.2
uses: actions/download-artifact@v4
with:
name: coverage-data
pattern: coverage-data-*
merge-multiple: true

- name: combine coverage data
id: combinecoverage
Expand Down
3 changes: 2 additions & 1 deletion examples/scripts/possible_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def resolve_function(contract_name, function_name):
contract = contracts[0]
# Obtain the target function
target_function = next(
(function for function in contract.functions if function.name == function_name), None
(function for function in contract.functions_declared if function.name == function_name),
None,
)

# Verify we have resolved the function specified.
Expand Down
10 changes: 9 additions & 1 deletion slither/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,20 @@ def parse_args(

group_misc.add_argument(
"--triage-mode",
help="Run triage mode (save results in slither.db.json)",
help="Run triage mode (save results in triage database)",
action="store_true",
dest="triage_mode",
default=False,
)

group_misc.add_argument(
"--triage-database",
help="File path to the triage database (default: slither.db.json)",
action="store",
dest="triage_database",
default=defaults_flag_in_config["triage_database"],
)

group_misc.add_argument(
"--config-file",
help="Provide a config file (default: slither.config.json)",
Expand Down
6 changes: 6 additions & 0 deletions slither/core/compilation_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel
from slither.core.declarations.enum_top_level import EnumTopLevel
from slither.core.declarations.event_top_level import EventTopLevel
from slither.core.declarations.function_top_level import FunctionTopLevel
from slither.core.declarations.structure_top_level import StructureTopLevel
from slither.core.declarations.using_for_top_level import UsingForTopLevel
Expand Down Expand Up @@ -57,6 +58,7 @@ def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit
self.contracts: List[Contract] = []
self._structures_top_level: List[StructureTopLevel] = []
self._enums_top_level: List[EnumTopLevel] = []
self._events_top_level: List[EventTopLevel] = []
self._variables_top_level: List[TopLevelVariable] = []
self._functions_top_level: List[FunctionTopLevel] = []
self._using_for_top_level: List[UsingForTopLevel] = []
Expand Down Expand Up @@ -234,6 +236,10 @@ def structures_top_level(self) -> List[StructureTopLevel]:
def enums_top_level(self) -> List[EnumTopLevel]:
return self._enums_top_level

@property
def events_top_level(self) -> List[EventTopLevel]:
return self._events_top_level

@property
def variables_top_level(self) -> List[TopLevelVariable]:
return self._variables_top_level
Expand Down
2 changes: 2 additions & 0 deletions slither/core/declarations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from .contract import Contract
from .enum import Enum
from .event import Event
from .event_contract import EventContract
from .event_top_level import EventTopLevel
from .function import Function
from .import_directive import Import
from .modifier import Modifier
Expand Down
12 changes: 6 additions & 6 deletions slither/core/declarations/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType
from slither.core.declarations import (
Enum,
Event,
EventContract,
Modifier,
EnumContract,
StructureContract,
Expand Down Expand Up @@ -73,7 +73,7 @@ def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope

self._enums: Dict[str, "EnumContract"] = {}
self._structures: Dict[str, "StructureContract"] = {}
self._events: Dict[str, "Event"] = {}
self._events: Dict[str, "EventContract"] = {}
# map accessible variable from name -> variable
# do not contain private variables inherited from contract
self._variables: Dict[str, "StateVariable"] = {}
Expand Down Expand Up @@ -278,28 +278,28 @@ def enums_as_dict(self) -> Dict[str, "EnumContract"]:
###################################################################################

@property
def events(self) -> List["Event"]:
def events(self) -> List["EventContract"]:
"""
list(Event): List of the events
"""
return list(self._events.values())

@property
def events_inherited(self) -> List["Event"]:
def events_inherited(self) -> List["EventContract"]:
"""
list(Event): List of the inherited events
"""
return [e for e in self.events if e.contract != self]

@property
def events_declared(self) -> List["Event"]:
def events_declared(self) -> List["EventContract"]:
"""
list(Event): List of the events declared within the contract (not inherited)
"""
return [e for e in self.events if e.contract == self]

@property
def events_as_dict(self) -> Dict[str, "Event"]:
def events_as_dict(self) -> Dict[str, "EventContract"]:
return self._events

# endregion
Expand Down
24 changes: 2 additions & 22 deletions slither/core/declarations/event.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
from typing import List, Tuple, TYPE_CHECKING
from typing import List, Tuple

from slither.core.declarations.contract_level import ContractLevel
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.event_variable import EventVariable

if TYPE_CHECKING:
from slither.core.declarations import Contract


class Event(ContractLevel, SourceMapping):
class Event(SourceMapping):
def __init__(self) -> None:
super().__init__()
self._name = None
Expand Down Expand Up @@ -39,25 +35,9 @@ def full_name(self) -> str:
name, parameters = self.signature
return name + "(" + ",".join(parameters) + ")"

@property
def canonical_name(self) -> str:
"""Return the function signature as a str
Returns:
str: contract.func_name(type1,type2)
"""
return self.contract.name + "." + self.full_name

@property
def elems(self) -> List["EventVariable"]:
return self._elems

def is_declared_by(self, contract: "Contract") -> bool:
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract

def __str__(self) -> str:
return self.name
25 changes: 25 additions & 0 deletions slither/core/declarations/event_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from typing import TYPE_CHECKING

from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations import Event

if TYPE_CHECKING:
from slither.core.declarations import Contract


class EventContract(Event, ContractLevel):
def is_declared_by(self, contract: "Contract") -> bool:
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract

@property
def canonical_name(self) -> str:
"""Return the function signature as a str
Returns:
str: contract.func_name(type1,type2)
"""
return self.contract.name + "." + self.full_name
13 changes: 13 additions & 0 deletions slither/core/declarations/event_top_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import TYPE_CHECKING

from slither.core.declarations import Event
from slither.core.declarations.top_level import TopLevel

if TYPE_CHECKING:
from slither.core.scope.scope import FileScope


class EventTopLevel(Event, TopLevel):
def __init__(self, scope: "FileScope") -> None:
super().__init__()
self.file_scope: "FileScope" = scope
7 changes: 6 additions & 1 deletion slither/core/scope/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from slither.core.declarations import Contract, Import, Pragma
from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel
from slither.core.declarations.enum_top_level import EnumTopLevel
from slither.core.declarations.event_top_level import EventTopLevel
from slither.core.declarations.function_top_level import FunctionTopLevel
from slither.core.declarations.using_for_top_level import UsingForTopLevel
from slither.core.declarations.structure_top_level import StructureTopLevel
Expand Down Expand Up @@ -35,6 +36,7 @@ def __init__(self, filename: Filename) -> None:
# So we simplify the logic and have the scope fields all populated
self.custom_errors: Set[CustomErrorTopLevel] = set()
self.enums: Dict[str, EnumTopLevel] = {}
self.events: Dict[str, EventTopLevel] = {}
# Functions is a list instead of a dict
# Because we parse the function signature later on
# So we simplify the logic and have the scope fields all populated
Expand All @@ -54,7 +56,7 @@ def __init__(self, filename: Filename) -> None:
# Name -> type alias
self.type_aliases: Dict[str, TypeAlias] = {}

def add_accesible_scopes(self) -> bool:
def add_accesible_scopes(self) -> bool: # pylint: disable=too-many-branches
"""
Add information from accessible scopes. Return true if new information was obtained
Expand All @@ -74,6 +76,9 @@ def add_accesible_scopes(self) -> bool:
if not _dict_contain(new_scope.enums, self.enums):
self.enums.update(new_scope.enums)
learn_something = True
if not _dict_contain(new_scope.events, self.events):
self.events.update(new_scope.events)
learn_something = True
if not new_scope.functions.issubset(self.functions):
self.functions |= new_scope.functions
learn_something = True
Expand Down
2 changes: 2 additions & 0 deletions slither/core/slither_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ def _compute_offsets_to_ref_impl_decl(self): # pylint: disable=too-many-branche
self._compute_offsets_from_thing(event)
for enum in compilation_unit.enums_top_level:
self._compute_offsets_from_thing(enum)
for event in compilation_unit.events_top_level:
self._compute_offsets_from_thing(event)
for function in compilation_unit.functions_top_level:
self._compute_offsets_from_thing(function)
for st in compilation_unit.structures_top_level:
Expand Down
2 changes: 2 additions & 0 deletions slither/slither.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None:
self._exclude_dependencies = kwargs.get("exclude_dependencies", False)

triage_mode = kwargs.get("triage_mode", False)
triage_database = kwargs.get("triage_database", "slither.db.json")
self._triage_mode = triage_mode
self._previous_results_filename = triage_database

printers_to_run = kwargs.get("printers_to_run", "")
if printers_to_run == "echidna":
Expand Down
8 changes: 4 additions & 4 deletions slither/solc_parsing/declarations/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from slither.core.declarations import (
Modifier,
Event,
EventContract,
EnumContract,
StructureContract,
Function,
Expand Down Expand Up @@ -747,12 +747,12 @@ def analyze_events(self) -> None:
self._contract.events_as_dict.update(father.events_as_dict)

for event_to_parse in self._eventsNotParsed:
event = Event()
event = EventContract()
event.set_contract(self._contract)
event.set_offset(event_to_parse["src"], self._contract.compilation_unit)

event_parser = EventSolc(event, event_to_parse, self) # type: ignore
event_parser.analyze(self) # type: ignore
event_parser = EventSolc(event, event_to_parse, self._slither_parser) # type: ignore
event_parser.analyze() # type: ignore
self._contract.events_as_dict[event.full_name] = event
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing event {e}")
Expand Down
19 changes: 9 additions & 10 deletions slither/solc_parsing/declarations/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@
from slither.core.declarations.event import Event

if TYPE_CHECKING:
from slither.solc_parsing.declarations.contract import ContractSolc
from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc


class EventSolc:
"""
Event class
"""

def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSolc") -> None:
def __init__(
self, event: Event, event_data: Dict, slither_parser: "SlitherCompilationUnitSolc"
) -> None:

self._event = event
event.set_contract(contract_parser.underlying_contract)
self._parser_contract = contract_parser
self._slither_parser = slither_parser

if self.is_compact_ast:
self._event.name = event_data["name"]
Expand All @@ -41,18 +42,16 @@ def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSol

@property
def is_compact_ast(self) -> bool:
return self._parser_contract.is_compact_ast
return self._slither_parser.is_compact_ast

def analyze(self, contract: "ContractSolc") -> None:
def analyze(self) -> None:
for elem_to_parse in self._elemsNotParsed:
elem = EventVariable()
# Todo: check if the source offset is always here
if "src" in elem_to_parse:
elem.set_offset(
elem_to_parse["src"], self._parser_contract.underlying_contract.compilation_unit
)
elem.set_offset(elem_to_parse["src"], self._slither_parser.compilation_unit)
elem_parser = EventVariableSolc(elem, elem_to_parse)
elem_parser.analyze(contract)
elem_parser.analyze(self._slither_parser)

self._event.elems.append(elem)

Expand Down
3 changes: 3 additions & 0 deletions slither/solc_parsing/expressions/find_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def find_top_level(
if var_name in scope.enums:
return scope.enums[var_name], False

if var_name in scope.events:
return scope.events[var_name], False

for import_directive in scope.imports:
if import_directive.alias == var_name:
new_val = SolidityImportPlaceHolder(import_directive)
Expand Down
Loading

0 comments on commit c1cd3e5

Please sign in to comment.