Merge pull request #3513 from poanetwork/vb-fix-multiple-input

Allow brackets for arrays for contract input data, fix decoding for multiple inputs
pull/3514/head
Victor Baranov 4 years ago committed by GitHub
commit 19c744f102
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 3
      apps/block_scout_web/assets/js/lib/smart_contract/functions.js
  3. 67
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/contract.ex
  4. 14
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/encoder.ex
  5. 21
      apps/explorer/lib/explorer/smart_contract/reader.ex

@ -1,11 +1,13 @@
## Current ## Current
### Features ### 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 - [#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 - [#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 - [#3462](https://github.com/poanetwork/blockscout/pull/3462) - Display price for bridged tokens
### Fixes ### 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 - [#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 - [#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 - [#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 let preparedVal
if (isNonSpaceInputType(inputType)) { preparedVal = val.replace(/\s/g, '') } else { preparedVal = val } if (isNonSpaceInputType(inputType)) { preparedVal = val.replace(/\s/g, '') } else { preparedVal = val }
if (isArrayInputType(inputType)) { if (isArrayInputType(inputType)) {
if (preparedVal.startsWith('[') && preparedVal.endsWith(']')) {
preparedVal = preparedVal.substring(1, preparedVal.length - 1)
}
return preparedVal.split(',') return preparedVal.split(',')
} else { return preparedVal } } else { return preparedVal }
}) })

@ -78,10 +78,11 @@ defmodule EthereumJSONRPC.Contract do
end end
defp format_args(function, args) do defp format_args(function, args) do
types = function.types
args args
|> Enum.with_index() |> Enum.with_index()
|> Enum.map(fn {arg, index} -> |> Enum.map(fn {arg, index} ->
types = function.types
type = Enum.at(types, index) type = Enum.at(types, index)
convert_string_to_array(type, arg) convert_string_to_array(type, arg)
@ -97,27 +98,55 @@ defmodule EthereumJSONRPC.Contract do
convert_int_string_to_array(arg) convert_int_string_to_array(arg)
{:array, _} -> {:array, _} ->
if arg && arg !== "" do convert_string_to_array(arg)
String.split(arg, ",")
else
[]
end
_ -> _ ->
arg arg
end end
end end
defp convert_int_string_to_array(arg) do defp convert_int_string_to_array(arg) when is_nil(arg), do: true
if arg && arg !== "" do
arg defp convert_int_string_to_array(arg) when not is_nil(arg) do
|> String.split(",") cond do
|> Enum.map(fn el -> String.starts_with?(arg, "[") && String.ends_with?(arg, "]") ->
{int, _} = Integer.parse(el) arg
int |> String.trim_leading("[")
end) |> String.trim_trailing("]")
else |> 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)
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
end end
@ -151,11 +180,13 @@ defmodule EthereumJSONRPC.Contract do
block_number -> integer_to_quantity(block_number) block_number -> integer_to_quantity(block_number)
end end
request(%{ full_params = %{
id: id, id: id,
method: "eth_call", method: "eth_call",
params: [%{to: contract_address, data: data, from: from}, block] params: [%{to: contract_address, data: data, from: from}, block]
}) }
request(full_params)
end end
def eth_get_storage_at_request(contract_address, storage_pointer, block_number, json_rpc_named_arguments) do 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() @spec encode_function_call(%ABI.FunctionSelector{}, [term()]) :: String.t()
def encode_function_call(function_selector, args) do def encode_function_call(function_selector, args) do
parsed_args = parse_args(args)
encoded_args = encoded_args =
function_selector function_selector
|> ABI.encode(parse_args(args)) |> ABI.encode(parsed_args)
|> Base.encode16(case: :lower) |> Base.encode16(case: :lower)
"0x" <> encoded_args "0x" <> encoded_args
@ -28,7 +30,15 @@ defmodule EthereumJSONRPC.Encoder do
Base.decode16!(hexadecimal_digits, case: :mixed) Base.decode16!(hexadecimal_digits, case: :mixed)
item -> item ->
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)
end end

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

Loading…
Cancel
Save