Allow brakets for arrays for contract input data, fix decoding for multiple inputs

pull/3513/head
Victor Baranov 4 years ago
parent 2bcf1ceaad
commit 4c3f9b3de4
  1. 2
      CHANGELOG.md
  2. 3
      apps/block_scout_web/assets/js/lib/smart_contract/functions.js
  3. 53
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/contract.ex
  4. 12
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/encoder.ex
  5. 21
      apps/explorer/lib/explorer/smart_contract/reader.ex

@ -1,11 +1,13 @@
## Current
### Features
- [#3513](https://github.com/poanetwork/blockscout/pull/3513) - Allow square brackets for an array input data in contracts interaction
- [#3480](https://github.com/poanetwork/blockscout/pull/3480) - Add support of Autonity client
- [#3470](https://github.com/poanetwork/blockscout/pull/3470) - Display sum of tokens' USD value at tokens holder's address page
- [#3462](https://github.com/poanetwork/blockscout/pull/3462) - Display price for bridged tokens
### Fixes
- [#3513](https://github.com/poanetwork/blockscout/pull/3513) - Fix input data processing for method call (array type of data)
- [#3509](https://github.com/poanetwork/blockscout/pull/3509) - Fix QR code tooltip appearance in mobile view
- [#3507](https://github.com/poanetwork/blockscout/pull/3507), [#3510](https://github.com/poanetwork/blockscout/pull/3510) - Fix left margin of balance card in mobile view
- [#3506](https://github.com/poanetwork/blockscout/pull/3506) - Fix token trasfer's tile styles: prevent overlapping of long names

@ -135,6 +135,9 @@ function callMethod (isWalletEnabled, $functionInputs, explorerChainId, $form, f
let preparedVal
if (isNonSpaceInputType(inputType)) { preparedVal = val.replace(/\s/g, '') } else { preparedVal = val }
if (isArrayInputType(inputType)) {
if (preparedVal.startsWith('[') && preparedVal.endsWith(']')) {
preparedVal = preparedVal.substring(1, preparedVal.length - 1)
}
return preparedVal.split(',')
} else { return preparedVal }
})

@ -78,10 +78,11 @@ defmodule EthereumJSONRPC.Contract do
end
defp format_args(function, args) do
types = function.types
args
|> Enum.with_index()
|> Enum.map(fn {arg, index} ->
types = function.types
type = Enum.at(types, index)
convert_string_to_array(type, arg)
@ -97,26 +98,54 @@ defmodule EthereumJSONRPC.Contract do
convert_int_string_to_array(arg)
{:array, _} ->
if arg && arg !== "" do
String.split(arg, ",")
else
[]
end
convert_string_to_array(arg)
_ ->
arg
end
end
defp convert_int_string_to_array(arg) do
if arg && arg !== "" do
defp convert_int_string_to_array(arg) when is_nil(arg), do: true
defp convert_int_string_to_array(arg) when not is_nil(arg) do
cond do
String.starts_with?(arg, "[") && String.ends_with?(arg, "]") ->
arg
|> String.trim_leading("[")
|> String.trim_trailing("]")
|> convert_int_string_to_array_inner()
arg !== "" ->
convert_int_string_to_array_inner(arg)
true ->
[]
end
end
defp convert_int_string_to_array_inner(arg) do
arg
|> String.split(",")
|> Enum.map(fn el ->
{int, _} = Integer.parse(el)
int
end)
else
end
defp convert_string_to_array(arg) when is_nil(arg), do: true
defp convert_string_to_array(arg) when not is_nil(arg) do
cond do
String.starts_with?(arg, "[") && String.ends_with?(arg, "]") ->
arg
|> String.trim_leading("[")
|> String.trim_trailing("]")
|> String.split(",")
arg !== "" ->
String.split(arg, ",")
true ->
[]
end
end
@ -151,11 +180,13 @@ defmodule EthereumJSONRPC.Contract do
block_number -> integer_to_quantity(block_number)
end
request(%{
full_params = %{
id: id,
method: "eth_call",
params: [%{to: contract_address, data: data, from: from}, block]
})
}
request(full_params)
end
def eth_get_storage_at_request(contract_address, storage_pointer, block_number, json_rpc_named_arguments) do

@ -13,9 +13,11 @@ defmodule EthereumJSONRPC.Encoder do
"""
@spec encode_function_call(%ABI.FunctionSelector{}, [term()]) :: String.t()
def encode_function_call(function_selector, args) do
parsed_args = parse_args(args)
encoded_args =
function_selector
|> ABI.encode(parse_args(args))
|> ABI.encode(parsed_args)
|> Base.encode16(case: :lower)
"0x" <> encoded_args
@ -28,7 +30,15 @@ defmodule EthereumJSONRPC.Encoder do
Base.decode16!(hexadecimal_digits, case: :mixed)
item ->
if is_list(item) do
item
|> Enum.map(fn el ->
<<"0x", hexadecimal_digits::binary>> = el
Base.decode16!(hexadecimal_digits, case: :mixed)
end)
else
item
end
end)
end

@ -259,18 +259,18 @@ defmodule Explorer.SmartContract.Reader do
|> Enum.with_index()
|> Enum.all?(fn {target_type, index} ->
type_to_compare = Map.get(Enum.at(Map.get(target_method, "inputs"), index), "type")
target_type_formatted = format_input_type(target_type)
target_type_formatted = format_type(target_type)
target_type_formatted == type_to_compare
end)
end
defp format_input_type(input_type) do
defp format_type(input_type) do
case input_type do
{:array, type, array_size} ->
format_input_type(type) <> "[" <> Integer.to_string(array_size) <> "]"
format_type(type) <> "[" <> Integer.to_string(array_size) <> "]"
{:array, type} ->
format_input_type(type) <> "[]"
format_type(type) <> "[]"
{:tuple, tuple} ->
format_tuple_type(tuple)
@ -288,9 +288,9 @@ defmodule Explorer.SmartContract.Reader do
tuple
|> Enum.reduce(nil, fn tuple_item, acc ->
if acc do
acc <> "," <> format_input_type(tuple_item)
acc <> "," <> format_type(tuple_item)
else
format_input_type(tuple_item)
format_type(tuple_item)
end
end)
@ -378,6 +378,15 @@ defmodule Explorer.SmartContract.Reader do
returns
|> Enum.map(fn output ->
case output do
{:array, type, array_size} ->
%{"type" => format_type(type) <> "[" <> Integer.to_string(array_size) <> "]"}
{:array, type} ->
%{"type" => format_type(type) <> "[]"}
{:tuple, tuple} ->
%{"type" => format_tuple_type(tuple)}
{type, size} ->
full_type = Atom.to_string(type) <> Integer.to_string(size)
%{"type" => full_type}

Loading…
Cancel
Save