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" %>

@@ -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"},