Skip to content

Commit

Permalink
feat: show logs when not using structlogs
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Jun 25, 2024
1 parent e793532 commit a5e94ca
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 13 deletions.
38 changes: 33 additions & 5 deletions src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,9 @@ def _enrich_calltree(self, call: dict, **kwargs) -> dict:
return call

if events := call.get("events"):
call["events"] = self._enrich_trace_events(events, contract_type, address)
call["events"] = self._enrich_trace_events(
events, address=address, contract_type=contract_type
)

method_abi: Optional[Union[MethodABI, ConstructorABI]] = None
if is_create:
Expand Down Expand Up @@ -1308,19 +1310,45 @@ def _enrich_returndata(self, call: dict, method_abi: MethodABI, **kwargs) -> dic
return call

def _enrich_trace_events(
self, events: list[dict], contract_type: ContractType, address: AddressType
self,
events: list[dict],
address: Optional[AddressType] = None,
contract_type: Optional[ContractType] = None,
) -> list[dict]:
return [self._enrich_trace_event(e, contract_type, address) for e in events]
return [
self._enrich_trace_event(e, address=address, contract_type=contract_type)
for e in events
]

def _enrich_trace_event(
self, event: dict, contract_type: ContractType, address: AddressType
self,
event: dict,
address: Optional[AddressType] = None,
contract_type: Optional[ContractType] = None,
) -> dict:
if "topics" not in event or len(event["topics"]) < 1:
# Already enriched or wrong.
return event

elif not address:
address = event.get("address")
if not address:
# Cannot enrich further w/o an address.
return event

if not contract_type:
try:
contract_type = self.chain_manager.contracts.get(address)
except Exception as err:
logger.debug(f"Error getting contract type during event enrichment: {err}")
return event

if not contract_type:
# Cannot enrich further w/o an contract type.
return event

# The selector is always the first topic.
selector = event["topics"][0]
selector = event["topics"][0].hex()

if selector not in contract_type.identifier_lookup:
# Unable to enrich using this contract type.
Expand Down
52 changes: 44 additions & 8 deletions src/ape_ethereum/trace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import sys
from abc import abstractmethod
from collections import defaultdict
from collections.abc import Iterable, Iterator, Sequence
from enum import Enum
from functools import cached_property
Expand Down Expand Up @@ -218,9 +219,7 @@ def try_get_revert_msg(c) -> Optional[str]:

def show(self, verbose: bool = False, file: IO[str] = sys.stdout):
call = self.enriched_calltree

# If the trace-approach was struct-logs, the events emitted
# are present in their calls.
approaches_handling_events = (TraceApproach.GETH_STRUCT_LOG_PARSE,)

failed = call.get("failed", False)
revert_message = None
Expand All @@ -244,6 +243,40 @@ def show(self, verbose: bool = False, file: IO[str] = sys.stdout):
if sender := self.transaction.get("from"):
console.print(f"tx.origin=[{TraceStyles.CONTRACTS}]{sender}[/]")

if self.call_trace_approach not in approaches_handling_events and hasattr(
self._ecosystem, "_enrich_trace_events"
):
# We must manually inject the contract logs.
if logs := self.transaction.get("logs", []):
enriched_events = self._ecosystem._enrich_trace_events(logs)
event_counter = defaultdict(list)
for evt in enriched_events:
name = evt.get("name")
calldata = evt.get("calldata")

if not name or not calldata:
continue

tuple_key = (
name,
",".join(f"{k}={v}" for k, v in calldata.items()),
)
event_counter[tuple_key].append(evt)

if event_counter:
console.print("Events emitted:")

for evt_tup, events in event_counter.items():
count = len(events)

# NOTE: Using similar style to gas-cost on purpose.
suffix = f"[[{TraceStyles.GAS_COST}]x{count}[/]]" if count > 1 else ""

evt_tree = _create_event_tree(events[0], suffix=suffix)
console.print(evt_tree)

# else: the events are already included in the right spots.

console.print(root)

def get_gas_report(self, exclude: Optional[Sequence[ContractFunctionPath]] = None) -> GasReport:
Expand Down Expand Up @@ -541,8 +574,8 @@ def parse_rich_tree(call: dict, verbose: bool = False) -> Tree:
return tree


def _create_event_tree(event: dict) -> Tree:
signature = _event_to_str(event, stylize=True)
def _create_event_tree(event: dict, suffix: str = "") -> Tree:
signature = _event_to_str(event, stylize=True, suffix=suffix)
return Tree(signature)


Expand Down Expand Up @@ -605,10 +638,13 @@ def _call_to_str(call: dict, stylize: bool = False, verbose: bool = False) -> st
return signature


def _event_to_str(event: dict, stylize: bool = False) -> str:
name = event["name"]
def _event_to_str(event: dict, stylize: bool = False, suffix: str = "") -> str:
# NOTE: Some of the styles are matching others parts of the trace,
# even though the 'name' is a bit misleading.
name = f"[{TraceStyles.METHODS}]{event['name']}[/]" if stylize else event["name"]
arguments_str = _get_inputs_str(event.get("calldata"), stylize=stylize)
return f"emit {name}{arguments_str}"
prefix = f"[{TraceStyles.CONTRACTS}]log[/]" if stylize else "log"
return f"{prefix} {name}{arguments_str}{suffix}"


def _create_tree(call: dict, verbose: bool = False) -> Tree:
Expand Down

0 comments on commit a5e94ca

Please sign in to comment.