diff --git a/.circleci/config.yml b/.circleci/config.yml index 50b28b631b..f93c373f73 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -345,7 +345,7 @@ jobs: # PGUSER: postgres # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.HTTPWebSocket" # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Geth" - # - image: circleci/postgres:10.3-alpine + # - image: circleci/postgres:10.10-alpine # environment: # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database # POSTGRES_DB: explorer_test @@ -399,7 +399,7 @@ jobs: # PGUSER: postgres # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.Mox" # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - # - image: circleci/postgres:10.3-alpine + # - image: circleci/postgres:10.10-alpine # environment: # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database # POSTGRES_DB: explorer_test @@ -453,7 +453,7 @@ jobs: # PGUSER: postgres # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.HTTPWebSocket" # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Parity" - # - image: circleci/postgres:10.3-alpine + # - image: circleci/postgres:10.10-alpine # environment: # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database # POSTGRES_DB: explorer_test @@ -507,7 +507,7 @@ jobs: PGUSER: postgres ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - - image: circleci/postgres:10.3-alpine + - image: circleci/postgres:10.10-alpine environment: # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database POSTGRES_DB: explorer_test diff --git a/CHANGELOG.md b/CHANGELOG.md index e933805af6..6b7140c59d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,32 @@ ## Current ### Features -- [#2835](https://github.com/poanetwork/blockscout/pull/2835), [#2871](https://github.com/poanetwork/blockscout/pull/2871), [#2872](https://github.com/poanetwork/blockscout/pull/2872), [#2886](https://github.com/poanetwork/blockscout/pull/2886), [#2925](https://github.com/poanetwork/blockscout/pull/2925), [#2936](https://github.com/poanetwork/blockscout/pull/2936) - Add "block_hash" to logs, token_transfers and internal transactions and "pending blocks operations" approach + +### Fixes +- [#2989](https://github.com/poanetwork/blockscout/pull/2989) - Introduce API_PATH env var +- [#2988](https://github.com/poanetwork/blockscout/pull/2988) - Fix web manifest accessibility +- [#2897](https://github.com/poanetwork/blockscout/pull/2897) - remove duplicate indexes + +### Chore + + +## 3.0.0-beta + +### Features +- [#2835](https://github.com/poanetwork/blockscout/pull/2835), [#2871](https://github.com/poanetwork/blockscout/pull/2871), [#2872](https://github.com/poanetwork/blockscout/pull/2872), [#2886](https://github.com/poanetwork/blockscout/pull/2886), [#2925](https://github.com/poanetwork/blockscout/pull/2925), [#2936](https://github.com/poanetwork/blockscout/pull/2936), [#2949](https://github.com/poanetwork/blockscout/pull/2949), [#2940](https://github.com/poanetwork/blockscout/pull/2940), [#2958](https://github.com/poanetwork/blockscout/pull/2958) - Add "block_hash" to logs, token_transfers and internal transactions and "pending blocks operations" approach +- [#2975](https://github.com/poanetwork/blockscout/pull/2975) - Refine UX of contracts verification - [#2926](https://github.com/poanetwork/blockscout/pull/2926) - API endpoint: sum balances except burnt address - [#2918](https://github.com/poanetwork/blockscout/pull/2918) - Add tokenID for tokentx API action explicitly ### Fixes +- [#2969](https://github.com/poanetwork/blockscout/pull/2969) - Fix contract constructor require msg appearance in constructor arguments encoded view +- [#2964](https://github.com/poanetwork/blockscout/pull/2964) - Fix bug in skipping of constructor arguments in contract verification +- [#2961](https://github.com/poanetwork/blockscout/pull/2961) - Add a guard that addresses is enum in `values` function in `read contract` page +- [#2960](https://github.com/poanetwork/blockscout/pull/2960) - Add BLOCKSCOUT_HOST to docker setup +- [#2956](https://github.com/poanetwork/blockscout/pull/2956) - Add support of 0.6.x version of compiler +- [#2955](https://github.com/poanetwork/blockscout/pull/2955) - Move socket path to env - [#2950](https://github.com/poanetwork/blockscout/pull/2950) - Add `creationMethod` to `EthereumJSONRPC.Parity.Trace.Action.entry_to_elixir` +- [#2938](https://github.com/poanetwork/blockscout/pull/2938) - utf8 copy tx input tooltip - [#2934](https://github.com/poanetwork/blockscout/pull/2934) - RSK release 1.2.0 breaking changes support - [#2933](https://github.com/poanetwork/blockscout/pull/2933) - Get rid of deadlock in the query to address_current_token_balance table - [#2932](https://github.com/poanetwork/blockscout/pull/2932) - fix duplicate websocket connection @@ -14,6 +34,7 @@ - [#2924](https://github.com/poanetwork/blockscout/pull/2924) - Speedup address to logs query - [#2915](https://github.com/poanetwork/blockscout/pull/2915) - Speedup of blocks_without_reward_query - [#2914](https://github.com/poanetwork/blockscout/pull/2914) - Reduce execution time of stream_unfetched_token_instances query +- [2910](https://github.com/poanetwork/blockscout/pull/2910) - Reorganize queries and indexes for internal_transactions table - [#2908](https://github.com/poanetwork/blockscout/pull/2908) - Fix performance of address page - [#2906](https://github.com/poanetwork/blockscout/pull/2906) - fix address sum cache - [#2902](https://github.com/poanetwork/blockscout/pull/2902) - Offset in blocks retrieval for average block time @@ -21,9 +42,12 @@ - [#2899](https://github.com/poanetwork/blockscout/pull/2899) - fix empty buffered task - [#2887](https://github.com/poanetwork/blockscout/pull/2887) - increase chart loading speed -- [2910](https://github.com/poanetwork/blockscout/pull/2910) - Reorganize queries and indexes for internal_transactions table - ### Chore +- [#2959](https://github.com/poanetwork/blockscout/pull/2959) - Remove logs from test folder too in the cleaning script +- [#2954](https://github.com/poanetwork/blockscout/pull/2954) - Upgrade absinthe and ecto deps +- [#2947](https://github.com/poanetwork/blockscout/pull/2947) - Upgrade Circle CI postgres Docker image +- [#2946](https://github.com/poanetwork/blockscout/pull/2946) - Fix vulnerable NPM deps +- [#2942](https://github.com/poanetwork/blockscout/pull/2942) - Actualize Docker setup - [#2896](https://github.com/poanetwork/blockscout/pull/2896) - Disable Parity websockets tests diff --git a/apps/block_scout_web/assets/css/theme/_ethercore_variables-non-critical.scss b/apps/block_scout_web/assets/css/theme/_ethercore_variables-non-critical.scss new file mode 100644 index 0000000000..05844600df --- /dev/null +++ b/apps/block_scout_web/assets/css/theme/_ethercore_variables-non-critical.scss @@ -0,0 +1,7 @@ +// general +$primary: #3a6ea7; +$secondary: #558ac3; +$tertiary: #3a6ea7; +$additional-font: #bdbdff; + +$btn-line-color: $tertiary; // button border and font color && hover bg color diff --git a/apps/block_scout_web/assets/css/theme/_ethercore_variables.scss b/apps/block_scout_web/assets/css/theme/_ethercore_variables.scss new file mode 100644 index 0000000000..e5f99efb54 --- /dev/null +++ b/apps/block_scout_web/assets/css/theme/_ethercore_variables.scss @@ -0,0 +1,84 @@ +// general +$primary: #3a6ea7; +$secondary: #558ac3; +$tertiary: #3a6ea7; +$additional-font: #bdbdff; + +// footer +$footer-background-color: $primary; +$footer-title-color: #fff; +$footer-text-color: $additional-font; +$footer-item-disc-color: $tertiary; +$footer-social-icon-color: #3a6ea7; + +// dashboard +$dashboard-line-color-price: $secondary; +$dashboard-line-color-market: $tertiary; +$dashboard-banner-gradient-start: #7ba4d1; +$dashboard-banner-gradient-end: #3a6ea7; + +$dashboard-banner-chart-legend-label-color: $additional-font; +$dashboard-stats-item-label-color: $additional-font; +$dashboard-banner-chart-legend-value-color: #fff; // chart labels +$dashboard-stats-item-value-color: #fff; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border +$dashboard-banner-network-plain-container-background-color: #2e5884; // stats bg + +// navigation +$header-icon-border-color-hover: $tertiary; // top border on hover +$header-icon-color-hover: $tertiary; // nav icon on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: $tertiary; // button border and font color && hover bg color +$btn-copy-color: $tertiary; // btn copy +$btn-qr-color: $tertiary; // btn qr-code +$btn-address-card-icon-color: $tertiary; // btn address color +$btn-contract-color: $tertiary; + +//links & tile +$tile-body-a-color: $tertiary; +$tile-type-block-color: $tertiary; +$tile-type-progress-bar-color: $tertiary; +a.tile-title { color: $tertiary !important; } + +// card +$card-background-1: $tertiary; +$card-tab-active: $tertiary; + +// ETC theme's idiosyncrasies +.layout-container { + .navbar { + box-shadow: 0 0 30px 0 rgba(21, 53, 80, 0.12); + } + + .dropdown-item:hover, + .dropdown-item.active, + .dropdown-item:focus { + background-color: rgba($tertiary, .1) !important; + color: $tertiary !important; + } + + .dashboard-banner-container { + background-image: linear-gradient( + to bottom, + $dashboard-banner-gradient-start, + $dashboard-banner-gradient-end + ); + } + + .footer-logo { + filter: brightness(0) invert(1); + } +} + +// Badges +$badge-neutral-color: $tertiary; +$badge-neutral-background-color: rgba($tertiary, .1); +$api-text-monospace-color: $tertiary; + +// Dark theme +$dark-primary: #8588ff; +$dark-secondary: #4ad7a7; +$dark-primary-alternate: #5b5ed8; diff --git a/apps/block_scout_web/assets/css/theme/_variables-non-critical.scss b/apps/block_scout_web/assets/css/theme/_variables-non-critical.scss index 39762ec68a..24c9f77350 100644 --- a/apps/block_scout_web/assets/css/theme/_variables-non-critical.scss +++ b/apps/block_scout_web/assets/css/theme/_variables-non-critical.scss @@ -20,4 +20,5 @@ // @import "sokol_variables-non-critical"; // @import "tobalaba_variables-non-critical"; // @import "tomochain_variables-non-critical"; -// @import "rsk_variables-non-critical"; \ No newline at end of file +// @import "rsk_variables-non-critical"; +// @import "ethercore_variables-non-critical"; diff --git a/apps/block_scout_web/assets/css/theme/_variables.scss b/apps/block_scout_web/assets/css/theme/_variables.scss index 15571b454b..d2108eb342 100644 --- a/apps/block_scout_web/assets/css/theme/_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_variables.scss @@ -21,6 +21,7 @@ // @import "tobalaba_variables"; // @import "tomochain_variables"; // @import "rsk_variables"; +// @import "ethercore_variables"; // responsive breakpoints $breakpoint-xs: 320px; diff --git a/apps/block_scout_web/assets/js/lib/try_eth_api.js b/apps/block_scout_web/assets/js/lib/try_eth_api.js index 30299431be..fa611e5c4a 100644 --- a/apps/block_scout_web/assets/js/lib/try_eth_api.js +++ b/apps/block_scout_web/assets/js/lib/try_eth_api.js @@ -44,8 +44,9 @@ function parseInput (input) { } } -function dropDomain (url) { - return new URL(url).pathname +function composeRequestUrl () { + const url = $('[data-endpoint-url]').attr('data-endpoint-url') + return url } $('button[data-try-eth-api-ui-button-type="execute"]').click(event => { @@ -64,10 +65,8 @@ $('button[data-try-eth-api-ui-button-type="execute"]').click(event => { clickedButton.html(loadingText) } - const url = $('[data-endpoint-url]').attr('data-endpoint-url') - $.ajax({ - url: dropDomain(url), + url: composeRequestUrl(), type: 'POST', data: JSON.stringify(formData), dataType: 'json', diff --git a/apps/block_scout_web/assets/js/pages/verification_form.js b/apps/block_scout_web/assets/js/pages/verification_form.js index 1267d12c39..795cbf757b 100644 --- a/apps/block_scout_web/assets/js/pages/verification_form.js +++ b/apps/block_scout_web/assets/js/pages/verification_form.js @@ -88,6 +88,26 @@ const elements = { const $contractVerificationPage = $('[data-page="contract-verification"]') +function filterNightlyBuilds (filter) { + var select, options + select = document.getElementById('smart_contract_compiler_version') + options = select.getElementsByTagName('option') + for (const option of options) { + var txtValue = option.textContent || option.innerText + if (filter) { + if (txtValue.toLowerCase().indexOf('nightly') > -1) { + option.style.display = 'none' + } else { + option.style.display = '' + } + } else { + if (txtValue.toLowerCase().indexOf('nightly') > -1) { + option.style.display = '' + } + } + } +} + if ($contractVerificationPage.length) { const store = createStore(reducer) const addressHash = $('#smart_contract_address_hash').val() @@ -116,6 +136,10 @@ if ($contractVerificationPage.length) { }) $(function () { + setTimeout(function () { + $('.nightly-builds-false').trigger('click') + }, 10) + $('.js-btn-add-contract-libraries').on('click', function () { $('.js-smart-contract-libraries-wrapper').show() $(this).hide() @@ -129,6 +153,22 @@ if ($contractVerificationPage.length) { if ($(this).prop('checked')) { $('.constructor-arguments').hide() } }) + $('.nightly-builds-true').on('click', function () { + if ($(this).prop('checked')) { filterNightlyBuilds(false) } + }) + + $('.nightly-builds-false').on('click', function () { + if ($(this).prop('checked')) { filterNightlyBuilds(true) } + }) + + $('.optimization-false').on('click', function () { + if ($(this).prop('checked')) { $('.optimization-runs').hide() } + }) + + $('.optimization-true').on('click', function () { + if ($(this).prop('checked')) { $('.optimization-runs').show() } + }) + $('.js-smart-contract-form-reset').on('click', function () { $('.js-contract-library-form-group').removeClass('active') $('.js-contract-library-form-group').first().addClass('active') diff --git a/apps/block_scout_web/assets/js/socket.js b/apps/block_scout_web/assets/js/socket.js index 3490157a8b..b2eaa282df 100644 --- a/apps/block_scout_web/assets/js/socket.js +++ b/apps/block_scout_web/assets/js/socket.js @@ -1,7 +1,12 @@ import { Socket } from 'phoenix' import { locale } from './locale' -const socket = new Socket('/socket', { params: { locale: locale } }) +let websocketRootUrl = process.env.SOCKET_ROOT +if (!websocketRootUrl || websocketRootUrl === '/') { + websocketRootUrl = '' +} + +const socket = new Socket(websocketRootUrl + '/socket', { params: { locale: locale } }) socket.connect() export default socket diff --git a/apps/block_scout_web/assets/package-lock.json b/apps/block_scout_web/assets/package-lock.json index b24d278bae..5cdcd178fd 100644 --- a/apps/block_scout_web/assets/package-lock.json +++ b/apps/block_scout_web/assets/package-lock.json @@ -5883,9 +5883,9 @@ "dev": true }, "handlebars": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz", - "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.6.0.tgz", + "integrity": "sha512-i1ZUP7Qp2JdkMaFon2a+b0m5geE8Z4ZTLaGkgrObkEd+OkUKyRbRWw4KxuFCoHfdETSY1yf9/574eVoNSiK7pw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -11466,9 +11466,9 @@ "dev": true }, "serialize-javascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.0.tgz", - "integrity": "sha512-a/mxFfU00QT88umAJQsNWOnUKckhNCqOl028N48e7wFmo2/EHpTo9Wso+iJJCMrQnmFvcjto5RJdAHEvVhcyUQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "set-blocking": { @@ -12672,9 +12672,9 @@ "dev": true }, "uglify-js": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", - "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.4.tgz", + "integrity": "sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg==", "dev": true, "optional": true, "requires": { @@ -13312,12 +13312,6 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13325,20 +13319,31 @@ "dev": true }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "dev": true, "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" + }, + "dependencies": { + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + } } } } @@ -13586,15 +13591,6 @@ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/apps/block_scout_web/assets/package.json b/apps/block_scout_web/assets/package.json index 8d36aa8797..ec3192a2a4 100644 --- a/apps/block_scout_web/assets/package.json +++ b/apps/block_scout_web/assets/package.json @@ -8,8 +8,8 @@ "author": "POA Network", "license": "GPL-3.0", "engines": { - "node": "9.x", - "npm": "5.x" + "node": "12.x", + "npm": "6.x" }, "scripts": { "deploy": "webpack --mode production", diff --git a/apps/block_scout_web/assets/static/images/ethercore_logo.svg b/apps/block_scout_web/assets/static/images/ethercore_logo.svg new file mode 100644 index 0000000000..993c43dec0 --- /dev/null +++ b/apps/block_scout_web/assets/static/images/ethercore_logo.svg @@ -0,0 +1,10139 @@ + + + + + + + diff --git a/apps/block_scout_web/assets/static/images/ethercore_testnet_logo.svg b/apps/block_scout_web/assets/static/images/ethercore_testnet_logo.svg new file mode 100644 index 0000000000..d114fb8cd5 --- /dev/null +++ b/apps/block_scout_web/assets/static/images/ethercore_testnet_logo.svg @@ -0,0 +1,5382 @@ + + + + + + + diff --git a/apps/block_scout_web/assets/static/site.webmanifest b/apps/block_scout_web/assets/static/manifest.webmanifest similarity index 100% rename from apps/block_scout_web/assets/static/site.webmanifest rename to apps/block_scout_web/assets/static/manifest.webmanifest diff --git a/apps/block_scout_web/assets/webpack.config.js b/apps/block_scout_web/assets/webpack.config.js index 07452b55c8..1cf3ac2b62 100644 --- a/apps/block_scout_web/assets/webpack.config.js +++ b/apps/block_scout_web/assets/webpack.config.js @@ -5,6 +5,7 @@ const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') const { ContextReplacementPlugin } = require('webpack') const glob = require('glob') +const webpack = require('webpack') function transpileViewScript(file) { return { @@ -136,7 +137,10 @@ const appJs = filename: '../css/[name].css' }), new CopyWebpackPlugin([{ from: 'static/', to: '../' }]), - new ContextReplacementPlugin(/moment[\/\\]locale$/, /en/) + new ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), + new webpack.DefinePlugin({ + 'process.env.SOCKET_ROOT': JSON.stringify(process.env.SOCKET_ROOT) + }) ] } diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index e5d7ed947c..8c96401f9a 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -41,7 +41,8 @@ config :block_scout_web, BlockScoutWeb.Endpoint, url: [ scheme: System.get_env("BLOCKSCOUT_PROTOCOL") || "http", host: System.get_env("BLOCKSCOUT_HOST") || "localhost", - path: System.get_env("NETWORK_PATH") || "/" + path: System.get_env("NETWORK_PATH") || "/", + api_path: System.get_env("API_PATH") || "/" ], render_errors: [view: BlockScoutWeb.ErrorView, accepts: ~w(html json)], pubsub: [name: BlockScoutWeb.PubSub] diff --git a/apps/block_scout_web/config/dev.exs b/apps/block_scout_web/config/dev.exs index de386f1a5d..fa1e25341d 100644 --- a/apps/block_scout_web/config/dev.exs +++ b/apps/block_scout_web/config/dev.exs @@ -21,7 +21,8 @@ config :block_scout_web, BlockScoutWeb.Endpoint, url: [ scheme: "http", host: System.get_env("BLOCKSCOUT_HOST") || "localhost", - path: System.get_env("NETWORK_PATH") || "/" + path: System.get_env("NETWORK_PATH") || "/", + api_path: System.get_env("API_PATH") || "/" ], https: [ port: (port && port + 1) || 4001, diff --git a/apps/block_scout_web/config/prod.exs b/apps/block_scout_web/config/prod.exs index 00cedfe8c3..4d97721ce4 100644 --- a/apps/block_scout_web/config/prod.exs +++ b/apps/block_scout_web/config/prod.exs @@ -23,7 +23,8 @@ config :block_scout_web, BlockScoutWeb.Endpoint, scheme: System.get_env("BLOCKSCOUT_PROTOCOL") || "https", port: System.get_env("PORT"), host: System.get_env("BLOCKSCOUT_HOST") || "localhost", - path: System.get_env("NETWORK_PATH") || "/" + path: System.get_env("NETWORK_PATH") || "/", + api_path: System.get_env("API_PATH") || "/" ] config :block_scout_web, BlockScoutWeb.Tracer, env: "production", disabled?: true diff --git a/apps/block_scout_web/lib/block_scout_web/endpoint.ex b/apps/block_scout_web/lib/block_scout_web/endpoint.ex index 86e86ad79b..f293f83ec3 100644 --- a/apps/block_scout_web/lib/block_scout_web/endpoint.ex +++ b/apps/block_scout_web/lib/block_scout_web/endpoint.ex @@ -29,9 +29,9 @@ defmodule BlockScoutWeb.Endpoint do browserconfig.xml mstile-150x150.png safari-pinned-tab.svg - site.manifest robots.txt - ) + ), + only_matching: ~w(manifest) ) # Code reloading can be explicitly enabled under the 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 ddaa85a18b..1002375ac2 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 @@ -35,6 +35,28 @@ +
+
+ <%= label f, "Include nightly builds" %> +
+
+
+ <%= radio_button f, :nightly_builds, false, checked: true, class: "form-check-input nightly-builds-false" %> +
+ <%= label :nightly_builds, :false, gettext("No"), class: "radio-text" %> +
+
+ <%= radio_button f, :nightly_builds, true, class: "form-check-input nightly-builds-true", "aria-describedby": "nightly_builds-help-block" %> +
+ <%= label :nightly_builds, :true, gettext("Yes"), class: "radio-text" %> +
+
+ <%= error_tag f, :nightly_builds, id: "nightly_builds-help-block", class: "text-danger form-error" %> +
+
Select yes if you want to show nightly builds.
+
+
+
<%= label f, :compiler_version, gettext("Compiler") %> @@ -62,12 +84,12 @@
- <%= radio_button f, :optimization, false, checked: true, class: "form-check-input" %> + <%= radio_button f, :optimization, false, class: "form-check-input optimization-false" %>
<%= label :smart_contract_optimization, :false, gettext("No"), class: "radio-text" %>
- <%= radio_button f, :optimization, true, class: "form-check-input", "aria-describedby": "optimization-help-block" %> + <%= radio_button f, :optimization, true, checked: true, class: "form-check-input optimization-true", "aria-describedby": "optimization-help-block" %>
<%= label :smart_contract_optimization, :true, gettext("Yes"), class: "radio-text" %>
@@ -78,7 +100,7 @@
-
+
<%= label f, :name, gettext("Optimization runs") %>
@@ -110,12 +132,12 @@ <%= label :autodetect_contructor_args, :false, gettext("No"), class: "radio-text" %>
- <%= radio_button f, :autodetect_contructor_args, true, class: "form-check-input autodetecttrue", "aria-describedby": "optimization-help-block" %> + <%= radio_button f, :autodetect_contructor_args, true, class: "form-check-input autodetecttrue", "aria-describedby": "autodetect_contructor_args-help-block" %>
<%= label :autodetect_contructor_args, :true, gettext("Yes"), class: "radio-text" %>
- <%= error_tag f, :autodetect_contructor_args, id: "optimization-help-block", class: "text-danger form-error" %> + <%= error_tag f, :autodetect_contructor_args, id: "autodetect_contructor_args-help-block", class: "text-danger form-error" %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex index cde1169f3d..ecab786228 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex @@ -12,7 +12,7 @@ "> "> "> - "> + "> " color="#5bbad5"> "> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex index 68f6fe98b8..d2ed2c8339 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex @@ -144,6 +144,7 @@ data-clipboard-text="<%= @transaction.input %>" data-placement="top" data-toggle="tooltip" + title='<%= gettext("Copy Txn Input") %>' style="display: none;" > diff --git a/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex index a75bd2dcbf..08ccab4256 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/api_docs_view.ex @@ -34,10 +34,17 @@ defmodule BlockScoutWeb.APIDocsView do end) end - def blockscout_url do + def blockscout_url(is_api) do url_params = Application.get_env(:block_scout_web, BlockScoutWeb.Endpoint)[:url] host = url_params[:host] - path = url_params[:path] + + path = + if is_api do + url_params[:api_path] + else + url_params[:path] + end + scheme = Keyword.get(url_params, :scheme, "http") if host != "localhost" do @@ -49,12 +56,18 @@ defmodule BlockScoutWeb.APIDocsView do end def api_url do - blockscout_url() + is_api = true + + is_api + |> blockscout_url() |> Path.join("api") end def eth_rpc_api_url do - blockscout_url() + is_api = true + + is_api + |> blockscout_url() |> Path.join("api/eth_rpc") end end diff --git a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex index c96c5efe91..fef4fbc9d2 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex @@ -10,7 +10,7 @@ defmodule BlockScoutWeb.SmartContractView do def named_argument?(%{"name" => _}), do: true def named_argument?(_), do: false - def values(addresses, type) when type == "address[]" do + def values(addresses, type) when is_list(addresses) and type == "address[]" do addresses |> Enum.map(&values(&1, "address")) |> Enum.join(", ") diff --git a/apps/block_scout_web/lib/block_scout_web/views/tokens/instance/overview_view.ex b/apps/block_scout_web/lib/block_scout_web/views/tokens/instance/overview_view.ex index f56d10761e..3ad44bfcd5 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/tokens/instance/overview_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/tokens/instance/overview_view.ex @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.Tokens.Instance.OverviewView do alias BlockScoutWeb.CurrencyHelpers alias Explorer.Chain.{Address, SmartContract, Token} - import BlockScoutWeb.APIDocsView, only: [blockscout_url: 0] + import BlockScoutWeb.APIDocsView, only: [blockscout_url: 1] @tabs ["token_transfers", "metadata"] @@ -55,7 +55,8 @@ defmodule BlockScoutWeb.Tokens.Instance.OverviewView do def qr_code(conn, token_id, hash) do token_instance_path = token_instance_path(conn, :show, to_string(hash), to_string(token_id)) - url = Path.join(blockscout_url(), token_instance_path) + is_api = false + url = Path.join(blockscout_url(is_api), token_instance_path) url |> QRCode.to_png() diff --git a/apps/block_scout_web/mix.exs b/apps/block_scout_web/mix.exs index 029819a202..6a53ffd4e7 100644 --- a/apps/block_scout_web/mix.exs +++ b/apps/block_scout_web/mix.exs @@ -60,13 +60,13 @@ defmodule BlockScoutWeb.Mixfile do defp deps do [ # GraphQL toolkit - {:absinthe, "~> 1.4"}, + {:absinthe, "~> 1.5.0-rc.2"}, # Integrates Absinthe subscriptions with Phoenix - {:absinthe_phoenix, git: "https://github.com/ayrat555/absinthe_phoenix.git", branch: "ab-update-plug"}, + {:absinthe_phoenix, "~> 1.5.0-rc.0"}, # Plug support for Absinthe - {:absinthe_plug, git: "https://github.com/ayrat555/absinthe_plug.git", branch: "ab-enable-default-query"}, + {:absinthe_plug, "~> 1.5.0-rc.1"}, # Absinthe support for the Relay framework - {:absinthe_relay, "~> 1.4"}, + {:absinthe_relay, "~> 1.5.0-rc.0"}, {:bypass, "~> 1.0", only: :test}, # To add (CORS)(https://www.w3.org/TR/cors/) {:cors_plug, "~> 2.0"}, @@ -76,7 +76,7 @@ defmodule BlockScoutWeb.Mixfile do {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, # Need until https://github.com/absinthe-graphql/absinthe_relay/pull/125 is released, then can be removed # The current `absinthe_relay` is compatible though as shown from that PR - {:ecto, "~> 3.0", override: true}, + {:ecto, "~> 3.3", override: true}, {:ex_cldr, "~> 2.7"}, {:ex_cldr_numbers, "~> 2.6"}, {:ex_cldr_units, "~> 2.5"}, diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 27513a79b2..36b02fec4c 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -13,7 +13,7 @@ msgstr[0] "" msgstr[1] "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:193 +#: lib/block_scout_web/templates/transaction/overview.html.eex:194 msgid " Token Transfer" msgstr "" @@ -87,7 +87,7 @@ msgid "A string with the name of the module to be invoked." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:125 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:147 msgid "ABI-encoded Constructor Arguments (if required by the contract)" msgstr "" @@ -266,7 +266,7 @@ msgid "Call Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:274 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:296 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:54 msgid "Cancel" @@ -289,7 +289,7 @@ msgid "Clear" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:62 msgid "Compiler" msgstr "" @@ -370,7 +370,7 @@ msgid "Contract Creation Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161 msgid "Contract Libraries" msgstr "" @@ -579,7 +579,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:51 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:73 msgid "EVM Version" msgstr "" @@ -599,7 +599,7 @@ msgid "Emission Reward" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:115 msgid "Enter the Solidity Contract Code" msgstr "" @@ -646,8 +646,8 @@ msgstr "" #: lib/block_scout_web/templates/layout/app.html.eex:32 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 #: lib/block_scout_web/templates/transaction/_tile.html.eex:29 -#: lib/block_scout_web/templates/transaction/overview.html.eex:180 -#: lib/block_scout_web/templates/transaction/overview.html.eex:215 +#: lib/block_scout_web/templates/transaction/overview.html.eex:181 +#: lib/block_scout_web/templates/transaction/overview.html.eex:216 #: lib/block_scout_web/views/wei_helpers.ex:78 msgid "Ether" msgstr "" @@ -898,7 +898,7 @@ msgstr "" #: lib/block_scout_web/templates/transaction/_tabs.html.eex:4 #: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7 #: lib/block_scout_web/views/address_view.ex:308 -#: lib/block_scout_web/views/tokens/instance/overview_view.ex:71 +#: lib/block_scout_web/views/tokens/instance/overview_view.ex:72 #: lib/block_scout_web/views/tokens/overview_view.ex:35 #: lib/block_scout_web/views/transaction_view.ex:314 msgid "Token Transfers" @@ -971,20 +971,20 @@ msgid "Less than" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:154 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:176 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:198 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:220 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:242 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:264 msgid "Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:144 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:166 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:188 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:210 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:232 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:254 msgid "Library Name" msgstr "" @@ -999,7 +999,7 @@ msgid "License ID" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:243 +#: lib/block_scout_web/templates/transaction/overview.html.eex:244 msgid "Limit" msgstr "" @@ -1010,7 +1010,7 @@ msgid "Loading..." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:268 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:290 msgid "Loading...." msgstr "" @@ -1096,8 +1096,9 @@ msgid "New Smart Contract Verification" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:110 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:46 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:89 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:132 msgid "No" msgstr "" @@ -1114,7 +1115,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address_contract/index.html.eex:39 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:105 msgid "Optimization runs" msgstr "" @@ -1218,7 +1219,7 @@ msgid "Request URL" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:271 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:293 msgid "Reset" msgstr "" @@ -1538,7 +1539,7 @@ msgid "Use the search box to find a hosted network, or select from the list of a msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:237 +#: lib/block_scout_web/templates/transaction/overview.html.eex:238 msgid "Used" msgstr "" @@ -1568,8 +1569,8 @@ msgid "Validator Info" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:180 -#: lib/block_scout_web/templates/transaction/overview.html.eex:215 +#: lib/block_scout_web/templates/transaction/overview.html.eex:181 +#: lib/block_scout_web/templates/transaction/overview.html.eex:216 msgid "Value" msgstr "" @@ -1580,7 +1581,7 @@ msgid "Verify & Publish" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:270 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:292 msgid "Verify & publish" msgstr "" @@ -1654,8 +1655,9 @@ msgid "Wei" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:115 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:94 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:137 msgid "Yes" msgstr "" @@ -1745,7 +1747,7 @@ msgid "Decimals" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:233 +#: lib/block_scout_web/templates/transaction/overview.html.eex:234 msgid "Gas" msgstr "" @@ -1772,7 +1774,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/tokens/instance/metadata/index.html.eex:18 #: lib/block_scout_web/templates/tokens/instance/overview/_tabs.html.eex:10 -#: lib/block_scout_web/views/tokens/instance/overview_view.ex:72 +#: lib/block_scout_web/views/tokens/instance/overview_view.ex:73 msgid "Metadata" msgstr "" @@ -1793,6 +1795,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/transaction/overview.html.eex:134 +#: lib/block_scout_web/templates/transaction/overview.html.eex:147 msgid "Copy Txn Input" 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 27513a79b2..36b02fec4c 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 @@ -13,7 +13,7 @@ msgstr[0] "" msgstr[1] "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:193 +#: lib/block_scout_web/templates/transaction/overview.html.eex:194 msgid " Token Transfer" msgstr "" @@ -87,7 +87,7 @@ msgid "A string with the name of the module to be invoked." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:125 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:147 msgid "ABI-encoded Constructor Arguments (if required by the contract)" msgstr "" @@ -266,7 +266,7 @@ msgid "Call Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:274 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:296 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:54 msgid "Cancel" @@ -289,7 +289,7 @@ msgid "Clear" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:62 msgid "Compiler" msgstr "" @@ -370,7 +370,7 @@ msgid "Contract Creation Code" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:139 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:161 msgid "Contract Libraries" msgstr "" @@ -579,7 +579,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:51 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:73 msgid "EVM Version" msgstr "" @@ -599,7 +599,7 @@ msgid "Emission Reward" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:93 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:115 msgid "Enter the Solidity Contract Code" msgstr "" @@ -646,8 +646,8 @@ msgstr "" #: lib/block_scout_web/templates/layout/app.html.eex:32 #: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 #: lib/block_scout_web/templates/transaction/_tile.html.eex:29 -#: lib/block_scout_web/templates/transaction/overview.html.eex:180 -#: lib/block_scout_web/templates/transaction/overview.html.eex:215 +#: lib/block_scout_web/templates/transaction/overview.html.eex:181 +#: lib/block_scout_web/templates/transaction/overview.html.eex:216 #: lib/block_scout_web/views/wei_helpers.ex:78 msgid "Ether" msgstr "" @@ -898,7 +898,7 @@ msgstr "" #: lib/block_scout_web/templates/transaction/_tabs.html.eex:4 #: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7 #: lib/block_scout_web/views/address_view.ex:308 -#: lib/block_scout_web/views/tokens/instance/overview_view.ex:71 +#: lib/block_scout_web/views/tokens/instance/overview_view.ex:72 #: lib/block_scout_web/views/tokens/overview_view.ex:35 #: lib/block_scout_web/views/transaction_view.ex:314 msgid "Token Transfers" @@ -971,20 +971,20 @@ msgid "Less than" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:154 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:176 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:198 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:220 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:242 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:264 msgid "Library Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:144 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:166 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:188 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:210 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:232 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:254 msgid "Library Name" msgstr "" @@ -999,7 +999,7 @@ msgid "License ID" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:243 +#: lib/block_scout_web/templates/transaction/overview.html.eex:244 msgid "Limit" msgstr "" @@ -1010,7 +1010,7 @@ msgid "Loading..." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:268 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:290 msgid "Loading...." msgstr "" @@ -1096,8 +1096,9 @@ msgid "New Smart Contract Verification" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:67 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:110 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:46 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:89 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:132 msgid "No" msgstr "" @@ -1114,7 +1115,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address_contract/index.html.eex:39 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:83 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:105 msgid "Optimization runs" msgstr "" @@ -1218,7 +1219,7 @@ msgid "Request URL" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:271 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:293 msgid "Reset" msgstr "" @@ -1538,7 +1539,7 @@ msgid "Use the search box to find a hosted network, or select from the list of a msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:237 +#: lib/block_scout_web/templates/transaction/overview.html.eex:238 msgid "Used" msgstr "" @@ -1568,8 +1569,8 @@ msgid "Validator Info" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:180 -#: lib/block_scout_web/templates/transaction/overview.html.eex:215 +#: lib/block_scout_web/templates/transaction/overview.html.eex:181 +#: lib/block_scout_web/templates/transaction/overview.html.eex:216 msgid "Value" msgstr "" @@ -1580,7 +1581,7 @@ msgid "Verify & Publish" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:270 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:292 msgid "Verify & publish" msgstr "" @@ -1654,8 +1655,9 @@ msgid "Wei" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:72 -#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:115 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:51 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:94 +#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:137 msgid "Yes" msgstr "" @@ -1745,7 +1747,7 @@ msgid "Decimals" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/transaction/overview.html.eex:233 +#: lib/block_scout_web/templates/transaction/overview.html.eex:234 msgid "Gas" msgstr "" @@ -1772,7 +1774,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/tokens/instance/metadata/index.html.eex:18 #: lib/block_scout_web/templates/tokens/instance/overview/_tabs.html.eex:10 -#: lib/block_scout_web/views/tokens/instance/overview_view.ex:72 +#: lib/block_scout_web/views/tokens/instance/overview_view.ex:73 msgid "Metadata" msgstr "" @@ -1793,6 +1795,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/transaction/overview.html.eex:134 +#: lib/block_scout_web/templates/transaction/overview.html.eex:147 msgid "Copy Txn Input" msgstr "" diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs index 505520a2c0..b00d457426 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs @@ -647,7 +647,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do test "with external libraries", %{conn: conn} do contract_data = - "#{File.cwd!()}/test/support/fixture/smart_contract/compiler_tests.json" + "#{File.cwd!()}/test/support/fixture/smart_contract/contract_with_lib.json" |> File.read!() |> Jason.decode!() |> List.first() diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/verified_smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/verified_smart_contract_controller_test.exs index 7e5d41e930..19dd22151a 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/verified_smart_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/verified_smart_contract_controller_test.exs @@ -28,7 +28,7 @@ defmodule BlockScoutWeb.API.V1.VerifiedControllerTest do test "verifying a smart contract with external libraries", %{conn: conn} do contract_data = - "#{File.cwd!()}/test/support/fixture/smart_contract/compiler_tests.json" + "#{File.cwd!()}/test/support/fixture/smart_contract/contract_with_lib.json" |> File.read!() |> Jason.decode!() |> List.first() diff --git a/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs index 31922b4486..a353c9f870 100644 --- a/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/api_docs_view_test.exs @@ -14,7 +14,7 @@ defmodule BlockScoutWeb.ApiDocsViewTest do test "adds slash before path" do Application.put_env(:block_scout_web, BlockScoutWeb.Endpoint, - url: [scheme: "https", host: "blockscout.com", port: 9999, path: "/chain/dog"] + url: [scheme: "https", host: "blockscout.com", port: 9999, api_path: "/chain/dog"] ) assert APIDocsView.api_url() == "https://blockscout.com/chain/dog/api" @@ -22,7 +22,7 @@ defmodule BlockScoutWeb.ApiDocsViewTest do test "does not add slash to empty path" do Application.put_env(:block_scout_web, BlockScoutWeb.Endpoint, - url: [scheme: "https", host: "blockscout.com", port: 9999, path: ""] + url: [scheme: "https", host: "blockscout.com", port: 9999, api_path: ""] ) assert APIDocsView.api_url() == "https://blockscout.com/api" @@ -49,7 +49,7 @@ defmodule BlockScoutWeb.ApiDocsViewTest do test "adds slash before path" do Application.put_env(:block_scout_web, BlockScoutWeb.Endpoint, - url: [scheme: "https", host: "blockscout.com", port: 9999, path: "/chain/dog"] + url: [scheme: "https", host: "blockscout.com", port: 9999, api_path: "/chain/dog"] ) assert APIDocsView.eth_rpc_api_url() == "https://blockscout.com/chain/dog/api/eth_rpc" diff --git a/apps/block_scout_web/test/support/fixture/smart_contract/contract_with_lib.json b/apps/block_scout_web/test/support/fixture/smart_contract/contract_with_lib.json new file mode 100644 index 0000000000..aba02b0ec4 --- /dev/null +++ b/apps/block_scout_web/test/support/fixture/smart_contract/contract_with_lib.json @@ -0,0 +1,13 @@ +[ + { + "compiler_version": "v0.5.11+commit.c082d0b4", + "contract": "pragma solidity 0.5.11;library BadSafeMath { function add(uint256 a, uint256 b) public pure returns (uint256) { uint256 c = a + 2 * b; require(c >= a, \"SafeMath: addition overflow\"); return c; }}contract SimpleStorage { uint256 storedData = 10; using BadSafeMath for uint256; function increment(uint256 x) public { storedData = storedData.add(x); } function set(uint256 x) public { storedData = x; } function get() public view returns (uint256) { return storedData; }}", + "expected_bytecode": "608060405234801561001057600080fd5b50600436106100415760003560e01c806360fe47b1146100465780636d4ce63c146100655780637cf5dab01461007f575b600080fd5b6100636004803603602081101561005c57600080fd5b503561009c565b005b61006d6100a1565b60408051918252519081900360200190f35b6100636004803603602081101561009557600080fd5b50356100a7565b600055565b60005490565b600054733662e222908fa35f013bee37695d0510098b6d7363771602f79091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561010257600080fd5b505af4158015610116573d6000803e3d6000fd5b505050506040513d602081101561012c57600080fd5b50516000555056fea265627a7a723158203e59bfb9a5a2e55d38231922c86d8b2ec9b66cb2f6595613674bc4e15290b60764736f6c634300050b0032", + "external_libraries": { + "BadSafeMath": "0x3662e222908fa35f013bee37695d0510098b6d73" + }, + "name": "SimpleStorage", + "optimize": true + } + ] + \ No newline at end of file diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 21025cd480..d69ee6238f 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -12,7 +12,7 @@ config :explorer, token_functions_reader_max_retries: 3, allowed_evm_versions: System.get_env("ALLOWED_EVM_VERSIONS") || - "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,default", + "homestead,tangerineWhistle,spuriousDragon,byzantium,constantinople,petersburg,istanbul,default", include_uncles_in_average_block_time: if(System.get_env("UNCLES_IN_AVERAGE_BLOCK_TIME") == "true", do: true, else: false), healthy_blocks_period: System.get_env("HEALTHY_BLOCKS_PERIOD") || :timer.minutes(5), diff --git a/apps/explorer/lib/explorer/admin/role.ex b/apps/explorer/lib/explorer/admin/role.ex index 1fe753d400..ef31ed957c 100644 --- a/apps/explorer/lib/explorer/admin/role.ex +++ b/apps/explorer/lib/explorer/admin/role.ex @@ -3,7 +3,7 @@ defmodule Explorer.Admin.Administrator.Role do Supported roles for an administrator. """ - @behaviour Ecto.Type + use Ecto.Type @typedoc """ Supported role atoms for an administrator. diff --git a/apps/explorer/lib/explorer/chain/block/range.ex b/apps/explorer/lib/explorer/chain/block/range.ex index c60cd2039d..354ccd6d42 100644 --- a/apps/explorer/lib/explorer/chain/block/range.ex +++ b/apps/explorer/lib/explorer/chain/block/range.ex @@ -19,7 +19,7 @@ defmodule Explorer.Chain.Block.Range do to: integer() | :infinity } - @behaviour Ecto.Type + use Ecto.Type @doc """ The underlying Postgres type, `int8range`. diff --git a/apps/explorer/lib/explorer/chain/block/reward/address_type.ex b/apps/explorer/lib/explorer/chain/block/reward/address_type.ex index aac552a16e..9e0fe2ac52 100644 --- a/apps/explorer/lib/explorer/chain/block/reward/address_type.ex +++ b/apps/explorer/lib/explorer/chain/block/reward/address_type.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.Block.Reward.AddressType do Block reward address types """ - @behaviour Ecto.Type + use Ecto.Type @typedoc """ * `:emission_funds` diff --git a/apps/explorer/lib/explorer/chain/data.ex b/apps/explorer/lib/explorer/chain/data.ex index a3bec019af..ed07de1249 100644 --- a/apps/explorer/lib/explorer/chain/data.ex +++ b/apps/explorer/lib/explorer/chain/data.ex @@ -9,7 +9,7 @@ defmodule Explorer.Chain.Data do alias Explorer.Chain.Data alias Poison.Encoder.BitString - @behaviour Ecto.Type + use Ecto.Type @typedoc """ A variable-byte-length binary, wrapped in a struct, so that it can use protocols. diff --git a/apps/explorer/lib/explorer/chain/hash/address.ex b/apps/explorer/lib/explorer/chain/hash/address.ex index 4cb1ba751f..80a51e0af8 100644 --- a/apps/explorer/lib/explorer/chain/hash/address.ex +++ b/apps/explorer/lib/explorer/chain/hash/address.ex @@ -8,7 +8,7 @@ defmodule Explorer.Chain.Hash.Address do alias Explorer.Chain.Hash - @behaviour Ecto.Type + use Ecto.Type @behaviour Hash @byte_count 20 diff --git a/apps/explorer/lib/explorer/chain/hash/full.ex b/apps/explorer/lib/explorer/chain/hash/full.ex index f5c0855536..eb8ae148dd 100644 --- a/apps/explorer/lib/explorer/chain/hash/full.ex +++ b/apps/explorer/lib/explorer/chain/hash/full.ex @@ -5,7 +5,7 @@ defmodule Explorer.Chain.Hash.Full do alias Explorer.Chain.Hash - @behaviour Ecto.Type + use Ecto.Type @behaviour Hash @byte_count 32 diff --git a/apps/explorer/lib/explorer/chain/hash/nonce.ex b/apps/explorer/lib/explorer/chain/hash/nonce.ex index e5dbf3fe73..f8be6c2762 100644 --- a/apps/explorer/lib/explorer/chain/hash/nonce.ex +++ b/apps/explorer/lib/explorer/chain/hash/nonce.ex @@ -5,7 +5,7 @@ defmodule Explorer.Chain.Hash.Nonce do alias Explorer.Chain.Hash - @behaviour Ecto.Type + use Ecto.Type @behaviour Hash @byte_count 8 diff --git a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex index 3190c1abae..ddce8d0200 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex @@ -310,25 +310,29 @@ defmodule Explorer.Chain.Import.Runner.Blocks do end defp new_pending_operations(repo, nonconsensus_hashes, hashes, %{timeout: timeout, timestamps: timestamps}) do - sorted_pending_ops = - nonconsensus_hashes - |> MapSet.new() - |> MapSet.union(MapSet.new(hashes)) - |> Enum.sort() - |> Enum.map(fn hash -> - %{block_hash: hash, fetch_internal_transactions: true} - end) - - Import.insert_changes_list( - repo, - sorted_pending_ops, - conflict_target: :block_hash, - on_conflict: PendingBlockOperation.default_on_conflict(), - for: PendingBlockOperation, - returning: true, - timeout: timeout, - timestamps: timestamps - ) + if Application.get_env(:explorer, :json_rpc_named_arguments)[:variant] == EthereumJSONRPC.RSK do + {:ok, []} + else + sorted_pending_ops = + nonconsensus_hashes + |> MapSet.new() + |> MapSet.union(MapSet.new(hashes)) + |> Enum.sort() + |> Enum.map(fn hash -> + %{block_hash: hash, fetch_internal_transactions: true} + end) + + Import.insert_changes_list( + repo, + sorted_pending_ops, + conflict_target: :block_hash, + on_conflict: PendingBlockOperation.default_on_conflict(), + for: PendingBlockOperation, + returning: true, + timeout: timeout, + timestamps: timestamps + ) + end end defp delete_address_token_balances(_, [], _), do: {:ok, []} diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index fa4fa97a75..3568b0da6e 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -154,7 +154,7 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do total = repo.one!(total_query) - if total > Decimal.new(0) do + if total.value > Decimal.new(0) do update_query = from( p in StakingPool, @@ -162,8 +162,8 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do # ShareLocks order already enforced by `acquire_all_staking_pools` (see docs: sharelocks.md) update: [ set: [ - staked_ratio: p.staked_amount / ^total * 100, - likelihood: p.staked_amount / ^total * 100 + staked_ratio: p.staked_amount / ^total.value * 100, + likelihood: p.staked_amount / ^total.value * 100 ] ] ) diff --git a/apps/explorer/lib/explorer/chain/internal_transaction/call_type.ex b/apps/explorer/lib/explorer/chain/internal_transaction/call_type.ex index 8d354553ee..2f94ca901d 100644 --- a/apps/explorer/lib/explorer/chain/internal_transaction/call_type.ex +++ b/apps/explorer/lib/explorer/chain/internal_transaction/call_type.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.InternalTransaction.CallType do Internal transaction types """ - @behaviour Ecto.Type + use Ecto.Type @typedoc """ * `:call` - call a function in a contract by jumping into the contract's context diff --git a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex index 0a13587afe..6c2890c59b 100644 --- a/apps/explorer/lib/explorer/chain/internal_transaction/type.ex +++ b/apps/explorer/lib/explorer/chain/internal_transaction/type.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do Internal transaction types """ - @behaviour Ecto.Type + use Ecto.Type @typedoc """ * `:call` diff --git a/apps/explorer/lib/explorer/chain/method_identifier.ex b/apps/explorer/lib/explorer/chain/method_identifier.ex index 56cc2d5e93..e6097b59d9 100644 --- a/apps/explorer/lib/explorer/chain/method_identifier.ex +++ b/apps/explorer/lib/explorer/chain/method_identifier.ex @@ -5,7 +5,7 @@ defmodule Explorer.Chain.MethodIdentifier do Represented in the database as a 4 byte integer, decodes into a 4 byte bitstring """ - @behaviour Ecto.Type + use Ecto.Type @type t :: binary diff --git a/apps/explorer/lib/explorer/chain/transaction/status.ex b/apps/explorer/lib/explorer/chain/transaction/status.ex index 22d0eb976e..df4e56597f 100644 --- a/apps/explorer/lib/explorer/chain/transaction/status.ex +++ b/apps/explorer/lib/explorer/chain/transaction/status.ex @@ -8,7 +8,7 @@ defmodule Explorer.Chain.Transaction.Status do for failure. """ - @behaviour Ecto.Type + use Ecto.Type @typedoc """ * `:ok` - transaction succeeded diff --git a/apps/explorer/lib/explorer/chain/wei.ex b/apps/explorer/lib/explorer/chain/wei.ex index 78483632a7..6a2a6f7683 100644 --- a/apps/explorer/lib/explorer/chain/wei.ex +++ b/apps/explorer/lib/explorer/chain/wei.ex @@ -24,7 +24,7 @@ defmodule Explorer.Chain.Wei do defstruct ~w(value)a - @behaviour Ecto.Type + use Ecto.Type @impl Ecto.Type def type, do: :decimal diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index a81bc3d0ec..ce55258358 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -54,17 +54,25 @@ defmodule Explorer.SmartContract.Verifier do external_libs: external_libraries ) - compare_bytecodes(solc_output, address_hash, constructor_arguments, autodetect_contructor_arguments) + compare_bytecodes( + solc_output, + address_hash, + constructor_arguments, + autodetect_contructor_arguments, + contract_source_code + ) end - defp compare_bytecodes({:error, :name}, _, _, _), do: {:error, :name} - defp compare_bytecodes({:error, _}, _, _, _), do: {:error, :compilation} + defp compare_bytecodes({:error, :name}, _, _, _, _), do: {:error, :name} + defp compare_bytecodes({:error, _}, _, _, _, _), do: {:error, :compilation} + # credo:disable-for-next-line /Complexity/ defp compare_bytecodes( {:ok, %{"abi" => abi, "bytecode" => bytecode}}, address_hash, arguments_data, - autodetect_contructor_arguments + autodetect_contructor_arguments, + contract_source_code ) do generated_bytecode = extract_bytecode(bytecode) @@ -73,6 +81,7 @@ defmodule Explorer.SmartContract.Verifier do |> Chain.smart_contract_bytecode() blockchain_bytecode_without_whisper = extract_bytecode(blockchain_bytecode) + empty_constructor_arguments = arguments_data == "" or arguments_data == nil cond do generated_bytecode != blockchain_bytecode_without_whisper && @@ -80,7 +89,7 @@ defmodule Explorer.SmartContract.Verifier do {:error, :generated_bytecode} has_constructor_with_params?(abi) && autodetect_contructor_arguments -> - result = ConstructorArguments.find_constructor_arguments(address_hash, abi) + result = ConstructorArguments.find_constructor_arguments(address_hash, abi, contract_source_code) if result do {:ok, %{abi: abi, contructor_arguments: result}} @@ -88,8 +97,16 @@ defmodule Explorer.SmartContract.Verifier do {:error, :constructor_arguments} end + has_constructor_with_params?(abi) && empty_constructor_arguments -> + {:error, :constructor_arguments} + has_constructor_with_params?(abi) && - !ConstructorArguments.verify(address_hash, blockchain_bytecode_without_whisper, arguments_data) -> + !ConstructorArguments.verify( + address_hash, + blockchain_bytecode_without_whisper, + arguments_data, + contract_source_code + ) -> {:error, :constructor_arguments} true -> @@ -151,6 +168,22 @@ defmodule Explorer.SmartContract.Verifier do |> Enum.reverse() |> :binary.list_to_bin() + # Solidity >= 0.6.0 https://github.com/ethereum/solidity/blob/develop/Changelog.md#060-2019-12-17 + # https://github.com/ethereum/solidity/blob/26b700771e9cc9c956f0503a05de69a1be427963/docs/metadata.rst#encoding-of-the-metadata-hash-in-the-bytecode + # IPFS is used instead of Swarm + # The current version of the Solidity compiler usually adds the following to the end of the deployed bytecode: + # 0xa2 + # 0x64 'i' 'p' 'f' 's' 0x58 0x22 <34 bytes IPFS hash> + # 0x64 's' 'o' 'l' 'c' 0x43 <3 byte version encoding> + # 0x00 0x32 + # Note: there is a bug in the docs. Instead of 0x32, 0x33 should be used. + # Fixing PR has been created https://github.com/ethereum/solidity/pull/8174 + "a264697066735822" <> + <<_::binary-size(68)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0033" <> _constructor_arguments -> + extracted + |> Enum.reverse() + |> :binary.list_to_bin() + <> <> rest -> do_extract_bytecode([next | extracted], rest) end diff --git a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex index 576ff78168..f93eaf3c58 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex @@ -5,7 +5,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do alias ABI.{FunctionSelector, TypeDecoder} alias Explorer.Chain - def verify(address_hash, contract_code, arguments_data) do + def verify(address_hash, contract_code, arguments_data, contract_source_code) do arguments_data = arguments_data |> String.trim_trailing() |> String.trim_leading("0x") creation_code = @@ -18,7 +18,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do if verify_older_version(creation_code, contract_code, check_func) do true else - extract_constructor_arguments(creation_code, check_func) + extract_constructor_arguments(creation_code, check_func, contract_source_code) end end @@ -31,50 +31,76 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do |> check_func.() end - defp extract_constructor_arguments(code, check_func) do + defp extract_constructor_arguments(code, check_func, contract_source_code) do case code do # Solidity ~ 4.23 # https://solidity.readthedocs.io/en/v0.4.23/metadata.html "a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> constructor_arguments -> - check_func_result = check_func.(constructor_arguments) - - if check_func_result do - check_func_result - else - extract_constructor_arguments(constructor_arguments, check_func) - end + extract_constructor_arguments_check_func(constructor_arguments, check_func, contract_source_code) # Solidity >= 0.5.10 https://solidity.readthedocs.io/en/v0.5.10/metadata.html "a265627a7a72305820" <> <<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> constructor_arguments -> - check_func_result = check_func.(constructor_arguments) - - if check_func_result do - check_func_result - else - extract_constructor_arguments(constructor_arguments, check_func) - end + extract_constructor_arguments_check_func(constructor_arguments, check_func, contract_source_code) # Solidity >= 0.5.11 https://github.com/ethereum/solidity/blob/develop/Changelog.md#0511-2019-08-12 # Metadata: Update the swarm hash to the current specification, changes bzzr0 to bzzr1 and urls to use bzz-raw:// "a265627a7a72315820" <> <<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> constructor_arguments -> - check_func_result = check_func.(constructor_arguments) - - if check_func_result do - check_func_result - else - extract_constructor_arguments(constructor_arguments, check_func) - end + extract_constructor_arguments_check_func(constructor_arguments, check_func, contract_source_code) + + # Solidity >= 0.6.0 https://github.com/ethereum/solidity/blob/develop/Changelog.md#060-2019-12-17 + # https://github.com/ethereum/solidity/blob/26b700771e9cc9c956f0503a05de69a1be427963/docs/metadata.rst#encoding-of-the-metadata-hash-in-the-bytecode + # IPFS is used instead of Swarm + # The current version of the Solidity compiler usually adds the following to the end of the deployed bytecode: + # 0xa2 + # 0x64 'i' 'p' 'f' 's' 0x58 0x22 <34 bytes IPFS hash> + # 0x64 's' 'o' 'l' 'c' 0x43 <3 byte version encoding> + # 0x00 0x32 + # Note: there is a bug in the docs. Instead of 0x32, 0x33 should be used. + # Fixing PR has been created https://github.com/ethereum/solidity/pull/8174 + "a264697066735822" <> + <<_::binary-size(68)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0033" <> constructor_arguments -> + extract_constructor_arguments_check_func(constructor_arguments, check_func, contract_source_code) <<>> -> check_func.("") <<_::binary-size(2)>> <> rest -> - extract_constructor_arguments(rest, check_func) + extract_constructor_arguments(rest, check_func, contract_source_code) end end - def find_constructor_arguments(address_hash, abi) do + defp extract_constructor_arguments_check_func(constructor_arguments, check_func, contract_source_code) do + constructor_arguments = + remove_require_messages_from_constructor_arguments(contract_source_code, constructor_arguments) + + check_func_result = check_func.(constructor_arguments) + + if check_func_result do + check_func_result + else + extract_constructor_arguments(constructor_arguments, check_func, contract_source_code) + end + end + + def remove_require_messages_from_constructor_arguments(contract_source_code, constructor_arguments) do + msgs_list = + contract_source_code + |> extract_require_messages_from_constructor() + |> Enum.reverse() + + Enum.reduce(msgs_list, constructor_arguments, fn msg, pure_constructor_arguments -> + case String.split(pure_constructor_arguments, msg, parts: 2) do + [_, constructor_arguments_part] -> + constructor_arguments_part + + [_] -> + pure_constructor_arguments + end + end) + end + + def find_constructor_arguments(address_hash, abi, contract_source_code) do creation_code = address_hash |> Chain.contract_creation_input_data() @@ -97,6 +123,61 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do end end - extract_constructor_arguments(creation_code, check_func) + extract_constructor_arguments(creation_code, check_func, contract_source_code) + end + + def extract_require_messages_from_constructor(contract_source_code) do + constructor = find_constructor_content(contract_source_code) + require_contents = find_require_in_constructor(constructor) + + messages_list = + Enum.reduce(require_contents, [], fn require_content, msgs -> + msg = get_require_message_hex(require_content) + if msg, do: [msg | msgs] + end) + + if messages_list, do: messages_list, else: [] + end + + def find_constructor_content(contract_source_code) do + case String.split(contract_source_code, "constructor", parts: 2) do + [_, right_from_contstructor] -> + [_, right_from_contstructor_inside] = String.split(right_from_contstructor, "{", parts: 2) + [constructor, _] = String.split(right_from_contstructor_inside, "}", parts: 2) + constructor + + [_] -> + nil + end + end + + def find_require_in_constructor(constructor) do + if constructor do + [_ | requires] = String.split(constructor, "require") + + Enum.reduce(requires, [], fn right_from_require, requires_list -> + [_ | [right_from_require_inside]] = String.split(right_from_require, "(", parts: 2) + [require_content | _] = String.split(right_from_require_inside, ");", parts: 2) + [require_content | requires_list] + end) + else + [] + end + end + + def get_require_message_hex(require_content) do + case String.split(require_content, ",", parts: 2) do + [_ | [msg]] -> + msg + |> String.trim() + |> String.trim_leading("\"") + |> String.trim_trailing("\"") + |> String.trim_leading("'") + |> String.trim_trailing("'") + |> Base.encode16(case: :lower) + + [_] -> + nil + end end end diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs index 4d73894d5e..7eb0be4d13 100644 --- a/apps/explorer/mix.exs +++ b/apps/explorer/mix.exs @@ -74,9 +74,9 @@ defmodule Explorer.Mixfile do {:decimal, "~> 1.0"}, {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, # `override: true` for `ex_machina` compatibility - {:ecto, "~> 3.1", override: true}, + {:ecto, "~> 3.3", override: true}, # Storing blockchain data and derived data in PostgreSQL. - {:ecto_sql, "~> 3.1"}, + {:ecto_sql, "~> 3.3"}, # JSONRPC access to query smart contracts {:ethereum_jsonrpc, in_umbrella: true}, # Data factory for testing @@ -110,7 +110,7 @@ defmodule Explorer.Mixfile do # `:spandex` tracing of `:ecto` {:spandex_ecto, "~> 0.4.0"}, # Attach `:prometheus_ecto` to `:ecto` - {:telemetry, "~> 0.4.0"}, + {:telemetry, "~> 0.4.1"}, # `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0` {:timex, "~> 3.6"}, {:con_cache, "~> 0.13"} diff --git a/apps/explorer/package-lock.json b/apps/explorer/package-lock.json index 29cf4e81a8..2c3c20aed5 100644 --- a/apps/explorer/package-lock.json +++ b/apps/explorer/package-lock.json @@ -3,19 +3,6 @@ "requires": true, "lockfileVersion": 1, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -38,67 +25,26 @@ "concat-map": "0.0.1" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, "command-exists": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" }, + "commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, "fs-extra": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", @@ -116,15 +62,10 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, "glob": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", - "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -153,11 +94,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -190,15 +126,6 @@ "graceful-fs": "^4.1.9" } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -230,52 +157,16 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, - "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -294,42 +185,19 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, "solc": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.5.12.tgz", - "integrity": "sha512-OX/AGZT04tuUsagoVXSZBiBZYJReA02hdwZOfRkB03/eeYP9Dl3pr+M+au+1MhssgiuWBlFPN7sRXFiqwkAW2g==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.6.1.tgz", + "integrity": "sha512-iKqNYps2p++x8L9sBg7JeAJb7EmW8VJ/2asAzwlLYcUhj86AzuWLe94UTSQHv1SSCCj/x6lya8twvXkZtlTbIQ==", "requires": { "command-exists": "^1.2.8", + "commander": "3.0.2", "fs-extra": "^0.30.0", "js-sha3": "0.8.0", "memorystream": "^0.3.1", "require-from-string": "^2.0.0", "semver": "^5.5.0", - "tmp": "0.0.33", - "yargs": "^13.2.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" + "tmp": "0.0.33" } }, "tmp": { @@ -340,56 +208,10 @@ "os-tmpdir": "~1.0.2" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } } diff --git a/apps/explorer/package.json b/apps/explorer/package.json index 9010d39c7d..8fdead7f1d 100644 --- a/apps/explorer/package.json +++ b/apps/explorer/package.json @@ -8,12 +8,12 @@ "author": "POA Network", "license": "GPL-3.0", "engines": { - "node": "9.x", - "npm": "5.x" + "node": "12.x", + "npm": "6.x" }, "scripts": {}, "dependencies": { "keccak": "^2.0.0", - "solc": "^0.5.12" + "solc": "^0.6.1" } } diff --git a/apps/explorer/priv/repo/migrations/20191018140054_add_pending_internal_txs_operation.exs b/apps/explorer/priv/repo/migrations/20191018140054_add_pending_internal_txs_operation.exs index 41af522005..13d46ab013 100644 --- a/apps/explorer/priv/repo/migrations/20191018140054_add_pending_internal_txs_operation.exs +++ b/apps/explorer/priv/repo/migrations/20191018140054_add_pending_internal_txs_operation.exs @@ -55,76 +55,6 @@ defmodule Explorer.Repo.Migrations.AddPendingInternalTxsOperation do DELETE FROM internal_transactions WHERE block_hash IS NULL; """) - execute(""" - DO $$ - DECLARE - duplicates_count INTEGER := 0; - blocks_scanned INTEGER := 0; - int_txs_count INTEGER := 0; - temprow RECORD; - BEGIN - SELECT COUNT(*) INTO int_txs_count FROM internal_transactions; - IF int_txs_count < 10000000 THEN - - FOR temprow IN - SELECT block_hash FROM internal_transactions - GROUP BY block_hash, block_index HAVING COUNT(*) > 1 - LOOP - duplicates_count := duplicates_count + 1; - RAISE NOTICE '% duplicates, blocks scanned %, block #%, block hash is %', duplicates_count, blocks_scanned, temprow.number , temprow.hash; - - IF NOT EXISTS ( - SELECT 1 FROM pending_block_operations - WHERE block_hash = temprow.block_hash - ) THEN - INSERT INTO pending_block_operations - (block_hash, inserted_at, updated_at, fetch_internal_transactions) - SELECT b.hash, now(), now(), TRUE FROM blocks b - WHERE b.hash = temprow.block_hash; - END IF; - - DELETE FROM internal_transactions - WHERE block_hash = temprow.block_hash; - - RAISE NOTICE 'DELETED'; - END LOOP; - - ELSE - FOR temprow IN SELECT number, hash FROM blocks LOOP - blocks_scanned := blocks_scanned + 1; - IF EXISTS ( - SELECT 1 FROM transactions WHERE block_hash = temprow.hash - ) THEN - IF EXISTS ( - SELECT block_hash, block_index FROM internal_transactions - WHERE block_hash = temprow.hash - GROUP BY block_hash, block_index HAVING COUNT(*) > 1 - ) THEN - duplicates_count := duplicates_count + 1; - RAISE NOTICE '% duplicates, blocks scanned %, block #%, block hash is %', duplicates_count, blocks_scanned, temprow.number , temprow.hash; - - IF NOT EXISTS ( - SELECT 1 FROM pending_block_operations - WHERE block_hash = temprow.hash - ) THEN - INSERT INTO pending_block_operations - (block_hash, inserted_at, updated_at, fetch_internal_transactions) - SELECT b.hash, now(), now(), TRUE FROM blocks b - WHERE b.hash = temprow.hash; - END IF; - - DELETE FROM internal_transactions - WHERE block_hash = temprow.hash; - - RAISE NOTICE 'DELETED'; - END IF; - END IF; - END LOOP; - END IF; - RAISE NOTICE 'SCRIPT FINISHED'; - END $$; - """) - execute(""" ALTER table internal_transactions DROP CONSTRAINT internal_transactions_pkey, diff --git a/apps/explorer/priv/repo/migrations/20191128124415_remove_duplicate_indexes_token_entities.exs b/apps/explorer/priv/repo/migrations/20191128124415_remove_duplicate_indexes_token_entities.exs new file mode 100644 index 0000000000..9a9415ada4 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20191128124415_remove_duplicate_indexes_token_entities.exs @@ -0,0 +1,9 @@ +defmodule Explorer.Repo.Migrations.RemoveDuplicateIndexesTokenEntities do + use Ecto.Migration + + def change do + drop_if_exists(index(:address_token_balances, [:block_number], name: "address_token_balances_block_number_index")) + + drop_if_exists(index(:token_instances, [:token_id], name: "token_instances_token_id_index")) + end +end diff --git a/apps/explorer/priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql b/apps/explorer/priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql index 69a6fa24dd..2b46109775 100644 --- a/apps/explorer/priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql +++ b/apps/explorer/priv/repo/migrations/scripts/20181108205650_additional_internal_transaction_constraints.sql @@ -1,69 +1,77 @@ +-- UPDATE (2020-08-01): use pending_block_operations table DO $$ DECLARE row_count integer := 1; - batch_size integer := 50000; -- HOW MANY ITEMS WILL BE UPDATED AT TIME + batch_size integer := 500; -- HOW MANY ITEMS WILL BE UPDATED AT TIME iterator integer := batch_size; max_row_number integer; next_iterator integer; - updated_transaction_count integer; + updated_blocks_count integer; deleted_internal_transaction_count integer; deleted_row_count integer; BEGIN - DROP TABLE IF EXISTS transactions_with_deprecated_internal_transactions; + DROP TABLE IF EXISTS blocks_with_deprecated_internal_transactions; -- CREATES TEMP TABLE TO STORE DATA TO BE UPDATED - CREATE TEMP TABLE transactions_with_deprecated_internal_transactions( - hash bytea NOT NULL, + CREATE TEMP TABLE blocks_with_deprecated_internal_transactions( + block_number integer NOT NULL, row_number integer ); - INSERT INTO transactions_with_deprecated_internal_transactions - SELECT DISTINCT ON (transaction_hash) - transaction_hash, + INSERT INTO blocks_with_deprecated_internal_transactions + SELECT DISTINCT ON (a.block_number) + a.block_number, ROW_NUMBER () OVER () - FROM internal_transactions - WHERE - -- call_has_call_type CONSTRAINT - (type = 'call' AND call_type IS NULL) OR - -- call_has_input CONSTRAINT - (type = 'call' AND input IS NULL) OR - -- create_has_init CONSTRAINT - (type = 'create' AND init is NULL) - ORDER BY transaction_hash DESC; - - max_row_number := (SELECT MAX(row_number) FROM transactions_with_deprecated_internal_transactions); - RAISE NOTICE '% transactions to be updated', max_row_number + 1; + FROM ( + SELECT DISTINCT i.block_number, i.transaction_index + FROM internal_transactions i + WHERE + i.block_number IS NOT NULL + AND + -- call_has_call_type CONSTRAINT + ((i.type = 'call' AND i.call_type IS NULL) OR + -- call_has_input CONSTRAINT + (i.type = 'call' AND i.input IS NULL) OR + -- create_has_init CONSTRAINT + (i.type = 'create' AND i.init is NULL)) + ORDER BY i.block_number DESC, i.transaction_index + ) a; + + max_row_number := (SELECT MAX(row_number) FROM blocks_with_deprecated_internal_transactions); + RAISE NOTICE '% blocks to be updated', max_row_number + 1; -- ITERATES THROUGH THE ITEMS UNTIL THE TEMP TABLE IS EMPTY WHILE iterator <= max_row_number LOOP next_iterator := iterator + batch_size; - RAISE NOTICE '-> transactions with deprecated internal transactions % to % to be updated', iterator, next_iterator - 1; + RAISE NOTICE '-> blocks with deprecated internal transactions % to % to be updated', iterator, next_iterator - 1; - UPDATE transactions - SET internal_transactions_indexed_at = NULL, - error = NULL - FROM transactions_with_deprecated_internal_transactions - WHERE transactions.hash = transactions_with_deprecated_internal_transactions.hash AND - transactions_with_deprecated_internal_transactions.row_number < next_iterator; + INSERT INTO pending_block_operations (block_hash, inserted_at, updated_at, fetch_internal_transactions) + SELECT b.hash, NOW(), NOW(), true + FROM blocks_with_deprecated_internal_transactions bd, blocks b + WHERE bd.block_number = b.number + AND bd.row_number < next_iterator + AND b.consensus = true + ON CONFLICT (block_hash) + DO NOTHING; - GET DIAGNOSTICS updated_transaction_count = ROW_COUNT; + GET DIAGNOSTICS updated_blocks_count = ROW_COUNT; - RAISE NOTICE '-> % transactions updated to refetch internal transactions', updated_transaction_count; + RAISE NOTICE '-> % blocks updated to refetch internal transactions', updated_blocks_count; DELETE FROM internal_transactions - USING transactions_with_deprecated_internal_transactions - WHERE internal_transactions.transaction_hash = transactions_with_deprecated_internal_transactions.hash AND - transactions_with_deprecated_internal_transactions.row_number < next_iterator; + USING blocks_with_deprecated_internal_transactions + WHERE internal_transactions.block_number = blocks_with_deprecated_internal_transactions.block_number AND + blocks_with_deprecated_internal_transactions.row_number < next_iterator; GET DIAGNOSTICS deleted_internal_transaction_count = ROW_COUNT; RAISE NOTICE '-> % internal transactions deleted', deleted_internal_transaction_count; - DELETE FROM transactions_with_deprecated_internal_transactions + DELETE FROM blocks_with_deprecated_internal_transactions WHERE row_number < next_iterator; GET DIAGNOSTICS deleted_row_count = ROW_COUNT; - ASSERT updated_transaction_count = deleted_row_count; + ASSERT updated_blocks_count = deleted_row_count; -- COMMITS THE BATCH UPDATES CHECKPOINT; diff --git a/apps/explorer/priv/repo/migrations/scripts/20191018140054_send_block_hash_block_index_dups_to_carnitine.sql b/apps/explorer/priv/repo/migrations/scripts/20191018140054_send_block_hash_block_index_dups_to_carnitine.sql new file mode 100644 index 0000000000..a35667d26f --- /dev/null +++ b/apps/explorer/priv/repo/migrations/scripts/20191018140054_send_block_hash_block_index_dups_to_carnitine.sql @@ -0,0 +1,73 @@ +-- This script should be a part of migration to "pennding_block_operations" internal transactions indexing approach +-- if 20191018140054_add_pending_internal_txs_operation.exs migration failed due to occasional duplicates of +-- {block_hash, block_index} pair in the DB, that could exist due to bugs in previous versions of the application +--, before setting a primary key on those columns. If so, this script should be inserted at line 57 of that migration +-- just before changing of a primary key. + +DO $$ +DECLARE + duplicates_count INTEGER := 0; + blocks_scanned INTEGER := 0; + int_txs_count INTEGER := 0; + temprow RECORD; +BEGIN + SELECT COUNT(*) INTO int_txs_count FROM internal_transactions; + IF int_txs_count < 10000000 THEN + + FOR temprow IN + SELECT block_hash FROM internal_transactions + GROUP BY block_hash, block_index HAVING COUNT(*) > 1 + LOOP + duplicates_count := duplicates_count + 1; + RAISE NOTICE '% duplicates, blocks scanned %, block #%, block hash is %', duplicates_count, blocks_scanned, temprow.number , temprow.hash; + + IF NOT EXISTS ( + SELECT 1 FROM pending_block_operations + WHERE block_hash = temprow.block_hash + ) THEN + INSERT INTO pending_block_operations + (block_hash, inserted_at, updated_at, fetch_internal_transactions) + SELECT b.hash, now(), now(), TRUE FROM blocks b + WHERE b.hash = temprow.block_hash; + END IF; + + DELETE FROM internal_transactions + WHERE block_hash = temprow.block_hash; + + RAISE NOTICE 'DELETED'; + END LOOP; + + ELSE + FOR temprow IN SELECT number, hash FROM blocks LOOP + blocks_scanned := blocks_scanned + 1; + IF EXISTS ( + SELECT 1 FROM transactions WHERE block_hash = temprow.hash + ) THEN + IF EXISTS ( + SELECT block_hash, block_index FROM internal_transactions + WHERE block_hash = temprow.hash + GROUP BY block_hash, block_index HAVING COUNT(*) > 1 + ) THEN + duplicates_count := duplicates_count + 1; + RAISE NOTICE '% duplicates, blocks scanned %, block #%, block hash is %', duplicates_count, blocks_scanned, temprow.number , temprow.hash; + + IF NOT EXISTS ( + SELECT 1 FROM pending_block_operations + WHERE block_hash = temprow.hash + ) THEN + INSERT INTO pending_block_operations + (block_hash, inserted_at, updated_at, fetch_internal_transactions) + SELECT b.hash, now(), now(), TRUE FROM blocks b + WHERE b.hash = temprow.hash; + END IF; + + DELETE FROM internal_transactions + WHERE block_hash = temprow.hash; + + RAISE NOTICE 'DELETED'; + END IF; + END IF; + END LOOP; + END IF; + RAISE NOTICE 'SCRIPT FINISHED'; +END $$; \ No newline at end of file diff --git a/apps/explorer/test/explorer/smart_contract/publisher_test.exs b/apps/explorer/test/explorer/smart_contract/publisher_test.exs index 7a0d33fb45..79fbe55f63 100644 --- a/apps/explorer/test/explorer/smart_contract/publisher_test.exs +++ b/apps/explorer/test/explorer/smart_contract/publisher_test.exs @@ -131,7 +131,7 @@ defmodule Explorer.SmartContract.PublisherTest do test "validates and creates smart contract with external libraries" do contract_data = - "#{File.cwd!()}/test/support/fixture/smart_contract/compiler_tests.json" + "#{File.cwd!()}/test/support/fixture/smart_contract/contract_with_lib.json" |> File.read!() |> Jason.decode!() |> List.first() diff --git a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs index 968ae4131b..24a40e03ee 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs @@ -23,7 +23,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do |> insert(created_contract_address_hash: address.hash, input: input_data) |> with_block() - assert ConstructorArguments.verify(address.hash, "", constructor_arguments) + assert ConstructorArguments.verify(address.hash, "", constructor_arguments, "") end test "verifies with multiple nested constructor arguments" do @@ -43,7 +43,7 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do |> insert(created_contract_address_hash: address.hash, input: input_data) |> with_block() - assert ConstructorArguments.verify(address.hash, "", constructor_arguments) + assert ConstructorArguments.verify(address.hash, "", constructor_arguments, "") end test "verifies older version of Solidity where constructor_arguments were directly appended to source code" do @@ -64,7 +64,560 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do |> insert(created_contract_address_hash: address.hash, input: input_data) |> with_block() - assert ConstructorArguments.verify(address.hash, source_code, constructor_arguments) + assert ConstructorArguments.verify(address.hash, source_code, constructor_arguments, "") end + + test "verifies with require messages" do + address = insert(:address) + + source_code = """ + pragma solidity ^0.5.8; + + contract ValidatorProxy { + mapping(address => bool) public isValidator; + address public systemAddress = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; + address[] public validators; + + constructor(address[] memory _validators) public { + validators = _validators; + + for (uint i = 0; i < _validators.length; i++) { + isValidator[_validators[i]] = true; + } + } + + function updateValidators(address[] memory newValidators) public { + require( + tx.origin == systemAddress, // solium-disable-line security/no-tx-origin + "Only the system address can be responsible for the call of this function." + ); + + for (uint i = 0; i < validators.length; i++) { + isValidator[validators[i]] = false; + } + + for (uint i = 0; i < newValidators.length; i++) { + isValidator[newValidators[i]] = true; + } + + validators = newValidators; + } + + function numberOfValidators() public view returns (uint) { + return validators.length; + } + + function getValidators() public view returns (address[] memory) { + return validators; + } + } + + + contract HomeBridge { + struct TransferState { + mapping(address => bool) isConfirmedByValidator; + address[] confirmingValidators; + bool isCompleted; + } + + event Confirmation( + bytes32 transferHash, + bytes32 transactionHash, + uint256 amount, + address recipient, + address indexed validator + ); + event TransferCompleted( + bytes32 transferHash, + bytes32 transactionHash, + uint256 amount, + address recipient, + bool coinTransferSuccessful + ); + + mapping(bytes32 => TransferState) public transferState; + ValidatorProxy public validatorProxy; + uint public validatorsRequiredPercent; + + constructor(ValidatorProxy _proxy, uint _validatorsRequiredPercent) public { + require( + address(_proxy) != address(0), + "proxy must not be the zero address!" + ); + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + "_validatorsRequiredPercent must be between 0 and 100" + ); + validatorProxy = _proxy; + validatorsRequiredPercent = _validatorsRequiredPercent; + } + + function fund() external payable {} + + function confirmTransfer( + bytes32 transferHash, + bytes32 transactionHash, + uint256 amount, + address payable recipient + ) public { + // We compute a keccak hash for the transfer and use that as an identifier for the transfer + bytes32 transferStateId = keccak256( + abi.encodePacked(transferHash, transactionHash, amount, recipient) + ); + + require( + !transferState[transferStateId].isCompleted, + "transfer already completed" + ); + + require( + validatorProxy.isValidator(msg.sender), + "must be validator to confirm transfers" + ); + + require( + recipient != address(0), + "recipient must not be the zero address!" + ); + + require(amount > 0, "amount must not be zero"); + + if (_confirmTransfer(transferStateId, msg.sender)) { + // We have to emit the events here, because _confirmTransfer + // doesn't even receive the necessary information to do it on + // its own + + emit Confirmation( + transferHash, + transactionHash, + amount, + recipient, + msg.sender + ); + } + + if (_requiredConfirmationsReached(transferStateId)) { + transferState[transferStateId].isCompleted = true; + delete transferState[transferStateId].confirmingValidators; + bool coinTransferSuccessful = recipient.send(amount); + emit TransferCompleted( + transferHash, + transactionHash, + amount, + recipient, + coinTransferSuccessful + ); + } + } + + // check if a 2nd confirmTransfer would complete a transfer. this + // can happen after validator set changes. + function reconfirmCompletesTransfer( + bytes32 transferHash, + bytes32 transactionHash, + uint256 amount, + address payable recipient + ) public view returns (bool) { + require( + recipient != address(0), + "recipient must not be the zero address!" + ); + require(amount > 0, "amount must not be zero"); + + // We compute a keccak hash for the transfer and use that as an identifier for the transfer + bytes32 transferStateId = keccak256( + abi.encodePacked(transferHash, transactionHash, amount, recipient) + ); + + require( + !transferState[transferStateId].isCompleted, + "transfer already completed" + ); + + address[] storage confirmingValidators = transferState[transferStateId] + .confirmingValidators; + uint numConfirming = 0; + for (uint i = 0; i < confirmingValidators.length; i++) { + if (validatorProxy.isValidator(confirmingValidators[i])) { + numConfirming += 1; + } + } + return numConfirming >= _getNumRequiredConfirmations(); + } + + function _purgeConfirmationsFromExValidators(bytes32 transferStateId) + internal + { + address[] storage confirmingValidators = transferState[transferStateId] + .confirmingValidators; + + uint i = 0; + while (i < confirmingValidators.length) { + if (validatorProxy.isValidator(confirmingValidators[i])) { + i++; + } else { + confirmingValidators[i] = confirmingValidators[confirmingValidators + .length - + 1]; + confirmingValidators.length--; + } + } + } + + function _getNumRequiredConfirmations() internal view returns (uint) { + return + ( + validatorProxy.numberOfValidators() * + validatorsRequiredPercent + + 99 + ) / + 100; + } + + function _confirmTransfer(bytes32 transferStateId, address validator) + internal + returns (bool) + { + if (transferState[transferStateId].isConfirmedByValidator[validator]) { + return false; + } + + transferState[transferStateId].isConfirmedByValidator[validator] = true; + transferState[transferStateId].confirmingValidators.push(validator); + + return true; + } + + function _requiredConfirmationsReached(bytes32 transferStateId) + internal + returns (bool) + { + uint numRequired = _getNumRequiredConfirmations(); + + /* We now check if we have enough confirmations. If that is the + case, we purge ex-validators from the list of confirmations + and do the check again, so we do not count + confirmations from ex-validators. + + This means that old confirmations stay valid over validator set changes given + that the validator doesn't lose its validator status. + + The double check is here to save some gas. If checking the validator + status for all confirming validators becomes too costly, we can introduce + a 'serial number' for the validator set changes and determine if there + was a change of the validator set between the first confirmation + and the last confirmation and skip calling into + _purgeConfirmationsFromExValidators if there were no changes. + */ + + if ( + transferState[transferStateId].confirmingValidators.length < + numRequired + ) { + return false; + } + + _purgeConfirmationsFromExValidators(transferStateId); + + if ( + transferState[transferStateId].confirmingValidators.length < + numRequired + ) { + return false; + } + + return true; + } + } + """ + + constructor_arguments = + "5f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e642031303070726f7879206d757374206e6f7420626520746865207a65726f206164647265737321000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" + + input = + "608060405234801561001057600080fd5b50604051604080610ebb8339810180604052604081101561003057600080fd5b5080516020909101516001600160a01b038216610098576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610e986023913960400191505060405180910390fd5b60648111156100f2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526034815260200180610e646034913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b039390931692909217909155600255610d3f806101256000396000f3fe6080604052600436106100655760003560e01c8063397bc64111610043578063397bc64114610135578063b60d42881461015f578063f176cde71461016957610065565b806305dab2881461006a5780630b1ec76014610091578063236459c7146100cf575b600080fd5b34801561007657600080fd5b5061007f6101bb565b60408051918252519081900360200190f35b34801561009d57600080fd5b506100a66101c1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100db57600080fd5b50610121600480360360808110156100f257600080fd5b508035906020810135906040810135906060013573ffffffffffffffffffffffffffffffffffffffff166101dd565b604080519115158252519081900360200190f35b34801561014157600080fd5b506101216004803603602081101561015857600080fd5b5035610484565b61016761049c565b005b34801561017557600080fd5b506101676004803603608081101561018c57600080fd5b508035906020810135906040810135906060013573ffffffffffffffffffffffffffffffffffffffff1661049e565b60025481565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff821661024b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180610cc76027913960400191505060405180910390fd5b600083116102ba57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f616d6f756e74206d757374206e6f74206265207a65726f000000000000000000604482015290519081900360640190fd5b604080516020808201889052818301879052606080830187905273ffffffffffffffffffffffffffffffffffffffff8616901b608083015282516074818403018152609490920183528151918101919091206000818152918290529190206002015460ff161561038b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f7472616e7366657220616c726561647920636f6d706c65746564000000000000604482015290519081900360640190fd5b600081815260208190526040812060010190805b825481101561046e57600154835473ffffffffffffffffffffffffffffffffffffffff9091169063facd743b908590849081106103d857fe5b600091825260209182902001546040805163ffffffff851660e01b815273ffffffffffffffffffffffffffffffffffffffff90921660048301525160248083019392829003018186803b15801561042e57600080fd5b505afa158015610442573d6000803e3d6000fd5b505050506040513d602081101561045857600080fd5b505115610466576001820191505b60010161039f565b506104776108a7565b1115979650505050505050565b60006020819052908152604090206002015460ff1681565b565b604080516020808201879052818301869052606080830186905273ffffffffffffffffffffffffffffffffffffffff8516901b608083015282516074818403018152609490920183528151918101919091206000818152918290529190206002015460ff161561056f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f7472616e7366657220616c726561647920636f6d706c65746564000000000000604482015290519081900360640190fd5b600154604080517ffacd743b000000000000000000000000000000000000000000000000000000008152336004820152905173ffffffffffffffffffffffffffffffffffffffff9092169163facd743b91602480820192602092909190829003018186803b1580156105e057600080fd5b505afa1580156105f4573d6000803e3d6000fd5b505050506040513d602081101561060a57600080fd5b5051610661576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610cee6026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166106cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180610cc76027913960400191505060405180910390fd5b6000831161073c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f616d6f756e74206d757374206e6f74206265207a65726f000000000000000000604482015290519081900360640190fd5b6107468133610954565b156107ab57604080518681526020810186905280820185905273ffffffffffffffffffffffffffffffffffffffff84166060820152905133917fdee96a12459a8c17d4cf9571d9ab18de19fa1055adff514e2d25595382d218df919081900360800190a25b6107b481610a35565b156108a05760008181526020819052604081206002810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915561080392910190610c67565b60405160009073ffffffffffffffffffffffffffffffffffffffff84169085156108fc0290869084818181858888f1604080518c8152602081018c90528082018b905273ffffffffffffffffffffffffffffffffffffffff8a166060820152821515608082015290519196507f546c8621785b0cc9f951c75b68621fbdfce93ba6df3943b1271813c3598852d1955081900360a0019350915050a1505b5050505050565b60006064600254600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d6832ea96040518163ffffffff1660e01b815260040160206040518083038186803b15801561091657600080fd5b505afa15801561092a573d6000803e3d6000fd5b505050506040513d602081101561094057600080fd5b5051026063018161094d57fe5b0490505b90565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff161561099257506000610a2f565b5060008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff851680855281845291842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155848452908101805480830182559085529290932090910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690911790555b92915050565b600080610a406108a7565b600084815260208190526040902060010154909150811115610a66576000915050610a98565b610a6f83610a9d565b600083815260208190526040902060010154811115610a92576000915050610a98565b60019150505b919050565b6000818152602081905260408120600101905b8154811015610c6257600154825473ffffffffffffffffffffffffffffffffffffffff9091169063facd743b90849084908110610ae957fe5b600091825260209182902001546040805163ffffffff851660e01b815273ffffffffffffffffffffffffffffffffffffffff90921660048301525160248083019392829003018186803b158015610b3f57600080fd5b505afa158015610b53573d6000803e3d6000fd5b505050506040513d6020811015610b6957600080fd5b505115610b7857600101610c5d565b815482907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908110610ba857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281548110610bdf57fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790558154610c5b837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301610c88565b505b610ab0565b505050565b5080546000825590600052602060002090810190610c859190610ca8565b50565b815481835581811115610c6257600083815260209020610c629181019083015b61095191905b80821115610cc25760008155600101610cae565b509056fe726563697069656e74206d757374206e6f7420626520746865207a65726f2061646472657373216d7573742062652076616c696461746f7220746f20636f6e6669726d207472616e7366657273a165627a7a7230582050f9daa0f47602e3462444b6fc1dc592b21ec7e054969a8a5a1846570c2570cc00295f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e642031303070726f7879206d757374206e6f7420626520746865207a65726f206164647265737321000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" + + input_data = %Data{ + bytes: Base.decode16!(input, case: :lower) + } + + :transaction + |> insert(created_contract_address_hash: address.hash, input: input_data) + |> with_block() + + assert ConstructorArguments.verify(address.hash, input, constructor_arguments, source_code) + end + + test "get require messages from constructor" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(address _proxy, uint256 _validatorsRequiredPercent) public { + require ( + address(_proxy) != address(0), + + + + "proxy must not be the zero address!" + ); + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + "_validatorsRequiredPercent must be between 0 and 100" + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [ + "70726f7879206d757374206e6f7420626520746865207a65726f206164647265737321", + "5f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e6420313030" + ] + end + + test "get require messages with a single quote from constructor" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(address _proxy, uint256 _validatorsRequiredPercent) public { + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + '_validatorsRequiredPercent must be between 0 and 100' + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [ + "5f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e6420313030" + ] + end + + test "get require messages with different quotes inside from constructor" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(uint256 _validatorsRequiredPercent) public { + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + "_val\"idatorsReq'uiredPercent must be ' between \" 0 and 100" + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [ + "5f76616c22696461746f727352657127756972656450657263656e74206d7573742062652027206265747765656e2022203020616e6420313030" + ] + end + + test "get empty require messages from constructor with require without message" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(uint256 _validatorsRequiredPercent) public { + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100 + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [] + end + + test "get empty require messages from constructor" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(address _proxy, uint256 _validatorsRequiredPercent) public { + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [] + end + end + + test "get empty require messages if no constructor" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + } + """ + + result = ConstructorArguments.extract_require_messages_from_constructor(contract_source_code) + + assert result == [] + end + + test "returns purified constructor arguments" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(address _proxy, uint256 _validatorsRequiredPercent) public { + require ( + address(_proxy) != address(0), + + + + "proxy must not be the zero address!" + ); + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + "_validatorsRequiredPercent must be between 0 and 100" + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + dirty_constructor_arguments = + "5f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e642031303070726f7879206d757374206e6f7420626520746865207a65726f206164647265737321000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" + + result = + ConstructorArguments.remove_require_messages_from_constructor_arguments( + contract_source_code, + dirty_constructor_arguments + ) + + assert result == + "000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" + end + + test "didn't replace text param if it is the same as message in require" do + contract_source_code = """ + pragma solidity 0.5.11; + + + contract HomeBridge { + string public param; + uint public param2; + + constructor(string memory test, uint test2) public { + require( + test2 != 0, + + "proxy must not be the zero address!" + ); + + param = test; + param2 = test2; + } + } + """ + + dirty_constructor_arguments = + "70726f7879206d757374206e6f7420626520746865207a65726f2061646472657373210000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002370726f7879206d757374206e6f7420626520746865207a65726f2061646472657373210000000000000000000000000000000000000000000000000000000000" + + result = + ConstructorArguments.remove_require_messages_from_constructor_arguments( + contract_source_code, + dirty_constructor_arguments + ) + + # Arg [0] (string) : 70726f7879206d757374206e6f7420626520746865207a65726f206164647265737321 + # Arg [1] (uint256) : 45 + assert result == + "0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002370726f7879206d757374206e6f7420626520746865207a65726f2061646472657373210000000000000000000000000000000000000000000000000000000000" + end + + test "returns the same constructor arguments if no matches in require hexed messages" do + contract_source_code = """ + pragma solidity 0.6.1; + + + contract HomeBridge { + uint public validatorsRequiredPercent; + + constructor(address _proxy, uint256 _validatorsRequiredPercent) public { + require ( + address(_proxy) != address(0), + + + + "proxy must not be the zero address!" + ); + + + require( + _validatorsRequiredPercent >= 0 && + _validatorsRequiredPercent <= 100, + "_validatorsRequiredPercent must be between 0 and 100" + ); + validatorsRequiredPercent = _validatorsRequiredPercent; + } + } + """ + + dirty_constructor_arguments = + "4f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e642031303070726f7879206d757374206e6f7420626520746864207a65726f206164647265737321000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" + + result = + ConstructorArguments.remove_require_messages_from_constructor_arguments( + contract_source_code, + dirty_constructor_arguments + ) + + assert result == + "4f76616c696461746f7273526571756972656450657263656e74206d757374206265206265747765656e203020616e642031303070726f7879206d757374206e6f7420626520746864207a65726f206164647265737321000000000000000000000000fb5a36f0e12cef9f88d95f0e02cad4ba183336dc0000000000000000000000000000000000000000000000000000000000000032" end end diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index 088820beea..1fdbc2331b 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -30,7 +30,7 @@ defmodule Explorer.SmartContract.VerifierTest do test "verifies the generated bytecode with external libraries" do contract_data = - "#{File.cwd!()}/test/support/fixture/smart_contract/compiler_tests.json" + "#{File.cwd!()}/test/support/fixture/smart_contract/contract_with_lib.json" |> File.read!() |> Jason.decode!() |> List.first() @@ -113,8 +113,17 @@ defmodule Explorer.SmartContract.VerifierTest do bytecode = "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063256fec88146100545780633fa4f245146100a9578063812600df146100d2575b600080fd5b341561005f57600080fd5b6100676100f5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100b457600080fd5b6100bc61011b565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b6100f36004808035906020019091905050610121565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b806000540160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505600a165627a7a72305820b81379d1ae9d8e0fde05ee02b8bd170f43f8bd3d54da8b7ec203434a23a298980029" + constructor_arguments = "000000000000000000000000000000000000000000000000000000000000000a" + contract_address = insert(:contract_address, contract_code: bytecode) + :transaction + |> insert( + created_contract_address_hash: contract_address.hash, + input: bytecode <> constructor_arguments + ) + |> with_block() + code = """ pragma solidity ^0.4.15; contract Incrementer { @@ -137,7 +146,8 @@ defmodule Explorer.SmartContract.VerifierTest do "compiler_version" => "v0.4.15+commit.bbb8e64f", "evm_version" => "homestead", "name" => "Incrementer", - "optimization" => false + "optimization" => false, + "constructor_arguments" => constructor_arguments } assert {:ok, %{abi: abi}} = Verifier.evaluate_authenticity(contract_address.hash, params) @@ -212,6 +222,7 @@ defmodule Explorer.SmartContract.VerifierTest do params = %{ "contract_source_code" => different_code, "compiler_version" => contract_code_info.version, + "evm_version" => "istanbul", "name" => contract_code_info.name, "optimization" => contract_code_info.optimized } @@ -221,6 +232,36 @@ defmodule Explorer.SmartContract.VerifierTest do assert {:error, :generated_bytecode} = response end + test "returns error when contract has constructor arguments ut they were not provided" do + path = File.cwd!() <> "/test/support/fixture/smart_contract/solidity_0.5.9_smart_contract.sol" + contract = File.read!(path) + + constructor_arguments = "" + + bytecode = + "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633177029f116100715780633177029f1461025f57806354fd4d50146102c557806370a082311461034857806395d89b41146103a0578063a9059cbb14610423578063dd62ed3e14610489576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b6610501565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061059f565b604051808215151515815260200191505060405180910390f35b61019f610691565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610696565b604051808215151515815260200191505060405180910390f35b61024361090f565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610922565b604051808215151515815260200191505060405180910390f35b6102cd610a14565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561030d5780820151818401526020810190506102f2565b50505050905090810190601f16801561033a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61038a6004803603602081101561035e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ab2565b6040518082815260200191505060405180910390f35b6103a8610afa565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e85780820151818401526020810190506103cd565b50505050905090810190601f1680156104155780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61046f6004803603604081101561043957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b98565b604051808215151515815260200191505060405180910390f35b6104eb6004803603604081101561049f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cfe565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105975780601f1061056c57610100808354040283529160200191610597565b820191906000526020600020905b81548152906001019060200180831161057a57829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b600090565b6000816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410158015610762575081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410155b801561076e5750600082115b1561090357816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050610908565b600090505b9392505050565b600460009054906101000a900460ff1681565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60068054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610aaa5780601f10610a7f57610100808354040283529160200191610aaa565b820191906000526020600020905b815481529060010190602001808311610a8d57829003601f168201915b505050505081565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b905780601f10610b6557610100808354040283529160200191610b90565b820191906000526020600020905b815481529060010190602001808311610b7357829003601f168201915b505050505081565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410158015610be85750600082115b15610cf357816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050610cf8565b600090505b92915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509291505056fea265627a7a72305820fe0ba5210ac95870683c2cb054304b04565703bd16c7d7e956df694c9643c6d264736f6c63430005090032" + + contract_address = insert(:contract_address, contract_code: bytecode) + + :transaction + |> insert( + created_contract_address_hash: contract_address.hash, + input: bytecode <> constructor_arguments + ) + |> with_block() + + params = %{ + "contract_source_code" => contract, + "compiler_version" => "v0.5.9+commit.e560f70d", + "evm_version" => "petersburg", + "name" => "TestToken", + "optimization" => false, + "constructor_arguments" => constructor_arguments + } + + assert {:error, :generated_bytecode} = Verifier.evaluate_authenticity(contract_address.hash, params) + end + test "returns error when there is a compilation problem", %{contract_code_info: contract_code_info} do contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) diff --git a/apps/explorer/test/support/fixture/smart_contract/contract_with_lib.json b/apps/explorer/test/support/fixture/smart_contract/contract_with_lib.json new file mode 100644 index 0000000000..aba02b0ec4 --- /dev/null +++ b/apps/explorer/test/support/fixture/smart_contract/contract_with_lib.json @@ -0,0 +1,13 @@ +[ + { + "compiler_version": "v0.5.11+commit.c082d0b4", + "contract": "pragma solidity 0.5.11;library BadSafeMath { function add(uint256 a, uint256 b) public pure returns (uint256) { uint256 c = a + 2 * b; require(c >= a, \"SafeMath: addition overflow\"); return c; }}contract SimpleStorage { uint256 storedData = 10; using BadSafeMath for uint256; function increment(uint256 x) public { storedData = storedData.add(x); } function set(uint256 x) public { storedData = x; } function get() public view returns (uint256) { return storedData; }}", + "expected_bytecode": "608060405234801561001057600080fd5b50600436106100415760003560e01c806360fe47b1146100465780636d4ce63c146100655780637cf5dab01461007f575b600080fd5b6100636004803603602081101561005c57600080fd5b503561009c565b005b61006d6100a1565b60408051918252519081900360200190f35b6100636004803603602081101561009557600080fd5b50356100a7565b600055565b60005490565b600054733662e222908fa35f013bee37695d0510098b6d7363771602f79091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561010257600080fd5b505af4158015610116573d6000803e3d6000fd5b505050506040513d602081101561012c57600080fd5b50516000555056fea265627a7a723158203e59bfb9a5a2e55d38231922c86d8b2ec9b66cb2f6595613674bc4e15290b60764736f6c634300050b0032", + "external_libraries": { + "BadSafeMath": "0x3662e222908fa35f013bee37695d0510098b6d73" + }, + "name": "SimpleStorage", + "optimize": true + } + ] + \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index f73c4b34f0..65a46ccced 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM bitwalker/alpine-elixir-phoenix:1.9.0 +FROM bitwalker/alpine-elixir-phoenix:1.9.1 RUN apk --no-cache --update add alpine-sdk gmp-dev automake libtool inotify-tools autoconf python @@ -15,7 +15,7 @@ ADD apps/explorer/mix.exs ./apps/explorer/ ADD apps/ethereum_jsonrpc/mix.exs ./apps/ethereum_jsonrpc/ ADD apps/indexer/mix.exs ./apps/indexer/ -RUN mix do deps.get, deps.compile +RUN mix do deps.get, local.rebar --force, deps.compile ADD . . @@ -37,6 +37,8 @@ RUN cd apps/explorer/ && \ # RUN mix do ecto.drop --force, ecto.create, ecto.migrate +RUN mix phx.digest + # USER default # CMD ["mix", "phx.server"] diff --git a/docker/Makefile b/docker/Makefile index 6005fbdaeb..7f23069c15 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -3,7 +3,7 @@ HOST = host.docker.internal DOCKER_IMAGE = blockscout_prod BS_CONTAINER_NAME = blockscout PG_CONTAINER_NAME = postgres -PG_CONTAINER_IMAGE = postgres:10.6 +PG_CONTAINER_IMAGE = postgres:10.10 THIS_FILE = $(lastword $(MAKEFILE_LIST)) ifeq ($(SYSTEM), Linux) @@ -16,35 +16,185 @@ BLOCKSCOUT_CONTAINNER_PARAMS = -e 'MIX_ENV=prod' \ ifeq ($(SYSTEM), Linux) BLOCKSCOUT_CONTAINNER_PARAMS += --network=host endif +ifdef NETWORK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK=$(NETWORK)' +endif +ifdef SUBNETWORK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUBNETWORK=$(SUBNETWORK)' +endif +ifdef NETWORK_ICON + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_ICON=$(NETWORK_ICON)' +endif +ifdef LOGO + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LOGO=$(LOGO)' +endif +ifdef LOGO_FOOTER + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LOGO_FOOTER=$(LOGO_FOOTER)' +endif ifdef ETHEREUM_JSONRPC_VARIANT BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_VARIANT=$(ETHEREUM_JSONRPC_VARIANT)' endif ifdef ETHEREUM_JSONRPC_HTTP_URL BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_HTTP_URL=$(ETHEREUM_JSONRPC_HTTP_URL)' endif +ifdef ETHEREUM_JSONRPC_TRACE_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_TRACE_URL=$(ETHEREUM_JSONRPC_TRACE_URL)' +endif ifdef ETHEREUM_JSONRPC_WS_URL BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_WS_URL=$(ETHEREUM_JSONRPC_WS_URL)' endif -ifdef ETHEREUM_JSONRPC_TRACE_URL - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_TRACE_URL=$(ETHEREUM_JSONRPC_TRACE_URL)' +ifdef ETHEREUM_JSONRPC_JSON_RPC_TRANSPORT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_JSON_RPC_TRANSPORT=$(ETHEREUM_JSONRPC_JSON_RPC_TRANSPORT)' +endif +ifdef IPC_PATH + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'IPC_PATH=$(IPC_PATH)' +endif +ifdef NETWORK_PATH + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_PATH=$(NETWORK_PATH)' +endif +ifdef CHECK_ORIGIN + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'CHECK_ORIGIN=$(CHECK_ORIGIN)' endif ifdef COIN BLOCKSCOUT_CONTAINNER_PARAMS += -e 'COIN=$(COIN)' endif -ifdef LOGO - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LOGO=$(LOGO)' +ifdef METADATA_CONTRACT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'METADATA_CONTRACT=$(METADATA_CONTRACT)' endif -ifdef NETWORK - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK=$(NETWORK)' +ifdef VALIDATORS_CONTRACT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'VALIDATORS_CONTRACT=$(VALIDATORS_CONTRACT)' endif -ifdef SUBNETWORK - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUBNETWORK=$(SUBNETWORK)' +ifdef SUPPLY_MODULE + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUPPLY_MODULE=$(SUPPLY_MODULE)' endif -ifdef NETWORK_ICON - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_ICON=$(NETWORK_ICON)' +ifdef SOURCE_MODULE + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SOURCE_MODULE=$(SOURCE_MODULE)' endif -ifdef NETWORK_PATH - BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_PATH=$(NETWORK_PATH)' +ifdef POOL_SIZE + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'POOL_SIZE=$(POOL_SIZE)' +endif +ifdef ECTO_USE_SSL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ECTO_USE_SSL=$(ECTO_USE_SSL)' +endif +ifdef DATADOG_HOST + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DATADOG_HOST=$(DATADOG_HOST)' +endif +ifdef DATADOG_PORT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DATADOG_PORT=$(DATADOG_PORT)' +endif +ifdef SPANDEX_BATCH_SIZE + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SPANDEX_BATCH_SIZE=$(SPANDEX_BATCH_SIZE)' +endif +ifdef SPANDEX_SYNC_THRESHOLD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SPANDEX_SYNC_THRESHOLD=$(SPANDEX_SYNC_THRESHOLD)' +endif +ifdef HEART_BEAT_TIMEOUT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'HEART_BEAT_TIMEOUT=$(HEART_BEAT_TIMEOUT)' +endif +ifdef HEART_COMMAND + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'HEART_COMMAND=$(HEART_COMMAND)' +endif +ifdef BLOCKSCOUT_VERSION + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'BLOCKSCOUT_VERSION=$(BLOCKSCOUT_VERSION)' +endif +ifdef RELEASE_LINK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'RELEASE_LINK=$(RELEASE_LINK)' +endif +ifdef ELIXIR_VERSION + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ELIXIR_VERSION=$(ELIXIR_VERSION)' +endif +ifdef BLOCK_TRANSFORMER + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'BLOCK_TRANSFORMER=$(BLOCK_TRANSFORMER)' +endif +ifdef GRAPHIQL_TRANSACTION + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'GRAPHIQL_TRANSACTION=$(GRAPHIQL_TRANSACTION)' +endif +ifdef FIRST_BLOCK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'FIRST_BLOCK=$(FIRST_BLOCK)' +endif +ifdef LAST_BLOCK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LAST_BLOCK=$(LAST_BLOCK)' +endif +ifdef TXS_COUNT_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'TXS_COUNT_CACHE_PERIOD=$(TXS_COUNT_CACHE_PERIOD)' +endif +ifdef ADDRESS_WITH_BALANCES_UPDATE_INTERVAL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=$(ADDRESS_WITH_BALANCES_UPDATE_INTERVAL)' +endif +ifdef LINK_TO_OTHER_EXPLORERS + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LINK_TO_OTHER_EXPLORERS=$(LINK_TO_OTHER_EXPLORERS)' +endif +ifdef COINMARKETCAP_PAGES + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'COINMARKETCAP_PAGES=$(COINMARKETCAP_PAGES)' +endif +ifdef SUPPORTED_CHAINS + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUPPORTED_CHAINS=$(SUPPORTED_CHAINS)' +endif +ifdef BLOCK_COUNT_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'BLOCK_COUNT_CACHE_PERIOD=$(BLOCK_COUNT_CACHE_PERIOD)' +endif +ifdef ADDRESS_SUM_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ADDRESS_SUM_CACHE_PERIOD=$(ADDRESS_SUM_CACHE_PERIOD)' +endif +ifdef ADDRESS_COUNT_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ADDRESS_COUNT_CACHE_PERIOD=$(ADDRESS_COUNT_CACHE_PERIOD)' +endif +ifdef ALLOWED_EVM_VERSIONS + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ALLOWED_EVM_VERSIONS=$(ALLOWED_EVM_VERSIONS)' +endif +ifdef UNCLES_IN_AVERAGE_BLOCK_TIME + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'UNCLES_IN_AVERAGE_BLOCK_TIME=$(UNCLES_IN_AVERAGE_BLOCK_TIME)' +endif +ifdef AVERAGE_BLOCK_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'AVERAGE_BLOCK_CACHE_PERIOD=$(AVERAGE_BLOCK_CACHE_PERIOD)' +endif +ifdef MARKET_HISTORY_CACHE_PERIOD + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'MARKET_HISTORY_CACHE_PERIOD=$(MARKET_HISTORY_CACHE_PERIOD)' +endif +ifdef DISABLE_WEBAPP + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DISABLE_WEBAPP=$(DISABLE_WEBAPP)' +endif +ifdef DISABLE_READ_API + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DISABLE_READ_API=$(DISABLE_READ_API)' +endif +ifdef DISABLE_WRITE_API + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DISABLE_WRITE_API=$(DISABLE_WRITE_API)' +endif +ifdef DISABLE_INDEXER + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DISABLE_INDEXER=$(DISABLE_INDEXER)' +endif +ifdef WEBAPP_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'WEBAPP_URL=$(WEBAPP_URL)' +endif +ifdef API_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'API_URL=$(API_URL)' +endif +ifdef CHAIN_SPEC_PATH + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'CHAIN_SPEC_PATH=$(CHAIN_SPEC_PATH)' +endif +ifdef COIN_GECKO_ID + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'COIN_GECKO_ID=$(COIN_GECKO_ID)' +endif +ifdef EMISSION_FORMAT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'EMISSION_FORMAT=$(EMISSION_FORMAT)' +endif +ifdef REWARDS_CONTRACT_ADDRESS + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'REWARDS_CONTRACT_ADDRESS=$(REWARDS_CONTRACT_ADDRESS)' +endif +ifdef SHOW_ADDRESS_MARKETCAP_PERCENTAGE + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SHOW_ADDRESS_MARKETCAP_PERCENTAGE=$(SHOW_ADDRESS_MARKETCAP_PERCENTAGE)' +endif +ifdef BLOCKSCOUT_PROTOCOL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'BLOCKSCOUT_PROTOCOL=$(BLOCKSCOUT_PROTOCOL)' +endif +ifdef BLOCKSCOUT_HOST + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'BLOCKSCOUT_HOST=$(BLOCKSCOUT_HOST)' +endif +ifdef DECOMPILED_SMART_CONTRACT_TOKEN + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'DECOMPILED_SMART_CONTRACT_TOKEN=$(DECOMPILED_SMART_CONTRACT_TOKEN)' +endif +ifdef SOCKET_ROOT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SOCKET_ROOT=$(SOCKET_ROOT)' endif HAS_BLOCKSCOUT_IMAGE := $(shell docker images | grep ${DOCKER_IMAGE}) @@ -61,7 +211,7 @@ migrate: build postgres @echo "==> Running migrations" @docker run --rm \ $(BLOCKSCOUT_CONTAINNER_PARAMS) \ - $(DOCKER_IMAGE) /bin/sh -c "echo $$MIX_ENV && mix do ecto.drop --force, ecto.create, ecto.migrate" + $(DOCKER_IMAGE) /bin/sh -c "echo $$MIX_ENV && mix do ecto.create, ecto.migrate" PG_EXIST := $(shell docker ps -a --filter name=${PG_CONTAINER_NAME} | grep ${PG_CONTAINER_NAME}) diff --git a/mix.lock b/mix.lock index 081e2eec49..40d7bc5bb3 100644 --- a/mix.lock +++ b/mix.lock @@ -1,8 +1,8 @@ %{ - "absinthe": {:hex, :absinthe, "1.4.16", "0933e4d9f12652b12115d5709c0293a1bf78a22578032e9ad0dad4efee6b9eb1", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "absinthe_phoenix": {:git, "https://github.com/ayrat555/absinthe_phoenix.git", "4dbb73a25a0935a4d292e63876698e18534d835f", [branch: "ab-update-plug"]}, - "absinthe_plug": {:git, "https://github.com/ayrat555/absinthe_plug.git", "cbe1c170e11e60b3b0146b925a1ce6ec562840ce", [branch: "ab-enable-default-query"]}, - "absinthe_relay": {:hex, :absinthe_relay, "1.4.6", "ec0e2288994b388556247cf9601245abec785cdf206d6e844f2992d29de21624", [:mix], [{:absinthe, "~> 1.4.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, + "absinthe": {:hex, :absinthe, "1.5.0-rc.2", "132ceb90783a39454cba1a043e833add5385036ed1e6fe8e889b85fc2b7cd89f", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, + "absinthe_phoenix": {:hex, :absinthe_phoenix, "1.5.0-rc.0", "63558295f77f09c9e412fa0a4ef92a66003eaf539821a810fd928c1c67a6005d", [:mix], [{:absinthe, "~> 1.5.0-rc.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.5.0-rc.0", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm"}, + "absinthe_plug": {:hex, :absinthe_plug, "1.5.0-rc.1", "f6d8a7a74c42cb1547f9d62cf728b8aab960c5246b8415deb0cb1f5aac1fb671", [:mix], [{:absinthe, "~> 1.5.0-rc.2", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.2 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"}, + "absinthe_relay": {:hex, :absinthe_relay, "1.5.0-rc.0", "99048f5a8239dbcecf6c600f6a2410e1b157832df01d3f4859bc804565ddf1bc", [:mix], [{:absinthe, "~> 1.5.0-rc.1", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, "accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "1.1.1", "6b5560e47a02196ce5f0ab3f1d8265db79a23868c137e973b27afef928ed8006", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, "benchee": {:hex, :benchee, "0.13.2", "30cd4ff5f593fdd218a9b26f3c24d580274f297d88ad43383afe525b1543b165", [:mix], [{:deep_merge, "~> 0.1", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm"}, @@ -22,15 +22,15 @@ "cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"}, "credo": {:hex, :credo, "1.1.2", "02b6422f3e659eb74b05aca3c20c1d8da0119a05ee82577a82e6c2938bf29f81", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "csv": {:hex, :csv, "2.3.1", "9ce11eff5a74a07baf3787b2b19dd798724d29a9c3a492a41df39f6af686da0e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm"}, - "dataloader": {:hex, :dataloader, "1.0.6", "fb724d6d3fb6acb87d27e3b32dea3a307936ad2d245faf9cf5221d1323d6a4ba", [:mix], [{:ecto, ">= 0.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, - "db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"}, - "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"}, + "dataloader": {:hex, :dataloader, "1.0.7", "58351b335673cf40601429bfed6c11fece6ce7ad169b2ac0f0fe83e716587391", [:mix], [{:ecto, ">= 0.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, + "db_connection": {:hex, :db_connection, "2.2.0", "e923e88887cd60f9891fd324ac5e0290954511d090553c415fbf54be4c57ee63", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"}, + "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm"}, "decorator": {:hex, :decorator, "1.3.0", "6203dbd6e4e519a21a079e2a74e50fddaf03e80be22711b92eb4cd410173abea", [:mix], [], "hexpm"}, "deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm"}, "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"}, "earmark": {:hex, :earmark, "1.3.5", "0db71c8290b5bc81cb0101a2a507a76dca659513984d683119ee722828b424f6", [:mix], [], "hexpm"}, - "ecto": {:hex, :ecto, "3.1.7", "fa21d06ef56cdc2fdaa62574e8c3ba34a2751d44ea34c30bc65f0728421043e5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, - "ecto_sql": {:hex, :ecto_sql, "3.1.6", "1e80e30d16138a729c717f73dcb938590bcdb3a4502f3012414d0cbb261045d8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, + "ecto": {:hex, :ecto, "3.3.1", "82ab74298065bf0c64ca299f6c6785e68ea5d6b980883ee80b044499df35aba1", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, + "ecto_sql": {:hex, :ecto_sql, "3.3.2", "92804e0de69bb63e621273c3492252cb08a29475c05d40eeb6f41ad2d483cfd3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"}, "ex_abi": {:hex, :ex_abi, "0.1.18", "19db9bffdd201edbdff97d7dd5849291218b17beda045c1b76bff5248964f37d", [:mix], [{:exth_crypto, "~> 0.1.4", [hex: :exth_crypto, repo: "hexpm", optional: false]}], "hexpm"}, "ex_cldr": {:hex, :ex_cldr, "2.7.2", "d79a1af6ed12630a15175d2b88d4381b22db5d6f835c5da8de132f0cf712b233", [:mix], [{:cldr_utils, "~> 2.1", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"}, @@ -92,7 +92,7 @@ "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"}, - "postgrex": {:hex, :postgrex, "0.15.0", "dd5349161019caeea93efa42f9b22f9d79995c3a86bdffb796427b4c9863b0f0", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, + "postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, "prometheus": {:hex, :prometheus, "4.4.1", "1e96073b3ed7788053768fea779cbc896ddc3bdd9ba60687f2ad50b252ac87d6", [:mix, :rebar3], [], "hexpm"}, "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"}, "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"}, @@ -108,7 +108,7 @@ "spandex_ecto": {:hex, :spandex_ecto, "0.4.0", "deaeaddc11a35f1c551206c53d09bb93a0da5808dbef751430e465c8c7de01d3", [:mix], [{:spandex, "~> 2.2", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm"}, "spandex_phoenix": {:hex, :spandex_phoenix, "0.3.2", "e81889d80852a895cf62ce2e25181b15766d21e8647962e0a4458414b935feb3", [:mix], [{:plug, "~> 1.3", [hex: :plug, repo: "hexpm", optional: false]}, {:spandex, "~> 2.2", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"}, - "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"}, + "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"}, "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"}, "tzdata": {:hex, :tzdata, "1.0.1", "f6027a331af7d837471248e62733c6ebee86a72e57c613aa071ebb1f750fc71a", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, diff --git a/rel/commands/clear_build.sh b/rel/commands/clear_build.sh index 5a032809ba..7c79a85ec3 100755 --- a/rel/commands/clear_build.sh +++ b/rel/commands/clear_build.sh @@ -4,8 +4,12 @@ rm -rf ./_build rm -rf ./deps logs=$(find . -not -path '*/\.*' -name "logs" -type d) dev=$(find ${logs} -name "dev") -files_and_dirs_in_logs=$(ls -d ${dev}/*) -rm -rf $files_and_dirs_in_logs +files_and_dirs_in_logs_dev=$(ls -d ${dev}/*) +rm -rf $files_and_dirs_in_logs_dev + +test=$(find ${logs} -name "test") +files_and_dirs_in_logs_test=$(ls -d ${test}/*) +rm -rf $files_and_dirs_in_logs_test find . -name "node_modules" -type d -exec rm -rf '{}' +