Skip to content

Commit

Permalink
Merge pull request #1245 from SatoshiAndKin/issue1241
Browse files Browse the repository at this point in the history
Handle erigon traces and other failing transactions
  • Loading branch information
iamdefinitelyahuman committed Sep 11, 2021
2 parents 1e2741c + 856c0da commit 7497b0f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
4 changes: 2 additions & 2 deletions brownie/network/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from brownie._config import CONFIG, _get_data_folder
from brownie._singleton import _Singleton
from brownie.convert import Wei
from brownie.exceptions import BrownieEnvironmentError
from brownie.exceptions import BrownieEnvironmentError, CompilerError
from brownie.network import rpc
from brownie.project.build import DEPLOYMENT_KEYS
from brownie.utils.sql import Cursor
Expand Down Expand Up @@ -555,7 +555,7 @@ def _find_contract(address: Any) -> Any:
from brownie.network.contract import Contract

return Contract(address)
except ValueError:
except (ValueError, CompilerError):
pass


Expand Down
39 changes: 33 additions & 6 deletions brownie/network/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from hashlib import sha1
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
from warnings import warn

import black
import requests
Expand Down Expand Up @@ -671,12 +672,32 @@ def _get_trace(self) -> None:
self._modified_state = False
return

if isinstance(trace[0]["gas"], str):
# handle traces where numeric values are returned as hex (Nethermind)
# different nodes return slightly different formats. its really fun to handle
# geth/nethermind returns unprefixed and with 0-padding for stack and memory
# erigon returns 0x-prefixed and without padding (but their memory values are like geth)
fix_stack = False
for step in trace:
if not step["stack"]:
continue
check = step["stack"][0]
if not isinstance(check, str):
break
if check.startswith("0x"):
fix_stack = True
break

fix_gas = isinstance(trace[0]["gas"], str)

if fix_stack or fix_gas:
for step in trace:
step["gas"] = int(step["gas"], 16)
step["gasCost"] = int.from_bytes(HexBytes(step["gasCost"]), "big", signed=True)
step["pc"] = int(step["pc"], 16)
if fix_stack:
# for stack values, we need 32 bytes (64 chars) without the 0x prefix
step["stack"] = [HexBytes(s).hex()[2:].zfill(64) for s in step["stack"]]
if fix_gas:
# handle traces where numeric values are returned as hex (Nethermind)
step["gas"] = int(step["gas"], 16)
step["gasCost"] = int.from_bytes(HexBytes(step["gasCost"]), "big", signed=True)
step["pc"] = int(step["pc"], 16)

if self.status:
self._confirmed_trace(trace)
Expand All @@ -692,6 +713,9 @@ def _confirmed_trace(self, trace: Sequence) -> None:
if contract:
data = _get_memory(trace[-1], -1)
fn = contract.get_method_object(self.input)
if not fn:
warn(f"Unable to find function on {contract} for input {self.input}")
return
self._return_value = fn.decode_output(data)

def _reverted_trace(self, trace: Sequence) -> None:
Expand Down Expand Up @@ -992,8 +1016,11 @@ def _expand_trace(self) -> None:
)

def _add_internal_xfer(self, from_: str, to: str, value: str) -> None:
if not value.startswith("0x"):
value = f"0x{value}"

self._internal_transfers.append( # type: ignore
{"from": EthAddress(from_), "to": EthAddress(to), "value": Wei(f"0x{value}")}
{"from": EthAddress(from_), "to": EthAddress(to), "value": Wei(value)}
)

def _full_name(self) -> str:
Expand Down

0 comments on commit 7497b0f

Please sign in to comment.