@@ -3,6 +3,8 @@ defmodule EthereumJSONRPC.Geth do
3
3
Ethereum JSONRPC methods that are only supported by [Geth](https://github.com/ethereum/go-ethereum/wiki/geth).
4
4
"""
5
5
6
+ require Logger
7
+
6
8
import EthereumJSONRPC , only: [ id_to_params: 1 , integer_to_quantity: 1 , json_rpc: 2 , request: 1 ]
7
9
8
10
alias EthereumJSONRPC . { FetchedBalance , FetchedCode , PendingTransaction }
@@ -78,12 +80,18 @@ defmodule EthereumJSONRPC.Geth do
78
80
defp debug_trace_transaction_request ( % { id: id , hash_data: hash_data } ) do
79
81
timeout = Application . get_env ( :ethereum_jsonrpc , :internal_transaction_timeout )
80
82
83
+ tracer =
84
+ case Application . get_env ( :ethereum_jsonrpc , __MODULE__ ) [ :tracer ] do
85
+ "js" -> @ tracer
86
+ "call_tracer" -> "callTracer"
87
+ end
88
+
81
89
request ( % {
82
90
id: id ,
83
91
method: "debug_traceTransaction" ,
84
92
params: [
85
93
hash_data ,
86
- % { tracer: @ tracer , disableStack: true , disableMemory: true , disableStorage: true , timeout: timeout }
94
+ % { tracer: tracer , disableStack: true , disableMemory: true , disableStorage: true , timeout: timeout }
87
95
]
88
96
} )
89
97
end
@@ -177,6 +185,7 @@ defmodule EthereumJSONRPC.Geth do
177
185
178
186
internal_transaction_params =
179
187
calls
188
+ |> prepare_calls ( )
180
189
|> Stream . with_index ( )
181
190
|> Enum . map ( fn { trace , index } ->
182
191
Map . merge ( trace , % {
@@ -223,6 +232,71 @@ defmodule EthereumJSONRPC.Geth do
223
232
{ :error , annotated_error }
224
233
end
225
234
235
+ defp prepare_calls ( calls ) do
236
+ case Application . get_env ( :ethereum_jsonrpc , __MODULE__ ) [ :tracer ] do
237
+ "call_tracer" -> { calls , 0 } |> parse_call_tracer_calls ( [ ] , [ ] , false ) |> Enum . reverse ( )
238
+ "js" -> calls
239
+ end
240
+ end
241
+
242
+ defp parse_call_tracer_calls ( calls , acc , trace_address , inner? \\ true )
243
+ defp parse_call_tracer_calls ( [ ] , acc , _trace_address , _inner? ) , do: acc
244
+ defp parse_call_tracer_calls ( { % { "type" => 0 } , _ } , acc , _trace_address , _inner? ) , do: acc
245
+
246
+ defp parse_call_tracer_calls (
247
+ { % { "type" => type , "from" => from } = call , index } ,
248
+ acc ,
249
+ trace_address ,
250
+ inner?
251
+ )
252
+ when type in ~w( CALL CALLCODE DELEGATECALL STATICCALL CREATE CREATE2 SELFDESTRUCT REWARD) do
253
+ new_trace_address = [ index | trace_address ]
254
+
255
+ formatted_call =
256
+ % {
257
+ "type" => if ( type in ~w( CALL CALLCODE DELEGATECALL STATICCALL) , do: "call" , else: String . downcase ( type ) ) ,
258
+ "callType" => String . downcase ( type ) ,
259
+ "from" => from ,
260
+ "to" => Map . get ( call , "to" , "0x" ) ,
261
+ "createdContractAddressHash" => Map . get ( call , "to" , "0x" ) ,
262
+ "value" => Map . get ( call , "value" , "0x0" ) ,
263
+ "gas" => Map . get ( call , "gas" , "0x0" ) ,
264
+ "gasUsed" => Map . get ( call , "gasUsed" , "0x0" ) ,
265
+ "input" => Map . get ( call , "input" , "0x" ) ,
266
+ "init" => Map . get ( call , "input" , "0x" ) ,
267
+ "createdContractCode" => Map . get ( call , "output" , "0x" ) ,
268
+ "traceAddress" => if ( inner? , do: Enum . reverse ( new_trace_address ) , else: [ ] ) ,
269
+ "error" => call [ "error" ]
270
+ }
271
+ |> case do
272
+ % { "error" => nil } = ok_call ->
273
+ ok_call
274
+ |> Map . delete ( "error" )
275
+ # to handle staticcall, all other cases handled by EthereumJSONRPC.Geth.Call.elixir_to_internal_transaction_params/1
276
+ |> Map . put ( "output" , Map . get ( call , "output" , "0x" ) )
277
+
278
+ error_call ->
279
+ error_call
280
+ end
281
+
282
+ parse_call_tracer_calls (
283
+ Map . get ( call , "calls" , [ ] ) ,
284
+ [ formatted_call | acc ] ,
285
+ if ( inner? , do: new_trace_address , else: [ ] )
286
+ )
287
+ end
288
+
289
+ defp parse_call_tracer_calls ( { call , _ } , acc , _trace_address , _inner? ) do
290
+ Logger . warning ( "Call from a callTracer with an unknown type: #{ inspect ( call ) } " )
291
+ acc
292
+ end
293
+
294
+ defp parse_call_tracer_calls ( calls , acc , trace_address , _inner ) when is_list ( calls ) do
295
+ calls
296
+ |> Stream . with_index ( )
297
+ |> Enum . reduce ( acc , & parse_call_tracer_calls ( & 1 , & 2 , trace_address ) )
298
+ end
299
+
226
300
defp reduce_internal_transactions_params ( internal_transactions_params ) when is_list ( internal_transactions_params ) do
227
301
internal_transactions_params
228
302
|> Enum . reduce ( { :ok , [ ] } , & internal_transactions_params_reducer / 2 )
0 commit comments