Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Commit 32e48e2

Browse files
authored
Merge pull request #84 from crytic/add-support-for-ethrawtransaction
Add support for ethrawtransaction
2 parents 84525ac + 232f2d1 commit 32e48e2

File tree

1 file changed

+60
-3
lines changed

1 file changed

+60
-3
lines changed

etheno/jsonrpc.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,60 @@
44
from .etheno import EthenoPlugin
55
from .utils import format_hex_address
66

7+
8+
# source: https://ethereum.stackexchange.com/a/83855
9+
import rlp
10+
from eth_typing import HexStr
11+
from eth_utils import keccak, to_bytes
12+
from rlp.sedes import Binary, big_endian_int, binary
13+
from web3 import Web3
14+
from web3.auto import w3
15+
16+
17+
class Transaction(rlp.Serializable):
18+
fields = [
19+
("nonce", big_endian_int),
20+
("gas_price", big_endian_int),
21+
("gas", big_endian_int),
22+
("to", Binary.fixed_length(20, allow_empty=True)),
23+
("value", big_endian_int),
24+
("data", binary),
25+
("v", big_endian_int),
26+
("r", big_endian_int),
27+
("s", big_endian_int),
28+
]
29+
30+
31+
def hex_to_bytes(data: str) -> bytes:
32+
return to_bytes(hexstr=HexStr(data))
33+
34+
35+
def decode_raw_tx(raw_tx: str):
36+
tx_bytes = hex_to_bytes(raw_tx)
37+
tx = rlp.decode(tx_bytes, Transaction)
38+
hash_tx = Web3.toHex(keccak(tx_bytes))
39+
from_ = w3.eth.account.recover_transaction(raw_tx)
40+
to = w3.toChecksumAddress(tx.to) if tx.to else None
41+
data = w3.toHex(tx.data)
42+
r = hex(tx.r)
43+
s = hex(tx.s)
44+
chain_id = (tx.v - 35) // 2 if tx.v % 2 else (tx.v - 36) // 2
45+
return {
46+
'txHash': hash_tx,
47+
'from': from_,
48+
'to': to,
49+
'nonce': tx.nonce,
50+
'gas': tx.gas,
51+
'gasPrice': tx.gas_price,
52+
'value': tx.value,
53+
'data': data,
54+
'chainId': chain_id,
55+
'r': r,
56+
's': s,
57+
'v': tx.v
58+
}
59+
60+
761
class JSONExporter:
862
def __init__(self, out_stream: Union[str, TextIO]):
963
self._was_path = isinstance(out_stream, str)
@@ -65,12 +119,15 @@ def after_post(self, post_data, result):
65119
result = result[0]
66120
if 'method' not in post_data:
67121
return
68-
elif post_data['method'] == 'eth_sendTransaction' and 'result' in result:
122+
elif (post_data['method'] == 'eth_sendTransaction' or post_data['method'] == 'eth_sendRawTransaction') and 'result' in result:
69123
try:
70124
transaction_hash = int(result['result'], 16)
71125
except ValueError:
72126
return
73-
self._transactions[transaction_hash] = post_data
127+
if post_data['method'] == 'eth_sendRawTransaction':
128+
self._transactions[transaction_hash] = decode_raw_tx(post_data['params'][0])
129+
else:
130+
self._transactions[transaction_hash] = post_data['params'][0]
74131
elif post_data['method'] == 'evm_mine':
75132
self.handle_increase_block_number()
76133
elif post_data['method'] == 'evm_increaseTime':
@@ -80,7 +137,7 @@ def after_post(self, post_data, result):
80137
if transaction_hash not in self._transactions:
81138
self.logger.error(f'Received transaction receipt {result} for unknown transaction hash {post_data["params"][0]}')
82139
return
83-
original_transaction = self._transactions[transaction_hash]['params'][0]
140+
original_transaction = self._transactions[transaction_hash]
84141
if 'value' not in original_transaction or original_transaction['value'] is None:
85142
value = '0x0'
86143
else:

0 commit comments

Comments
 (0)