Merge pull request #2052 from poanetwork/ab-fix-abi-for-token-name

allow bytes32 for name and symbol
pull/2064/head
Victor Baranov 6 years ago committed by GitHub
commit 9c929ee1e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 9
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/contract.ex
  3. 19
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/encoder.ex
  4. 23
      apps/explorer/lib/explorer/token/metadata_retriever.ex
  5. 47
      apps/explorer/test/explorer/token/metadata_retriever_test.exs

@ -45,6 +45,7 @@
- [#2017](https://github.com/poanetwork/blockscout/pull/2017) - fix: fix to/from filters on tx list pages - [#2017](https://github.com/poanetwork/blockscout/pull/2017) - fix: fix to/from filters on tx list pages
- [#2008](https://github.com/poanetwork/blockscout/pull/2008) - add new function clause for xDai network beneficiaries - [#2008](https://github.com/poanetwork/blockscout/pull/2008) - add new function clause for xDai network beneficiaries
- [#2009](https://github.com/poanetwork/blockscout/pull/2009) - addresses page improvements - [#2009](https://github.com/poanetwork/blockscout/pull/2009) - addresses page improvements
- [#2052](https://github.com/poanetwork/blockscout/pull/2052) - allow bytes32 for name and symbol
- [#2047](https://github.com/poanetwork/blockscout/pull/2047) - fix: show creating internal transactions - [#2047](https://github.com/poanetwork/blockscout/pull/2047) - fix: show creating internal transactions
- [#2014](https://github.com/poanetwork/blockscout/pull/2014) - fix: use better queries for listLogs endpoint - [#2014](https://github.com/poanetwork/blockscout/pull/2014) - fix: use better queries for listLogs endpoint
- [#2027](https://github.com/poanetwork/blockscout/pull/2027) - fix: `BlocksTransactionsMismatch` ignoring blocks without transactions - [#2027](https://github.com/poanetwork/blockscout/pull/2027) - fix: `BlocksTransactionsMismatch` ignoring blocks without transactions

@ -28,10 +28,11 @@ defmodule EthereumJSONRPC.Contract do
@spec execute_contract_functions([call()], [map()], EthereumJSONRPC.json_rpc_named_arguments()) :: [call_result()] @spec execute_contract_functions([call()], [map()], EthereumJSONRPC.json_rpc_named_arguments()) :: [call_result()]
def execute_contract_functions(requests, abi, json_rpc_named_arguments) do def execute_contract_functions(requests, abi, json_rpc_named_arguments) do
functions = parsed_abi =
abi abi
|> ABI.parse_specification() |> ABI.parse_specification()
|> Enum.into(%{}, &{&1.function, &1})
functions = Enum.into(parsed_abi, %{}, &{&1.function, &1})
requests_with_index = Enum.with_index(requests) requests_with_index = Enum.with_index(requests)
@ -52,13 +53,15 @@ defmodule EthereumJSONRPC.Contract do
|> Enum.into(%{}, &{&1.id, &1}) |> Enum.into(%{}, &{&1.id, &1})
Enum.map(requests_with_index, fn {%{function_name: function_name}, index} -> Enum.map(requests_with_index, fn {%{function_name: function_name}, index} ->
selectors = Enum.filter(parsed_abi, fn p_abi -> p_abi.function == function_name end)
indexed_responses[index] indexed_responses[index]
|> case do |> case do
nil -> nil ->
{:error, "No result"} {:error, "No result"}
response -> response ->
{^index, result} = Encoder.decode_result(response, functions[function_name]) {^index, result} = Encoder.decode_result(response, selectors)
result result
end end
end) end)

@ -35,12 +35,29 @@ defmodule EthereumJSONRPC.Encoder do
@doc """ @doc """
Given a result from the blockchain, and the function selector, returns the result decoded. Given a result from the blockchain, and the function selector, returns the result decoded.
""" """
@spec decode_result(map(), %ABI.FunctionSelector{}) :: @spec decode_result(map(), %ABI.FunctionSelector{} | [%ABI.FunctionSelector{}]) ::
{String.t(), {:ok, any()} | {:error, String.t() | :invalid_data}} {String.t(), {:ok, any()} | {:error, String.t() | :invalid_data}}
def decode_result(%{error: %{code: code, message: message}, id: id}, _selector) do def decode_result(%{error: %{code: code, message: message}, id: id}, _selector) do
{id, {:error, "(#{code}) #{message}"}} {id, {:error, "(#{code}) #{message}"}}
end end
def decode_result(result, selectors) when is_list(selectors) do
selectors
|> Enum.map(fn selector ->
try do
decode_result(result, selector)
rescue
_ -> :error
end
end)
|> Enum.find(fn decode ->
case decode do
{_id, {:ok, _}} -> true
_ -> false
end
end)
end
def decode_result(%{id: id, result: result}, function_selector) do def decode_result(%{id: id, result: result}, function_selector) do
types_list = List.wrap(function_selector.returns) types_list = List.wrap(function_selector.returns)

@ -22,6 +22,16 @@ defmodule Explorer.Token.MetadataRetriever do
"payable" => false, "payable" => false,
"type" => "function" "type" => "function"
}, },
%{
"constant" => true,
"inputs" => [],
"name" => "name",
"outputs" => [
%{"name" => "", "type" => "bytes32"}
],
"payable" => false,
"type" => "function"
},
%{ %{
"constant" => true, "constant" => true,
"inputs" => [], "inputs" => [],
@ -60,6 +70,19 @@ defmodule Explorer.Token.MetadataRetriever do
], ],
"payable" => false, "payable" => false,
"type" => "function" "type" => "function"
},
%{
"constant" => true,
"inputs" => [],
"name" => "symbol",
"outputs" => [
%{
"name" => "",
"type" => "bytes32"
}
],
"payable" => false,
"type" => "function"
} }
] ]

@ -426,4 +426,51 @@ defmodule Explorer.Token.MetadataRetrieverTest do
on_exit(fn -> Application.put_env(:explorer, :token_functions_reader_max_retries, original) end) on_exit(fn -> Application.put_env(:explorer, :token_functions_reader_max_retries, original) end)
end end
end end
test "returns name and symbol when they are bytes32" do
token = insert(:token, contract_address: build(:contract_address))
expect(
EthereumJSONRPC.Mox,
:json_rpc,
1,
fn requests, _opts ->
{:ok,
Enum.map(requests, fn
%{id: id, method: "eth_call", params: [%{data: "0x313ce567", to: _}, "latest"]} ->
%{
id: id,
result: "0x0000000000000000000000000000000000000000000000000000000000000012"
}
%{id: id, method: "eth_call", params: [%{data: "0x06fdde03", to: _}, "latest"]} ->
%{
id: id,
result: "0x4d616b6572000000000000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x95d89b41", to: _}, "latest"]} ->
%{
id: id,
result: "0x4d4b520000000000000000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x18160ddd", to: _}, "latest"]} ->
%{
id: id,
result: "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000"
}
end)}
end
)
expected = %{
decimals: 18,
name: "Maker",
symbol: "MKR",
total_supply: 1_000_000_000_000_000_000_000_000
}
assert MetadataRetriever.get_functions_of(token.contract_address_hash) == expected
end
end end

Loading…
Cancel
Save