Skip to content

Commit d93361e

Browse files
authored
Merge branch 'safe-global:master' into master
2 parents b67b64d + f6f1dcf commit d93361e

35 files changed

+4369
-1697
lines changed

gnosis/eth/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
UnknownAccount,
1818
)
1919
from .ethereum_network import EthereumNetwork, EthereumNetworkNotSupported
20-
from .exceptions import InvalidERC20Info, InvalidERC721Info, ParityTraceDecodeException
20+
from .exceptions import InvalidERC20Info, InvalidERC721Info, TraceDecodeException
2121

2222
__all__ = [
2323
"EthereumClient",
@@ -39,5 +39,5 @@
3939
"EthereumNetworkNotSupported",
4040
"InvalidERC20Info",
4141
"InvalidERC721Info",
42-
"ParityTraceDecodeException",
42+
"TraceDecodeException",
4343
]

gnosis/eth/abis/__init__.py

Whitespace-only changes.

gnosis/eth/abis/multicall.py

+250
Large diffs are not rendered by default.

gnosis/eth/eip712/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import re
2828
from typing import Any, Dict, List, Union
2929

30-
from eth_abi import encode_abi
30+
from eth_abi import encode as encode_abi
3131
from eth_account import Account
3232
from eth_typing import Hash32, HexStr
3333
from hexbytes import HexBytes

gnosis/eth/ethereum_client.py

+44-50
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,23 @@
3030
transaction_result_formatter,
3131
)
3232
from web3._utils.normalizers import BASE_RETURN_NORMALIZERS
33-
from web3.contract import ContractFunction
33+
from web3.contract.contract import ContractFunction
3434
from web3.datastructures import AttributeDict
3535
from web3.exceptions import (
36-
BadFunctionCallOutput,
3736
BlockNotFound,
3837
TimeExhausted,
3938
TransactionNotFound,
39+
Web3Exception,
4040
)
4141
from web3.middleware import geth_poa_middleware, simple_cache_middleware
4242
from web3.types import (
4343
BlockData,
4444
BlockIdentifier,
45+
BlockTrace,
4546
FilterParams,
47+
FilterTrace,
4648
LogReceipt,
4749
Nonce,
48-
ParityBlockTrace,
49-
ParityFilterParams,
50-
ParityFilterTrace,
5150
TxData,
5251
TxParams,
5352
TxReceipt,
@@ -80,9 +79,9 @@
8079
InvalidNonce,
8180
NonceTooHigh,
8281
NonceTooLow,
83-
ParityTraceDecodeException,
8482
ReplacementTransactionUnderpriced,
8583
SenderAccountNotFoundInNode,
84+
TraceDecodeException,
8685
TransactionAlreadyImported,
8786
TransactionGasPriceTooLow,
8887
TransactionQueueLimitReached,
@@ -96,7 +95,7 @@
9695

9796
def tx_with_exception_handling(func):
9897
"""
99-
Parity
98+
Parity / OpenEthereum
10099
- https://github.com/openethereum/openethereum/blob/main/rpc/src/v1/helpers/errors.rs
101100
Geth
102101
- https://github.com/ethereum/go-ethereum/blob/master/core/error.go
@@ -133,7 +132,7 @@ def tx_with_exception_handling(func):
133132
def with_exception_handling(*args, **kwargs):
134133
try:
135134
return func(*args, **kwargs)
136-
except ValueError as exc:
135+
except (Web3Exception, ValueError) as exc:
137136
str_exc = str(exc).lower()
138137
for reason, custom_exception in error_with_exception.items():
139138
if reason.lower() in str_exc:
@@ -290,7 +289,7 @@ def batch_call_custom(
290289
else:
291290
output_type = payload["output_type"]
292291
try:
293-
decoded_values = self.w3.codec.decode_abi(
292+
decoded_values = eth_abi.decode(
294293
output_type, HexBytes(result["result"])
295294
)
296295
normalized_data = map_abi_data(
@@ -430,7 +429,7 @@ def _decode_transfer_log(
430429
if topics_len == 1:
431430
# Not standard Transfer(address from, address to, uint256 unknown)
432431
# 1 topic (transfer topic)
433-
_from, to, unknown = eth_abi.decode_abi(
432+
_from, to, unknown = eth_abi.decode(
434433
["address", "address", "uint256"], HexBytes(data)
435434
)
436435
return {"from": _from, "to": to, "unknown": unknown}
@@ -439,7 +438,7 @@ def _decode_transfer_log(
439438
# 3 topics (transfer topic + from + to)
440439
try:
441440
value_data = HexBytes(data)
442-
value = eth_abi.decode_single("uint256", value_data)
441+
value = eth_abi.decode(["uint256"], value_data)[0]
443442
except DecodingError:
444443
logger.warning(
445444
"Cannot decode Transfer event `uint256 value` from data=%s",
@@ -450,7 +449,7 @@ def _decode_transfer_log(
450449
from_to_data = b"".join(topics[1:])
451450
_from, to = (
452451
fast_to_checksum_address(address)
453-
for address in eth_abi.decode_abi(
452+
for address in eth_abi.decode(
454453
["address", "address"], from_to_data
455454
)
456455
)
@@ -464,7 +463,7 @@ def _decode_transfer_log(
464463
elif topics_len == 4:
465464
# ERC712 Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
466465
# 4 topics (transfer topic + from + to + tokenId)
467-
_from, to, token_id = eth_abi.decode_abi(
466+
_from, to, token_id = eth_abi.decode(
468467
["address", "address", "uint256"], b"".join(topics[1:])
469468
)
470469
_from, to = [
@@ -585,9 +584,9 @@ def get_info(self, erc20_address: str) -> Erc20Info:
585584
results = [HexBytes(r["result"]) for r in response_json]
586585
name = decode_string_or_bytes32(results[0])
587586
symbol = decode_string_or_bytes32(results[1])
588-
decimals = self.ethereum_client.w3.codec.decode_single("uint8", results[2])
587+
decimals = eth_abi.decode(["uint8"], results[2])[0]
589588
return Erc20Info(name, symbol, decimals)
590-
except (ValueError, BadFunctionCallOutput, DecodingError) as e:
589+
except (Web3Exception, DecodingError, ValueError) as e:
591590
raise InvalidERC20Info from e
592591

593592
def get_total_transfer_history(
@@ -670,7 +669,7 @@ def get_total_transfer_history(
670669
topic_0 = self.TRANSFER_TOPIC.hex()
671670
if addresses:
672671
addresses_encoded = [
673-
HexBytes(eth_abi.encode_single("address", address)).hex()
672+
HexBytes(eth_abi.encode(["address"], [address])).hex()
674673
for address in addresses
675674
]
676675
# Topics for transfer `to` and `from` an address
@@ -752,7 +751,7 @@ def get_transfer_history(
752751
if to_address:
753752
argument_filters["to"] = to_address
754753

755-
return erc20.events.Transfer.createFilter(
754+
return erc20.events.Transfer.create_filter(
756755
fromBlock=from_block,
757756
toBlock=to_block,
758757
address=token_address,
@@ -902,8 +901,7 @@ def get_token_uris(
902901
]
903902

904903

905-
class ParityManager(EthereumClientManager):
906-
# TODO Test with mock
904+
class TracingManager(EthereumClientManager):
907905
def _decode_trace_action(self, action: Dict[str, Any]) -> Dict[str, Any]:
908906
decoded = {}
909907

@@ -935,6 +933,15 @@ def _decode_trace_action(self, action: Dict[str, Any]) -> Dict[str, Any]:
935933
if "refundAddress" in action:
936934
decoded["refundAddress"] = fast_to_checksum_address(action["refundAddress"])
937935

936+
# REWARD
937+
if "author" in action:
938+
decoded["author"] = action[
939+
"author"
940+
] # TODO Web3 is not performing checksum decoding
941+
942+
if "rewardType" in action:
943+
decoded["rewardType"] = action["rewardType"]
944+
938945
return decoded
939946

940947
def _decode_trace_result(self, result: Dict[str, Any]) -> Dict[str, Any]:
@@ -955,7 +962,7 @@ def _decode_trace_result(self, result: Dict[str, Any]) -> Dict[str, Any]:
955962
return decoded
956963

957964
def _decode_traces(
958-
self, traces: Sequence[Union[ParityBlockTrace, ParityFilterTrace]]
965+
self, traces: Sequence[Union[BlockTrace, FilterTrace]]
959966
) -> List[Dict[str, Any]]:
960967
new_traces: List[Dict[str, Any]] = []
961968
for trace in traces:
@@ -964,7 +971,7 @@ def _decode_traces(
964971
elif isinstance(trace, AttributeDict):
965972
trace_copy = trace.__dict__.copy()
966973
else:
967-
raise ParityTraceDecodeException(
974+
raise TraceDecodeException(
968975
"Expected dictionary, but found unexpected trace %s" % trace
969976
)
970977
new_traces.append(trace_copy)
@@ -973,6 +980,9 @@ def _decode_traces(
973980
if "result" in trace and trace["result"]:
974981
trace_copy["result"] = self._decode_trace_result(trace["result"])
975982
trace_copy["action"] = self._decode_trace_action(trace["action"])
983+
trace_copy["blockHash"] = HexBytes(trace_copy["blockHash"])
984+
if "transactionHash" in trace_copy: # Reward traces don't have txHash
985+
trace_copy["transactionHash"] = HexBytes(trace_copy["transactionHash"])
976986
return new_traces
977987

978988
def filter_out_errored_traces(
@@ -1064,16 +1074,8 @@ def get_next_traces(
10641074
traces.append(trace)
10651075
return traces
10661076

1067-
def trace_block(self, block_identifier: BlockIdentifier) -> List[Dict[str, Any]]:
1068-
try:
1069-
return self._decode_traces(
1070-
self.slow_w3.parity.trace_block(block_identifier)
1071-
)
1072-
except ParityTraceDecodeException as exc:
1073-
logger.warning("Problem decoding trace: %s - Retrying", exc)
1074-
return self._decode_traces(
1075-
self.slow_w3.parity.trace_block(block_identifier)
1076-
)
1077+
def trace_block(self, block_identifier: BlockIdentifier) -> List[BlockTrace]:
1078+
return self.slow_w3.tracing.trace_block(block_identifier)
10771079

10781080
def trace_blocks(
10791081
self, block_identifiers: List[BlockIdentifier]
@@ -1100,28 +1102,24 @@ def trace_blocks(
11001102
if raw_tx:
11011103
try:
11021104
decoded_traces = self._decode_traces(raw_tx)
1103-
except ParityTraceDecodeException as exc:
1105+
except TraceDecodeException as exc:
11041106
logger.warning("Problem decoding trace: %s - Retrying", exc)
11051107
decoded_traces = self._decode_traces(raw_tx)
11061108
traces.append(decoded_traces)
11071109
else:
11081110
traces.append([])
11091111
return traces
11101112

1111-
def trace_transaction(self, tx_hash: EthereumHash) -> List[Dict[str, Any]]:
1113+
def trace_transaction(self, tx_hash: EthereumHash) -> List[FilterTrace]:
11121114
"""
11131115
:param tx_hash:
11141116
:return: List of internal txs for `tx_hash`
11151117
"""
1116-
try:
1117-
return self._decode_traces(self.slow_w3.parity.trace_transaction(tx_hash))
1118-
except ParityTraceDecodeException as exc:
1119-
logger.warning("Problem decoding trace: %s - Retrying", exc)
1120-
return self._decode_traces(self.slow_w3.parity.trace_transaction(tx_hash))
1118+
return self.slow_w3.tracing.trace_transaction(tx_hash)
11211119

11221120
def trace_transactions(
11231121
self, tx_hashes: Sequence[EthereumHash]
1124-
) -> List[List[Dict[str, Any]]]:
1122+
) -> List[List[FilterTrace]]:
11251123
"""
11261124
:param tx_hashes:
11271125
:return: For every `tx_hash` a list of internal txs (in the same order as the `tx_hashes` were provided)
@@ -1143,7 +1141,7 @@ def trace_transactions(
11431141
if raw_tx:
11441142
try:
11451143
decoded_traces = self._decode_traces(raw_tx)
1146-
except ParityTraceDecodeException as exc:
1144+
except TraceDecodeException as exc:
11471145
logger.warning("Problem decoding trace: %s - Retrying", exc)
11481146
decoded_traces = self._decode_traces(raw_tx)
11491147
traces.append(decoded_traces)
@@ -1159,7 +1157,7 @@ def trace_filter(
11591157
to_address: Optional[Sequence[ChecksumAddress]] = None,
11601158
after: Optional[int] = None,
11611159
count: Optional[int] = None,
1162-
) -> List[Dict[str, Any]]:
1160+
) -> List[FilterTrace]:
11631161
"""
11641162
Get events using ``trace_filter`` method
11651163
@@ -1236,7 +1234,7 @@ def trace_filter(
12361234
assert (
12371235
from_address or to_address
12381236
), "You must provide at least `from_address` or `to_address`"
1239-
parameters: ParityFilterParams = {}
1237+
parameters: FilterParams = {}
12401238
if after:
12411239
parameters["after"] = after
12421240
if count:
@@ -1250,11 +1248,7 @@ def trace_filter(
12501248
if to_address:
12511249
parameters["toAddress"] = to_address
12521250

1253-
try:
1254-
return self._decode_traces(self.slow_w3.parity.trace_filter(parameters))
1255-
except ParityTraceDecodeException as exc:
1256-
logger.warning("Problem decoding trace: %s - Retrying", exc)
1257-
return self._decode_traces(self.slow_w3.parity.trace_filter(parameters))
1251+
return self.slow_w3.tracing.trace_filter(parameters)
12581252

12591253

12601254
class EthereumClient:
@@ -1300,7 +1294,7 @@ def __init__(
13001294
self.slow_w3: Web3 = Web3(self.w3_slow_provider)
13011295
self.erc20: Erc20Manager = Erc20Manager(self)
13021296
self.erc721: Erc721Manager = Erc721Manager(self)
1303-
self.parity: ParityManager = ParityManager(self)
1297+
self.tracing: TracingManager = TracingManager(self)
13041298
self.batch_call_manager: BatchCallManager = BatchCallManager(self)
13051299
try:
13061300
if self.get_network() != EthereumNetwork.MAINNET:
@@ -1423,7 +1417,7 @@ def is_eip1559_supported(self) -> EthereumNetwork:
14231417
try:
14241418
self.w3.eth.fee_history(1, "latest", reward_percentiles=[50])
14251419
return True
1426-
except ValueError:
1420+
except (Web3Exception, ValueError):
14271421
return False
14281422

14291423
@cached_property
@@ -1607,7 +1601,7 @@ def estimate_gas(
16071601
tx["gasPrice"] = gas_price
16081602
try:
16091603
return self.w3.eth.estimate_gas(tx, block_identifier=block_identifier)
1610-
except ValueError:
1604+
except (Web3Exception, ValueError):
16111605
if (
16121606
block_identifier is not None
16131607
): # Geth does not support setting `block_identifier`

gnosis/eth/exceptions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class TransactionGasPriceTooLow(EthereumClientException):
5454
pass
5555

5656

57-
class ParityTraceDecodeException(EthereumClientException):
57+
class TraceDecodeException(EthereumClientException):
5858
pass
5959

6060

0 commit comments

Comments
 (0)