diff --git a/.dialyzer-ignore b/.dialyzer-ignore
index 53e3554c6e..6b7c1ae65c 100644
--- a/.dialyzer-ignore
+++ b/.dialyzer-ignore
@@ -4,4 +4,6 @@
apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex:400: Function timestamp_to_datetime/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: Function microseconds_time/1 has no local return
apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer()
-apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:174: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()
\ No newline at end of file
+apps/block_scout_web/lib/block_scout_web/views/layout_view.ex:174: The call 'Elixir.Poison.Parser':'parse!'(any(),#{'keys':='atoms!'}) will never return since the success typing is (binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []),[{atom(),_}]) -> 'false' | 'nil' | 'true' | binary() | ['false' | 'nil' | 'true' | binary() | [any()] | number() | map()] | number() | map() and the contract is (iodata(),'Elixir.Keyword':t()) -> t()
+apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The pattern 'false' can never match the type 'true'
+apps/explorer/lib/explorer/smart_contract/publisher_worker.ex:6: The test 5 == 'infinity' can never evaluate to 'true'
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cee4b3eba2..26e9555484 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,8 @@
- [#2289](https://github.com/poanetwork/blockscout/pull/2289) - Optional websockets for dev environment
- [#2307](https://github.com/poanetwork/blockscout/pull/2307) - add GoJoy to README
+- [#2293](https://github.com/poanetwork/blockscout/pull/2293) - remove request idle timeout configuration
+
## 2.0.1-beta
diff --git a/apps/block_scout_web/assets/js/app.js b/apps/block_scout_web/assets/js/app.js
index cd690f31db..25de7b2688 100644
--- a/apps/block_scout_web/assets/js/app.js
+++ b/apps/block_scout_web/assets/js/app.js
@@ -34,6 +34,7 @@ import './pages/transactions'
import './pages/favorites'
import './pages/network-search'
import './pages/layout'
+import './pages/verification_form'
import './pages/admin/tasks.js'
@@ -46,7 +47,6 @@ import './lib/market_history_chart'
import './lib/pending_transactions_toggle'
import './lib/pretty_json'
import './lib/reload_button'
-import './lib/smart_contract/new_smart_contract_form'
import './lib/smart_contract/read_only_functions'
import './lib/smart_contract/wei_ether_converter'
import './lib/stop_propagation'
diff --git a/apps/block_scout_web/assets/js/lib/smart_contract/new_smart_contract_form.js b/apps/block_scout_web/assets/js/lib/smart_contract/new_smart_contract_form.js
deleted file mode 100644
index 43419aeb9b..0000000000
--- a/apps/block_scout_web/assets/js/lib/smart_contract/new_smart_contract_form.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'jquery'
-
-$(function () {
- $('.js-btn-add-contract-libraries').on('click', function () {
- $('.js-smart-contract-libraries-wrapper').show()
- $(this).hide()
- })
-
- $('.js-smart-contract-form-reset').on('click', function () {
- $('.js-contract-library-form-group').removeClass('active')
- $('.js-contract-library-form-group').first().addClass('active')
- $('.js-smart-contract-libraries-wrapper').hide()
- $('.js-btn-add-contract-libraries').show()
- $('.js-add-contract-library-wrapper').show()
- })
-
- $('.js-btn-add-contract-library').on('click', function () {
- let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
-
- if (nextContractLibrary) {
- nextContractLibrary.addClass('active')
- }
-
- if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
- $('.js-add-contract-library-wrapper').hide()
- }
- })
-})
diff --git a/apps/block_scout_web/assets/js/pages/verification_form.js b/apps/block_scout_web/assets/js/pages/verification_form.js
new file mode 100644
index 0000000000..619a8e1326
--- /dev/null
+++ b/apps/block_scout_web/assets/js/pages/verification_form.js
@@ -0,0 +1,144 @@
+import $ from 'jquery'
+import _ from 'lodash'
+import URI from 'urijs'
+import humps from 'humps'
+import { subscribeChannel } from '../socket'
+import { createStore, connectElements } from '../lib/redux_helpers.js'
+
+export const initialState = {
+ channelDisconnected: false,
+ addressHash: null,
+ newForm: null
+}
+
+export function reducer (state = initialState, action) {
+ switch (action.type) {
+ case 'PAGE_LOAD':
+ case 'ELEMENTS_LOAD': {
+ return Object.assign({}, state, _.omit(action, 'type'))
+ }
+ case 'CHANNEL_DISCONNECTED': {
+ if (state.beyondPageOne) return state
+
+ return Object.assign({}, state, {
+ channelDisconnected: true
+ })
+ }
+ case 'RECEIVED_VERIFICATION_RESULT': {
+ if (action.msg.verificationResult === 'ok') {
+ return window.location.replace(window.location.href.split('/contract_verifications')[0] + '/contracts')
+ } else {
+ return Object.assign({}, state, {
+ newForm: action.msg.verificationResult
+ })
+ }
+ }
+ default:
+ return state
+ }
+}
+
+const elements = {
+ '[data-selector="channel-disconnected-message"]': {
+ render ($el, state) {
+ if (state.channelDisconnected) $el.show()
+ }
+ },
+ '[data-page="contract-verification"]': {
+ render ($el, state) {
+ if (state.newForm) {
+ $el.replaceWith(state.newForm)
+ $('button[data-button-loading="animation"]').click(event => {
+ $('#loading').removeClass('d-none')
+ })
+
+ $(function () {
+ $('.js-btn-add-contract-libraries').on('click', function () {
+ $('.js-smart-contract-libraries-wrapper').show()
+ $(this).hide()
+ })
+
+ $('.js-smart-contract-form-reset').on('click', function () {
+ $('.js-contract-library-form-group').removeClass('active')
+ $('.js-contract-library-form-group').first().addClass('active')
+ $('.js-smart-contract-libraries-wrapper').hide()
+ $('.js-btn-add-contract-libraries').show()
+ $('.js-add-contract-library-wrapper').show()
+ })
+
+ $('.js-btn-add-contract-library').on('click', function () {
+ let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
+
+ if (nextContractLibrary) {
+ nextContractLibrary.addClass('active')
+ }
+
+ if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
+ $('.js-add-contract-library-wrapper').hide()
+ }
+ })
+ })
+
+ return $el
+ }
+ return $el
+ }
+ }
+}
+
+const $contractVerificationPage = $('[data-page="contract-verification"]')
+
+if ($contractVerificationPage.length) {
+ const store = createStore(reducer)
+ const addressHash = $('#smart_contract_address_hash').val()
+ const { filter, blockNumber } = humps.camelizeKeys(URI(window.location).query(true))
+
+ store.dispatch({
+ type: 'PAGE_LOAD',
+ addressHash,
+ filter,
+ beyondPageOne: !!blockNumber
+ })
+ connectElements({ store, elements })
+
+ const addressChannel = subscribeChannel(`addresses:${addressHash}`)
+
+ addressChannel.onError(() => store.dispatch({
+ type: 'CHANNEL_DISCONNECTED'
+ }))
+ addressChannel.on('verification', (msg) => store.dispatch({
+ type: 'RECEIVED_VERIFICATION_RESULT',
+ msg: humps.camelizeKeys(msg)
+ }))
+
+ $('button[data-button-loading="animation"]').click(event => {
+ $('#loading').removeClass('d-none')
+ })
+
+ $(function () {
+ $('.js-btn-add-contract-libraries').on('click', function () {
+ $('.js-smart-contract-libraries-wrapper').show()
+ $(this).hide()
+ })
+
+ $('.js-smart-contract-form-reset').on('click', function () {
+ $('.js-contract-library-form-group').removeClass('active')
+ $('.js-contract-library-form-group').first().addClass('active')
+ $('.js-smart-contract-libraries-wrapper').hide()
+ $('.js-btn-add-contract-libraries').show()
+ $('.js-add-contract-library-wrapper').show()
+ })
+
+ $('.js-btn-add-contract-library').on('click', function () {
+ let nextContractLibrary = $('.js-contract-library-form-group.active').next('.js-contract-library-form-group')
+
+ if (nextContractLibrary) {
+ nextContractLibrary.addClass('active')
+ }
+
+ if ($('.js-contract-library-form-group.active').length === $('.js-contract-library-form-group').length) {
+ $('.js-add-contract-library-wrapper').hide()
+ }
+ })
+ })
+}
diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs
index 28d142eb5c..836a21ba02 100644
--- a/apps/block_scout_web/config/config.exs
+++ b/apps/block_scout_web/config/config.exs
@@ -35,11 +35,6 @@ config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: t
# Configures the endpoint
config :block_scout_web, BlockScoutWeb.Endpoint,
instrumenters: [BlockScoutWeb.Prometheus.Instrumenter, SpandexPhoenix.Instrumenter],
- http: [
- protocol_options: [
- idle_timeout: 90_000
- ]
- ],
url: [
host: System.get_env("BLOCKSCOUT_HOST") || "localhost",
path: System.get_env("NETWORK_PATH") || "/"
diff --git a/apps/block_scout_web/config/dev.exs b/apps/block_scout_web/config/dev.exs
index ce955a764c..8e8aaaddcb 100644
--- a/apps/block_scout_web/config/dev.exs
+++ b/apps/block_scout_web/config/dev.exs
@@ -16,15 +16,9 @@ port =
config :block_scout_web, BlockScoutWeb.Endpoint,
http: [
- protocol_options: [
- idle_timeout: 90_000
- ],
port: port || 4000
],
https: [
- protocol_options: [
- idle_timeout: 90_000
- ],
port: (port && port + 1) || 4001,
cipher_suite: :strong,
certfile: System.get_env("CERTFILE") || "priv/cert/selfsigned.pem",
diff --git a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
index cbbaa7eba7..4009d4f461 100644
--- a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
+++ b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
@@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AddressChannel do
alias Explorer.ExchangeRates.Token
alias Phoenix.View
- intercept(["balance_update", "coin_balance", "count", "internal_transaction", "transaction"])
+ intercept(["balance_update", "coin_balance", "count", "internal_transaction", "transaction", "verification_result"])
def join("addresses:" <> address_hash, _params, socket) do
{:ok, %{}, assign(socket, :address_hash, address_hash)}
@@ -58,6 +58,18 @@ defmodule BlockScoutWeb.AddressChannel do
end
end
+ def handle_out("verification_result", result, socket) do
+ case result[:result] do
+ {:ok, _contract} ->
+ push(socket, "verification", %{verification_result: :ok})
+ {:noreply, socket}
+
+ {:error, result} ->
+ push(socket, "verification", %{verification_result: result})
+ {:noreply, socket}
+ end
+ end
+
def handle_out("count", %{count: count}, socket) do
Gettext.put_locale(BlockScoutWeb.Gettext, socket.assigns.locale)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
index dad0ebaeaf..cfffb85f3b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
@@ -2,7 +2,7 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
use BlockScoutWeb, :controller
alias Explorer.Chain.SmartContract
- alias Explorer.SmartContract.{Publisher, Solidity.CodeCompiler, Solidity.CompilerVersion}
+ alias Explorer.SmartContract.{PublisherWorker, Solidity.CodeCompiler, Solidity.CompilerVersion}
def new(conn, %{"address_id" => address_hash_string}) do
changeset =
@@ -16,31 +16,21 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
- evm_versions: CodeCompiler.allowed_evm_versions()
+ evm_versions: CodeCompiler.allowed_evm_versions(),
+ address_hash: address_hash_string
)
end
def create(
conn,
%{
- "address_id" => address_hash_string,
"smart_contract" => smart_contract,
"external_libraries" => external_libraries
}
) do
- case Publisher.publish(address_hash_string, smart_contract, external_libraries) do
- {:ok, _smart_contract} ->
- redirect(conn, to: address_contract_path(conn, :index, address_hash_string))
+ Que.add(PublisherWorker, {smart_contract["address_hash"], smart_contract, external_libraries, conn})
- {:error, changeset} ->
- {:ok, compiler_versions} = CompilerVersion.fetch_versions()
-
- render(conn, "new.html",
- changeset: changeset,
- compiler_versions: compiler_versions,
- evm_versions: CodeCompiler.allowed_evm_versions()
- )
- end
+ send_resp(conn, 204, "")
end
def parse_optimization_runs(%{"runs" => runs}) do
diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex
index a5bc99e242..2fbe17537b 100644
--- a/apps/block_scout_web/lib/block_scout_web/notifier.ex
+++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex
@@ -4,11 +4,13 @@ defmodule BlockScoutWeb.Notifier do
"""
alias Absinthe.Subscription
- alias BlockScoutWeb.Endpoint
+ alias BlockScoutWeb.{AddressContractVerificationView, Endpoint}
alias Explorer.{Chain, Market, Repo}
alias Explorer.Chain.{Address, InternalTransaction, Transaction}
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token
+ alias Explorer.SmartContract.{Solidity.CodeCompiler, Solidity.CompilerVersion}
+ alias Phoenix.View
def handle_event({:chain_event, :addresses, type, addresses}) when type in [:realtime, :on_demand] do
Endpoint.broadcast("addresses:new_address", "count", %{count: Chain.count_addresses_with_balance_from_cache()})
@@ -23,6 +25,38 @@ defmodule BlockScoutWeb.Notifier do
Enum.each(address_coin_balances, &broadcast_address_coin_balance/1)
end
+ def handle_event(
+ {:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}}
+ ) do
+ contract_verification_result =
+ case contract_verification_result do
+ {:ok, _} = result ->
+ result
+
+ {:error, changeset} ->
+ {:ok, compiler_versions} = CompilerVersion.fetch_versions()
+
+ result =
+ View.render_to_string(AddressContractVerificationView, "new.html",
+ changeset: changeset,
+ compiler_versions: compiler_versions,
+ evm_versions: CodeCompiler.allowed_evm_versions(),
+ address_hash: address_hash,
+ conn: conn
+ )
+
+ {:error, result}
+ end
+
+ Endpoint.broadcast(
+ "addresses:#{address_hash}",
+ "verification_result",
+ %{
+ result: contract_verification_result
+ }
+ )
+ end
+
def handle_event({:chain_event, :block_rewards, :realtime, rewards}) do
if Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:has_emission_funds] do
broadcast_rewards(rewards)
diff --git a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
index f0f73f402c..8357878efe 100644
--- a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
+++ b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
@@ -23,6 +23,7 @@ defmodule BlockScoutWeb.RealtimeEventHandler do
Subscriber.to(:transactions, :realtime)
Subscriber.to(:addresses, :on_demand)
Subscriber.to(:address_coin_balances, :on_demand)
+ Subscriber.to(:contract_verification_result, :on_demand)
# Does not come from the indexer
Subscriber.to(:exchange_rate)
{:ok, []}
diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex
index d13dc9c43e..4f5a8e1bed 100644
--- a/apps/block_scout_web/lib/block_scout_web/router.ex
+++ b/apps/block_scout_web/lib/block_scout_web/router.ex
@@ -29,6 +29,12 @@ defmodule BlockScoutWeb.Router do
resources("/verified_smart_contracts", VerifiedSmartContractController, only: [:create])
end
+ scope "/verify_smart_contract" do
+ pipe_through(:api)
+
+ post("/contract_verifications", BlockScoutWeb.AddressContractVerificationController, :create)
+ end
+
scope "/api", BlockScoutWeb.API.RPC do
pipe_through(:api)
@@ -161,7 +167,7 @@ defmodule BlockScoutWeb.Router do
resources(
"/contract_verifications",
AddressContractVerificationController,
- only: [:new, :create],
+ only: [:new],
as: :verify_contract
)
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
index 505413aa96..32f77425ca 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
@@ -52,17 +52,6 @@
<%= @address.smart_contract.constructor_arguments %>
<% end %>
- <%= if @address.smart_contract.external_libraries do %>
-
-
-
<%= gettext "External libraries" %>
-
-
-
<%= format_smart_contract_abi(@address.smart_contract.abi) %>
-
-
-
- <% end %>
@@ -109,7 +98,7 @@
<% {:ok, contract_code} -> %>
-
<%= gettext "Contract Byte Code" %>
+
<%= gettext "Contract Byte Code" %>
<%= gettext "Copy Contract Byte Code" %>
@@ -120,6 +109,19 @@
<% end %>
+ <%= if BlockScoutWeb.AddressView.smart_contract_verified?(@address) do %>
+ <%= if @address.smart_contract.external_libraries && @address.smart_contract.external_libraries != [] do %>
+
+
+
<%= gettext "External libraries" %>
+
+
+
<%= format_external_libraries(@address.smart_contract.external_libraries) %>
+
+
+
+ <% end %>
+ <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
index 7214af2eee..fd93b0af2b 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
@@ -1,9 +1,15 @@
-
+
+
+
<%= gettext "New Smart Contract Verification" %>
<%= form_for @changeset,
- address_verify_contract_path(@conn, :create, @conn.params["address_id"]),
+ address_contract_verification_path(@conn, :create),
[],
fn f -> %>
@@ -240,13 +246,13 @@
<%= gettext("Loading....") %>
- <%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-loading": "animation" %>
+ <%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-button-loading": "animation" %>
<%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %>
<%=
link(
gettext("Cancel"),
class: "btn-no-border",
- to: address_contract_path(@conn, :index, @conn.params["address_id"])
+ to: address_contract_path(@conn, :index, @address_hash)
)
%>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
index 4dc99a2a68..5de263f820 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
@@ -21,6 +21,12 @@ defmodule BlockScoutWeb.AddressContractView do
def format_optimization_text(true), do: gettext("true")
def format_optimization_text(false), do: gettext("false")
+ def format_external_libraries(libraries) do
+ Enum.reduce(libraries, "", fn %{name: name, address_hash: address_hash}, acc ->
+ acc <> name <> " : " <> address_hash <> "\n"
+ end)
+ end
+
def contract_lines_with_index(contract_source_code) do
contract_lines = String.split(contract_source_code, "\n")
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index 41aa7bf553..8217a39d9c 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -197,7 +197,7 @@ msgid "Blocks Validated"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:253
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel"
msgstr ""
@@ -225,7 +225,7 @@ msgid "Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:34
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Compiler"
msgstr ""
@@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:82
+#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Contract ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:12
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address"
msgstr ""
@@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:23
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:29
msgid "Contract Name"
msgstr ""
@@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:70
+#: lib/block_scout_web/templates/address_contract/index.html.eex:59
msgid "Contract source code"
msgstr ""
@@ -560,7 +560,7 @@ msgid "Name"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67
msgid "No"
msgstr ""
@@ -651,7 +651,7 @@ msgid "Request URL"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:244
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:250
msgid "Reset"
msgstr ""
@@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:243
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:249
msgid "Verify & publish"
msgstr ""
@@ -989,7 +989,7 @@ msgid "Wei"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72
msgid "Yes"
msgstr ""
@@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
msgid "Loading...."
msgstr ""
@@ -1405,17 +1405,17 @@ msgid "Support"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:84
+#: lib/block_scout_web/templates/address_contract/index.html.eex:73
msgid "Copy ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:100
+#: lib/block_scout_web/templates/address_contract/index.html.eex:89
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:72
+#: lib/block_scout_web/templates/address_contract/index.html.eex:61
msgid "Copy Source Code"
msgstr ""
@@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:112
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:118
msgid "Contract Libraries"
msgstr ""
@@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:45
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51
msgid "EVM Version"
msgstr ""
@@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:77
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83
msgid "Optimization runs"
msgstr ""
@@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:112
+#: lib/block_scout_web/templates/address_contract/index.html.eex:101
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:98
+#: lib/block_scout_web/templates/address_contract/index.html.eex:87
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:104
+#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:114
+#: lib/block_scout_web/templates/address_contract/index.html.eex:103
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:105
+#: lib/block_scout_web/templates/address_contract/index.html.eex:94
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:104
msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:87
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93
msgid "Enter the Solidity Contract Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:127
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:133
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:3
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
msgid "New Smart Contract Verification"
msgstr ""
@@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:58
+#: lib/block_scout_web/templates/address_contract/index.html.eex:116
msgid "External libraries"
msgstr ""
@@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12
msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
+msgid "Connection Lost"
+msgstr ""
diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
index 2a85e8470d..b58c06af59 100644
--- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
+++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
@@ -197,7 +197,7 @@ msgid "Blocks Validated"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:253
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47
msgid "Cancel"
msgstr ""
@@ -225,7 +225,7 @@ msgid "Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:34
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Compiler"
msgstr ""
@@ -258,12 +258,12 @@ msgid "Connection Lost, click to load newer validations"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:82
+#: lib/block_scout_web/templates/address_contract/index.html.eex:71
msgid "Contract ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:12
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/views/address_view.ex:97
msgid "Contract Address"
msgstr ""
@@ -286,7 +286,7 @@ msgid "Contract Creation"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:23
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:29
msgid "Contract Name"
msgstr ""
@@ -296,7 +296,7 @@ msgid "Contract name:"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:70
+#: lib/block_scout_web/templates/address_contract/index.html.eex:59
msgid "Contract source code"
msgstr ""
@@ -560,7 +560,7 @@ msgid "Name"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:61
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67
msgid "No"
msgstr ""
@@ -651,7 +651,7 @@ msgid "Request URL"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:244
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:250
msgid "Reset"
msgstr ""
@@ -674,7 +674,7 @@ msgstr ""
#, elixir-format
#:
-#: lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex:28
+#: lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex:30
msgid "Search tokens"
msgstr ""
@@ -877,7 +877,7 @@ msgid "Transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/_tile.html.eex:19
+#: lib/block_scout_web/templates/address/_tile.html.eex:31
msgid "Transactions sent"
msgstr ""
@@ -923,7 +923,7 @@ msgid "Validated Transactions"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address/_tile.html.eex:23
+#: lib/block_scout_web/templates/address/_tile.html.eex:35
msgid "Validations"
msgstr ""
@@ -939,7 +939,7 @@ msgid "Verify & Publish"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:243
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:249
msgid "Verify & publish"
msgstr ""
@@ -989,7 +989,7 @@ msgid "Wei"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:66
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72
msgid "Yes"
msgstr ""
@@ -1062,7 +1062,7 @@ msgid "Loading..."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:247
msgid "Loading...."
msgstr ""
@@ -1405,17 +1405,17 @@ msgid "Support"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:84
+#: lib/block_scout_web/templates/address_contract/index.html.eex:73
msgid "Copy ABI"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:100
+#: lib/block_scout_web/templates/address_contract/index.html.eex:89
msgid "Copy Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:72
+#: lib/block_scout_web/templates/address_contract/index.html.eex:61
msgid "Copy Source Code"
msgstr ""
@@ -1425,7 +1425,7 @@ msgid "Genesis Block"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:112
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:118
msgid "Contract Libraries"
msgstr ""
@@ -1488,7 +1488,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:35
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:45
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51
msgid "EVM Version"
msgstr ""
@@ -1519,7 +1519,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:45
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:77
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83
msgid "Optimization runs"
msgstr ""
@@ -1585,27 +1585,27 @@ msgid "Block Details"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:112
+#: lib/block_scout_web/templates/address_contract/index.html.eex:101
msgid "Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:98
+#: lib/block_scout_web/templates/address_contract/index.html.eex:87
msgid "Contract Creation Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:104
+#: lib/block_scout_web/templates/address_contract/index.html.eex:93
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:114
+#: lib/block_scout_web/templates/address_contract/index.html.eex:103
msgid "Copy Contract Byte Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:105
+#: lib/block_scout_web/templates/address_contract/index.html.eex:94
msgid "Displaying the init data provided of the creating transaction."
msgstr ""
@@ -1655,35 +1655,35 @@ msgid "Topic"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:104
msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:87
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93
msgid "Enter the Solidity Contract Code"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:127
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:149
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:171
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:193
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:215
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:133
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:155
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:177
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:199
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:221
msgid "Library Address"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:117
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:183
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:205
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:123
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:145
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:167
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:189
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:211
msgid "Library Name"
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:3
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
msgid "New Smart Contract Verification"
msgstr ""
@@ -1769,7 +1769,7 @@ msgid "ERC-721 "
msgstr ""
#, elixir-format
-#: lib/block_scout_web/templates/address_contract/index.html.eex:58
+#: lib/block_scout_web/templates/address_contract/index.html.eex:116
msgid "External libraries"
msgstr ""
@@ -1797,3 +1797,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:12
msgid "Use the search box to find a hosted network, or select from the list of available networks below."
msgstr ""
+
+#, elixir-format
+#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
+msgid "Connection Lost"
+msgstr ""
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index 8a7a9151b3..8ef228da30 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -2426,8 +2426,13 @@ defmodule Explorer.Chain do
naming the address for reference.
"""
@spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()}
- def create_smart_contract(attrs \\ %{}) do
- smart_contract_changeset = SmartContract.changeset(%SmartContract{}, attrs)
+ def create_smart_contract(attrs \\ %{}, external_libraries \\ []) do
+ new_contract = %SmartContract{}
+
+ smart_contract_changeset =
+ new_contract
+ |> SmartContract.changeset(attrs)
+ |> Changeset.put_change(:external_libraries, external_libraries)
insert_result =
Multi.new()
diff --git a/apps/explorer/lib/explorer/chain/events/publisher.ex b/apps/explorer/lib/explorer/chain/events/publisher.ex
index 7077fdfeab..c7e01eef3a 100644
--- a/apps/explorer/lib/explorer/chain/events/publisher.ex
+++ b/apps/explorer/lib/explorer/chain/events/publisher.ex
@@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Publisher do
Publishes events related to the Chain context.
"""
- @allowed_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions)a
+ @allowed_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a
def broadcast(_data, false), do: :ok
diff --git a/apps/explorer/lib/explorer/chain/events/subscriber.ex b/apps/explorer/lib/explorer/chain/events/subscriber.ex
index 6a9df99438..7d24ce4cd5 100644
--- a/apps/explorer/lib/explorer/chain/events/subscriber.ex
+++ b/apps/explorer/lib/explorer/chain/events/subscriber.ex
@@ -3,9 +3,9 @@ defmodule Explorer.Chain.Events.Subscriber do
Subscribes to events related to the Chain context.
"""
- @allowed_broadcast_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions)a
+ @allowed_broadcast_events ~w(addresses address_coin_balances blocks block_rewards internal_transactions token_transfers transactions contract_verification_result)a
- @allowed_broadcast_types ~w(catchup realtime on_demand)a
+ @allowed_broadcast_types ~w(catchup realtime on_demand contract_verification_result)a
@allowed_events ~w(exchange_rate)a
diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex
index 9dee6b147e..ed579e8e00 100644
--- a/apps/explorer/lib/explorer/chain/smart_contract.ex
+++ b/apps/explorer/lib/explorer/chain/smart_contract.ex
@@ -13,6 +13,7 @@ defmodule Explorer.Chain.SmartContract do
use Explorer.Schema
alias Explorer.Chain.{Address, ContractMethod, DecompiledSmartContract, Hash}
+ alias Explorer.Chain.SmartContract.ExternalLibrary
alias Explorer.Repo
@typedoc """
@@ -212,7 +213,7 @@ defmodule Explorer.Chain.SmartContract do
field(:constructor_arguments, :string)
field(:evm_version, :string)
field(:optimization_runs, :integer)
- field(:external_libraries, :map)
+ embeds_many(:external_libraries, ExternalLibrary)
field(:abi, {:array, :map})
has_many(
@@ -247,8 +248,7 @@ defmodule Explorer.Chain.SmartContract do
:abi,
:constructor_arguments,
:evm_version,
- :optimization_runs,
- :external_libraries
+ :optimization_runs
])
|> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash])
|> unique_constraint(:address_hash)
diff --git a/apps/explorer/lib/explorer/chain/smart_contract/external_library.ex b/apps/explorer/lib/explorer/chain/smart_contract/external_library.ex
new file mode 100644
index 0000000000..ac52388de5
--- /dev/null
+++ b/apps/explorer/lib/explorer/chain/smart_contract/external_library.ex
@@ -0,0 +1,12 @@
+defmodule Explorer.Chain.SmartContract.ExternalLibrary do
+ @moduledoc """
+ The representation of an external library that was used for a smart contract.
+ """
+
+ use Ecto.Schema
+
+ embedded_schema do
+ field(:name)
+ field(:address_hash)
+ end
+end
diff --git a/apps/explorer/lib/explorer/smart_contract/publisher.ex b/apps/explorer/lib/explorer/smart_contract/publisher.ex
index 702b45976d..ae5a24c088 100644
--- a/apps/explorer/lib/explorer/smart_contract/publisher.ex
+++ b/apps/explorer/lib/explorer/smart_contract/publisher.ex
@@ -28,17 +28,17 @@ defmodule Explorer.SmartContract.Publisher do
case Verifier.evaluate_authenticity(address_hash, params_with_external_libaries) do
{:ok, %{abi: abi}} ->
- publish_smart_contract(address_hash, params, abi)
+ publish_smart_contract(address_hash, params_with_external_libaries, abi)
{:error, error} ->
- {:error, unverified_smart_contract(address_hash, params, error)}
+ {:error, unverified_smart_contract(address_hash, params_with_external_libaries, error)}
end
end
defp publish_smart_contract(address_hash, params, abi) do
- address_hash
- |> attributes(params, abi)
- |> Chain.create_smart_contract()
+ attrs = address_hash |> attributes(params, abi)
+
+ Chain.create_smart_contract(attrs, attrs.external_libraries)
end
defp unverified_smart_contract(address_hash, params, error) do
@@ -64,6 +64,8 @@ defmodule Explorer.SmartContract.Publisher do
nil
end
+ prepared_external_libraries = prepare_external_libraies(params["external_libraries"])
+
%{
address_hash: address_hash,
name: params["name"],
@@ -73,11 +75,20 @@ defmodule Explorer.SmartContract.Publisher do
optimization: params["optimization"],
contract_source_code: params["contract_source_code"],
constructor_arguments: clean_constructor_arguments,
- external_libaries: params["external_libraries"],
+ external_libraries: prepared_external_libraries,
abi: abi
}
end
+ defp prepare_external_libraies(nil), do: []
+
+ defp prepare_external_libraies(map) do
+ map
+ |> Enum.map(fn {key, value} ->
+ %{name: key, address_hash: value}
+ end)
+ end
+
defp add_external_libraries(params, external_libraries) do
clean_external_libraries =
Enum.reduce(1..5, %{}, fn number, acc ->
diff --git a/apps/explorer/lib/explorer/smart_contract/publisher_worker.ex b/apps/explorer/lib/explorer/smart_contract/publisher_worker.ex
new file mode 100644
index 0000000000..f0c248c8fb
--- /dev/null
+++ b/apps/explorer/lib/explorer/smart_contract/publisher_worker.ex
@@ -0,0 +1,23 @@
+defmodule Explorer.SmartContract.PublisherWorker do
+ @moduledoc """
+ Background smart contract verification worker.
+ """
+
+ use Que.Worker, concurrency: 5
+
+ alias Explorer.Chain.Events.Publisher, as: EventsPublisher
+ alias Explorer.SmartContract.Publisher
+
+ def perform({address_hash, params, external_libraries, conn}) do
+ result =
+ case Publisher.publish(address_hash, params, external_libraries) do
+ {:ok, _contract} = result ->
+ result
+
+ {:error, changeset} ->
+ {:error, changeset}
+ end
+
+ EventsPublisher.broadcast([{:contract_verification_result, {address_hash, result, conn}}], :on_demand)
+ end
+end
diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs
index 79574b9354..2e9ad1a248 100644
--- a/apps/explorer/mix.exs
+++ b/apps/explorer/mix.exs
@@ -106,6 +106,7 @@ defmodule Explorer.Mixfile do
},
# bypass optional dependency
{:plug_cowboy, "~> 2.0", only: [:dev, :test]},
+ {:que, "~> 0.10.1"},
{:sobelow, ">= 0.7.0", only: [:dev, :test], runtime: false},
# Tracing
{:spandex, github: "spandex-project/spandex", branch: "allow-setting-trace-key", override: true},
diff --git a/apps/explorer/priv/repo/migrations/20190709103104_add_external_libraries_to_smart_contracts.exs b/apps/explorer/priv/repo/migrations/20190709103104_add_external_libraries_to_smart_contracts.exs
new file mode 100644
index 0000000000..5200253f84
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20190709103104_add_external_libraries_to_smart_contracts.exs
@@ -0,0 +1,13 @@
+defmodule Explorer.Repo.Migrations.AddExternalLibrariesToSmartContracts do
+ use Ecto.Migration
+
+ def change do
+ alter table(:smart_contracts) do
+ remove(:external_libraries)
+ end
+
+ alter table(:smart_contracts) do
+ add(:external_libraries, {:array, :map}, default: [])
+ end
+ end
+end
diff --git a/mix.lock b/mix.lock
index 95bc035f89..5ff4c0f8d0 100644
--- a/mix.lock
+++ b/mix.lock
@@ -42,6 +42,7 @@
"ex_doc": {:hex, :ex_doc, "0.19.2", "6f4081ccd9ed081b6dc0bd5af97a41e87f5554de469e7d76025fba535180565f", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.2.2", "d84217a6fb7840ff771d2561b8aa6d74a0d8968e4b10ecc0d7e9890dc8fb1c6a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
+ "ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], []},
"excoveralls": {:git, "https://github.com/KronicDeth/excoveralls.git", "0a859b68851eeba9b43eba59fbc8f9098299cfe1", [branch: "circle-workflows"]},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]},
@@ -66,6 +67,7 @@
"makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"math": {:hex, :math, "0.3.0", "e14e7291115201cb155a3567e66d196bf5088a6f55b030d598107d7ae934a11c", [:mix], []},
"meck": {:hex, :meck, "0.8.12", "1f7b1a9f5d12c511848fec26bbefd09a21e1432eadb8982d9a8aceb9891a3cf2", [:rebar3], [], "hexpm"},
+ "memento": {:hex, :memento, "0.3.1", "b2909390820550d8b90b68ec96f9e15ff8a45a28b6f97fa4a62ef50e87c2f9d9", [:mix], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
@@ -98,6 +100,7 @@
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
"prometheus_process_collector": {:hex, :prometheus_process_collector, "1.4.0", "6dbd39e3165b9ef1c94a7a820e9ffe08479f949dcdd431ed4aaea7b250eebfde", [:rebar3], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
"qrcode": {:hex, :qrcode, "0.1.4", "544dc67ba42eed5ebce3d2a691d053387937740561d251f83f0a067917fae2dc", [:mix], [], "hexpm"},
+ "que": {:hex, :que, "0.10.1", "788ed0ec92ed69bdf9cfb29bf41a94ca6355b8d44959bd0669cf706e557ac891", [:mix], [{:ex_utils, "~> 0.1.6", [hex: :ex_utils, repo: "hexpm", optional: false]}, {:memento, "~> 0.3.0", [hex: :memento, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"set_locale": {:git, "https://github.com/minifast/set_locale.git", "da9ae029642bc0fbd9212c2aaf86c0adca70c084", [branch: "master"]},
"sobelow": {:hex, :sobelow, "0.7.4", "228cc6185b448b63ecc88429b43e864e8dd570e8e09f2d04b3aa71894db1bdbb", [:mix], [], "hexpm"},