Merge branch 'supported-chains-env-var' of github.com:poanetwork/blockscout into supported-chains-env-var

pull/1900/head
Victor Baranov 6 years ago
commit fdcd6b31dd
  1. 4
      CHANGELOG.md
  2. 2
      README.md
  3. 5
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  4. 238
      apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex
  5. 2
      apps/block_scout_web/priv/gettext/default.pot
  6. 2
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  7. 4
      apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs
  8. 1
      apps/explorer/.gitignore
  9. 1
      apps/explorer/lib/explorer/application.ex
  10. 92
      apps/explorer/lib/explorer/smart_contract/solc_downloader.ex
  11. 57
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  12. 64
      apps/explorer/priv/compile_solc.js

@ -21,6 +21,9 @@
- [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth
- [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance
- [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view
- [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code
- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete
- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance
### Chore
@ -204,4 +207,3 @@
- [https://github.com/poanetwork/blockscout/pull/1532](https://github.com/poanetwork/blockscout/pull/1532) - Upgrade elixir to 1.8.1
- [https://github.com/poanetwork/blockscout/pull/1553](https://github.com/poanetwork/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix
- [https://github.com/poanetwork/blockscout/pull/1465](https://github.com/poanetwork/blockscout/pull/1465) - Resolve lodash security alert

@ -139,7 +139,7 @@ The [development stack page](https://github.com/poanetwork/blockscout/wiki/Devel
```
* If using Chrome, Enable `chrome://flags/#allow-insecure-localhost`.
9. Start Phoenix Server.
9. Run the Phoenix Server from the root directory of your application.
`mix phx.server`
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.

@ -112,9 +112,8 @@
"data-test": "search_input"
],
[ url: "#{chain_path(@conn, :token_autocomplete)}?q=",
prepop: true,
minChars: 3,
maxItems: 8,
limit: 0,
minChars: 2,
value: "contract_address_hash",
label: "contract_address_hash",
descrSearch: true,

@ -2,51 +2,231 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do
use BlockScoutWeb, :view
@colors %{
"\e[95m" => "136, 0, 0",
"\e[95m" => "",
# red
"\e[91m" => "236, 89, 58",
"\e[91m" => "",
# gray
"\e[38;5;8m" => "111, 110, 111",
"\e[38;5;8m" => "<span style=\"color:rgb(111, 110, 111)\">",
# green
"\e[32m" => "57, 115, 0",
"\e[32m" => "",
# yellowgreen
"\e[93m" => "57, 115, 0",
"\e[93m" => "",
# yellow
"\e[92m" => "119, 232, 81",
"\e[92m" => "",
# red
"\e[94m" => "136, 0, 0"
"\e[94m" => ""
}
@comment_start "#"
@reserved_words_types [
"var",
"bool",
"string",
"int",
"uint",
"int8",
"uint8",
"int16",
"uint16",
"int24",
"uint24",
"int32",
"uint32",
"int40",
"uint40",
"int48",
"uint48",
"int56",
"uint56",
"int64",
"uint64",
"int72",
"uint72",
"int80",
"uint80",
"int88",
"uint88",
"int96",
"uint96",
"int104",
"uint104",
"int112",
"uint112",
"int120",
"uint120",
"int128",
"uint128",
"int136",
"uint136",
"int144",
"uint144",
"int152",
"uint152",
"int160",
"uint160",
"int168",
"uint168",
"int176",
"uint176",
"int184",
"uint184",
"int192",
"uint192",
"int200",
"uint200",
"int208",
"uint208",
"int216",
"uint216",
"int224",
"uint224",
"int232",
"uint232",
"int240",
"uint240",
"int248",
"uint248",
"int256",
"uint256",
"byte",
"bytes",
"bytes1",
"bytes2",
"bytes3",
"bytes4",
"bytes5",
"bytes6",
"bytes7",
"bytes8",
"bytes9",
"bytes10",
"bytes11",
"bytes12",
"bytes13",
"bytes14",
"bytes15",
"bytes16",
"bytes17",
"bytes18",
"bytes19",
"bytes20",
"bytes21",
"bytes22",
"bytes23",
"bytes24",
"bytes25",
"bytes26",
"bytes27",
"bytes28",
"bytes29",
"bytes30",
"bytes31",
"bytes32",
"true",
"false",
"enum",
"struct",
"mapping",
"address"
]
@reserved_words_keywords [
"def",
"require",
"revert",
"return",
"assembly",
"memory",
"mem"
]
@modifiers [
"payable",
"public",
"view",
"pure",
"returns",
"internal"
]
@reserved_words @reserved_words_keywords ++ @reserved_words_types
@reserved_words_regexp ([@comment_start | @reserved_words] ++ @modifiers)
|> Enum.reduce("", fn el, acc -> acc <> "|" <> el end)
|> Regex.compile!()
def highlight_decompiled_code(code) do
{_, result} =
@colors
|> Enum.reduce(code, fn {symbol, rgb}, acc ->
String.replace(acc, symbol, "<span style=\"color:rgb(#{rgb})\">")
String.replace(acc, symbol, rgb)
end)
|> String.replace("\e[1m", "<span style=\"font-weight:bold\">")
|> String.replace("»", "&raquo;")
|> String.replace("\e[0m", "</span>")
|> String.split(~r/\<span style=.*?\)"\>|\<\/span\>/, include_captures: true, trim: true)
|> Enum.reduce({"", []}, fn part, {style, acc} ->
new_style =
cond do
String.contains?(part, "<span style") -> part
part == "</span>" -> ""
true -> style
end
new_part = new_part(part, new_style)
{new_style, [new_part | acc]}
end)
|> add_styles_to_every_line()
result
|> Enum.reduce("", fn part, acc ->
part <> acc
end)
|> add_styles_to_reserved_words()
|> add_line_numbers()
end
defp add_styles_to_every_line(lines) do
lines
|> Enum.reduce({"", []}, fn part, {style, acc} ->
new_style =
cond do
String.contains?(part, "<span style") -> part
part == "</span>" -> ""
true -> style
end
new_part = new_part(part, new_style)
{new_style, [new_part | acc]}
end)
end
defp add_styles_to_reserved_words(code) do
code
|> String.split("\n")
|> Enum.map(fn line ->
add_styles_to_line(line)
end)
|> Enum.reduce("", fn el, acc ->
acc <> el <> "\n"
end)
end
defp add_styles_to_line(line) do
parts =
line
|> String.split(@reserved_words_regexp,
include_captures: true
)
comment_position = Enum.find_index(parts, fn part -> part == "#" end)
parts
|> Enum.with_index()
|> Enum.map(fn {el, index} ->
cond do
!(is_nil(comment_position) || comment_position > index) -> el
el in @reserved_words -> "<span class=\"hljs-keyword\">" <> el <> "</span>"
el in @modifiers -> "<span class=\"hljs-title\">" <> el <> "</span>"
true -> el
end
end)
|> Enum.reduce("", fn el, acc ->
acc <> el
end)
end
def sort_contracts_by_version(decompiled_contracts) do
decompiled_contracts
|> Enum.sort_by(& &1.decompiler_version)
@ -76,18 +256,12 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do
part
true ->
result =
part
|> String.split("\n")
|> Enum.reduce("", fn p, a ->
a <> new_style <> p <> "</span>\n"
end)
if String.ends_with?(part, "\n") do
result
else
String.slice(result, 0..-2)
end
part
|> String.split("\n")
|> Enum.reduce("", fn p, a ->
a <> new_style <> p <> "</span>\n"
end)
|> String.slice(0..-2)
end
end
end

@ -714,7 +714,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""

@ -714,7 +714,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""

@ -56,7 +56,7 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do
result = AddressDecompiledContractView.highlight_decompiled_code(code)
assert result ==
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # I failed with these:</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span><span style=\"color:rgb(236, 89, 58)\">unknowne77c646d(?)</span><span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span><span style=\"color:rgb(236, 89, 58)\">transferFromWithData(address _from, address _to, uint256 _value, bytes _data)</span><span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # All the rest is below.</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># Storage definitions and getters</span></code>\n<code></code>\n<code> <span style=\"color:rgb(57, 115, 0)\">def</span> storage:</code>\n<code> <span style=\"color:rgb(57, 115, 0)\">allowance</span> is uint256 => uint256 <span style=\"color:rgb(111, 110, 111)\"># mask(256, 0) at storage #2</span></code>\n<code> <span style=\"color:rgb(57, 115, 0)\">stor4</span> is uint256 => uint8 <span style=\"color:rgb(111, 110, 111)\"># mask(8, 0) at storage #4</span></code>\n<code></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>allowance(address <span style=\"color:rgb(57, 115, 0)\">_owner</span>, address <span style=\"color:rgb(57, 115, 0)\">_spender</span>) <span style=\"color:rgb(136, 0, 0)\">payable</span>: 64</code>\n<code> return <span style=\"color:rgb(57, 115, 0)\">allowance</span><span style=\"color:rgb(57, 115, 0)\">[</span>sha3(((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span><span style=\"color:rgb(57, 115, 0)\">_owner</span>), 1), ((320 - 1)<span style=\"font-weight:bold\"> and </span><span style=\"color:rgb(57, 115, 0)\">_spender</span><span style=\"font-weight:bold\"> and </span>(320 - 1))<span style=\"color:rgb(57, 115, 0)\">]</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Regular functions - see Tutorial for understanding quirks of the code</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># folder failed in this function - may be terribly long, sorry</span></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>unknownc47d033b(?) <span style=\"color:rgb(136, 0, 0)\">payable</span>: not cd[4]:</code>\n<code> revert</code>\n<code> else:</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>0<span style=\"color:rgb(136, 0, 0)\">]</span>cd[4]</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>32<span style=\"color:rgb(136, 0, 0)\">]</span> = 4</code>\n<code> <span style=\"color:rgb(136, 0, 0)\">mem[</span>96<span style=\"color:rgb(136, 0, 0)\">]</span> = bool(<span style=\"color:rgb(57, 115, 0)\">stor4</span><span style=\"color:rgb(57, 115, 0)\">[</span>((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])<span style=\"color:rgb(57, 115, 0)\">]</span>)</code>\n<code> return bool(<span style=\"color:rgb(57, 115, 0)\">stor4</span><span style=\"color:rgb(57, 115, 0)\">[</span>((320 - 1)<span style=\"font-weight:bold\"> and </span>(320 - 1)<span style=\"font-weight:bold\"> and </span>cd[4])<span style=\"color:rgb(57, 115, 0)\">]</span>)</code>\n<code></code>\n<code> <span style=\"color:rgb(136, 0, 0)\">def </span>_fallback() <span style=\"color:rgb(136, 0, 0)\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"># default function</span></code>\n<code> revert</code>\n<code></code>\n"
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # I failed with these:</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span>unknowne77c646d(?)<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> </span><span style=\"color:rgb(111, 110, 111)\"># - </span>transferFromWithData(address _from, address _to, uint256 _value, bytes _data)<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # All the rest is below.</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># Storage definitions and getters</span></code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> storage:</code>\n<code> allowance is <span class=\"hljs-keyword\">uint</span>256 => <span class=\"hljs-keyword\">uint</span>256 <span style=\"color:rgb(111, 110, 111)\"># mask(256, 0) at storage #2</span></code>\n<code> stor4 is <span class=\"hljs-keyword\">uint</span>256 => <span class=\"hljs-keyword\">uint</span>8 <span style=\"color:rgb(111, 110, 111)\"># mask(8, 0) at storage #4</span></code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> allowance(<span class=\"hljs-keyword\">address</span> _owner, <span class=\"hljs-keyword\">address</span> _spender) <span class=\"hljs-title\">payable</span>: 64</code>\n<code> <span class=\"hljs-keyword\">return</span> allowance[_owner_spender(320 - 1))]</code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Regular functions - see Tutorial for understanding quirks of the code</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code></code>\n<code></code>\n<code> <span style=\"color:rgb(111, 110, 111)\"># folder failed in this function - may be terribly long, sorry</span></code>\n<code> <span class=\"hljs-keyword\">def</span> unknownc47d033b(?) <span class=\"hljs-title\">payable</span>: not cd[4]:</code>\n<code> <span class=\"hljs-keyword\">revert</span></code>\n<code> else:</code>\n<code> <span class=\"hljs-keyword\">mem</span>[0]cd[4]</code>\n<code> <span class=\"hljs-keyword\">mem</span>[32] = 4</code>\n<code> <span class=\"hljs-keyword\">mem</span>[96] = <span class=\"hljs-keyword\">bool</span>(stor4[cd[4])])</code>\n<code> <span class=\"hljs-keyword\">return</span> <span class=\"hljs-keyword\">bool</span>(stor4[cd[4])])</code>\n<code></code>\n<code> <span class=\"hljs-keyword\">def</span> _fallback() <span class=\"hljs-title\">payable</span>: <span style=\"color:rgb(111, 110, 111)\"># default function</span></code>\n<code> <span class=\"hljs-keyword\">revert</span></code>\n<code></code>\n<code></code>\n"
end
test "adds style span to every line" do
@ -70,7 +70,7 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do
"""
assert AddressDecompiledContractView.highlight_decompiled_code(code) ==
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code></code>\n"
"<code> <span style=\"color:rgb(111, 110, 111)\">#</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # eveem.org 6 Feb 2019</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Decompiled source of </span>0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875<span style=\"color:rgb(111, 110, 111)\"></span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> #</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # Let's make the world open source</span></code>\n<code><span style=\"color:rgb(111, 110, 111)\"> # </span></code>\n<code></code>\n<code></code>\n"
end
end

@ -1 +1,2 @@
priv/.recovery
priv/solc_compilers/

@ -26,6 +26,7 @@ defmodule Explorer.Application do
Supervisor.Spec.worker(SpandexDatadog.ApiServer, [datadog_opts()]),
Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor),
Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor),
Explorer.SmartContract.SolcDownloader,
{Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents},
{Admin.Recovery, [[], [name: Admin.Recovery]]},
{TransactionCountCache, [[], []]}

@ -0,0 +1,92 @@
defmodule Explorer.SmartContract.SolcDownloader do
@moduledoc """
Checks to see if the requested solc compiler version exists, and if not it
downloads and stores the file.
"""
use GenServer
alias Explorer.SmartContract.Solidity.CompilerVersion
@latest_compiler_refetch_time :timer.minutes(30)
def ensure_exists(version) do
path = file_path(version)
if File.exists?(path) do
path
else
{:ok, compiler_versions} = CompilerVersion.fetch_versions()
if version in compiler_versions do
GenServer.call(__MODULE__, {:ensure_exists, version}, 60_000)
else
false
end
end
end
def start_link(_) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
# sobelow_skip ["Traversal"]
@impl true
def init([]) do
File.mkdir(compiler_dir())
{:ok, []}
end
# sobelow_skip ["Traversal"]
@impl true
def handle_call({:ensure_exists, version}, _from, state) do
path = file_path(version)
if fetch?(version, path) do
temp_path = file_path("#{version}-tmp")
contents = download(version)
file = File.open!(temp_path, [:write, :exclusive])
IO.binwrite(file, contents)
File.rename(temp_path, path)
end
{:reply, path, state}
end
defp fetch?("latest", path) do
case File.stat(path) do
{:error, :enoent} ->
true
{:ok, %{mtime: mtime}} ->
last_modified = NaiveDateTime.from_erl!(mtime)
diff = Timex.diff(NaiveDateTime.utc_now(), last_modified, :milliseconds)
diff > @latest_compiler_refetch_time
end
end
defp fetch?(_, path) do
not File.exists?(path)
end
defp file_path(version) do
Path.join(compiler_dir(), "#{version}.js")
end
defp compiler_dir do
Application.app_dir(:explorer, "priv/solc_compilers/")
end
defp download(version) do
download_path = "https://ethereum.github.io/solc-bin/bin/soljson-#{version}.js"
download_path
|> HTTPoison.get!([], timeout: 60_000)
|> Map.get(:body)
end
end

@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
Module responsible to compile the Solidity code of a given Smart Contract.
"""
alias Explorer.SmartContract.SolcDownloader
@new_contract_name "New.sol"
@allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"]
@ -79,31 +81,36 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
"byzantium"
end
{response, _status} =
System.cmd(
"node",
[
Application.app_dir(:explorer, "priv/compile_solc.js"),
code,
compiler_version,
optimize_value(optimize),
optimization_runs,
@new_contract_name,
external_libs_string,
checked_evm_version
]
)
with {:ok, contracts} <- Jason.decode(response),
%{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <-
get_contract_info(contracts, name) do
{:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}}
else
{:error, %Jason.DecodeError{}} ->
{:error, :compilation}
error ->
parse_error(error)
path = SolcDownloader.ensure_exists(compiler_version)
if path do
{response, _status} =
System.cmd(
"node",
[
Application.app_dir(:explorer, "priv/compile_solc.js"),
code,
compiler_version,
optimize_value(optimize),
optimization_runs,
@new_contract_name,
external_libs_string,
checked_evm_version,
path
]
)
with {:ok, contracts} <- Jason.decode(response),
%{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <-
get_contract_info(contracts, name) do
{:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}}
else
{:error, %Jason.DecodeError{}} ->
{:error, :compilation}
error ->
parse_error(error)
end
end
end

@ -1,7 +1,5 @@
#!/usr/bin/env node
const solc = require('solc');
var sourceCode = process.argv[2];
var version = process.argv[3];
var optimize = process.argv[4];
@ -9,38 +7,38 @@ var optimizationRuns = parseInt(process.argv[5], 10);
var newContractName = process.argv[6];
var externalLibraries = JSON.parse(process.argv[7])
var evmVersion = process.argv[8];
var compilerVersionPath = process.argv[9];
var solc = require('solc')
var compilerSnapshot = require(compilerVersionPath);
var solc = solc.setupMethods(compilerSnapshot);
var compiled_code = solc.loadRemoteVersion(version, function (err, solcSnapshot) {
if (err) {
console.log(JSON.stringify(err.message));
} else {
const input = {
language: 'Solidity',
sources: {
[newContractName]: {
content: sourceCode
}
},
settings: {
evmVersion: evmVersion,
optimizer: {
enabled: optimize == '1',
runs: optimizationRuns
},
libraries: {
[newContractName]: externalLibraries
},
outputSelection: {
'*': {
'*': ['*']
}
}
const input = {
language: 'Solidity',
sources: {
[newContractName]: {
content: sourceCode
}
},
settings: {
evmVersion: evmVersion,
optimizer: {
enabled: optimize == '1',
runs: optimizationRuns
},
libraries: {
[newContractName]: externalLibraries
},
outputSelection: {
'*': {
'*': ['*']
}
}
const output = JSON.parse(solcSnapshot.compile(JSON.stringify(input)))
/** Older solc-bin versions don't use filename as contract key */
const response = output.contracts[newContractName] || output.contracts['']
console.log(JSON.stringify(response));
}
});
}
const output = JSON.parse(solc.compile(JSON.stringify(input)))
/** Older solc-bin versions don't use filename as contract key */
const response = output.contracts[newContractName] || output.contracts['']
console.log(JSON.stringify(response));

Loading…
Cancel
Save