Verify via metadata json

pull/3858/head
Victor Baranov 4 years ago committed by Viktor Baranov
parent b40758e36f
commit 51e7fd0571
  1. 4
      .dialyzer-ignore
  2. 1
      apps/block_scout_web/assets/css/_mixins.scss
  3. 1
      apps/block_scout_web/assets/css/app.scss
  4. 541
      apps/block_scout_web/assets/css/components/_dropzone.scss
  5. 4
      apps/block_scout_web/assets/css/components/_new_smart_contract.scss
  6. 1
      apps/block_scout_web/assets/js/lib/dropzone.js
  7. 36
      apps/block_scout_web/assets/js/pages/verification_form.js
  8. 11
      apps/block_scout_web/assets/package-lock.json
  9. 1
      apps/block_scout_web/assets/package.json
  10. 30
      apps/block_scout_web/assets/webpack.config.js
  11. 178
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_controller.ex
  12. 49
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_flattened_code_controller.ex
  13. 7
      apps/block_scout_web/lib/block_scout_web/controllers/address_contract_verification_via_json_controller.ex
  14. 22
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex
  15. 20
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  16. 22
      apps/block_scout_web/lib/block_scout_web/router.ex
  17. 35
      apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
  18. 393
      apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification/new.html.eex
  19. 314
      apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex
  20. 59
      apps/block_scout_web/lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex
  21. 9
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
  22. 9
      apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
  23. 9
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input.html.eex
  24. 9
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
  25. 5
      apps/block_scout_web/lib/block_scout_web/views/address_contract_verification_via_flattened_code_view.ex
  26. 3
      apps/block_scout_web/lib/block_scout_web/views/address_contract_verification_via_json_view.ex
  27. 2
      apps/block_scout_web/lib/block_scout_web/views/address_contract_verification_view.ex
  28. 7
      apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex
  29. 30
      apps/block_scout_web/lib/block_scout_web/web_router.ex
  30. 245
      apps/block_scout_web/priv/gettext/default.pot
  31. 245
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  32. 2
      apps/block_scout_web/test/block_scout_web/features/pages/contract_verify_page.ex
  33. 6
      apps/explorer/config/config.exs
  34. 69
      apps/explorer/lib/explorer/chain.ex
  35. 2
      apps/explorer/lib/explorer/chain/address.ex
  36. 11
      apps/explorer/lib/explorer/chain/smart_contract.ex
  37. 63
      apps/explorer/lib/explorer/chain/smart_contract_additional_sources.ex
  38. 8
      apps/explorer/lib/explorer/smart_contract/publisher.ex
  39. 184
      apps/explorer/lib/explorer/third_party_integrations/sourcify.ex
  40. 6
      apps/explorer/mix.exs
  41. 22
      apps/explorer/priv/repo/migrations/20201214203532_support_sourcify.exs
  42. 7
      apps/explorer/test/explorer/chain_test.exs
  43. 1
      mix.exs

@ -23,6 +23,8 @@ lib/indexer/fetcher/token_total_supply_on_demand.ex:16
lib/explorer/exchange_rates/source.ex:110 lib/explorer/exchange_rates/source.ex:110
lib/explorer/exchange_rates/source.ex:113 lib/explorer/exchange_rates/source.ex:113
lib/explorer/smart_contract/verifier.ex:89 lib/explorer/smart_contract/verifier.ex:89
lib/block_scout_web/templates/address_contract/index.html.eex:123 lib/block_scout_web/templates/address_contract/index.html.eex:149
lib/explorer/staking/stake_snapshotting.ex:15: Function do_snapshotting/7 has no local return lib/explorer/staking/stake_snapshotting.ex:15: Function do_snapshotting/7 has no local return
lib/explorer/staking/stake_snapshotting.ex:147 lib/explorer/staking/stake_snapshotting.ex:147
lib/explorer/third_party_integrations/sourcify.ex:65
lib/explorer/third_party_integrations/sourcify.ex:68

@ -95,6 +95,7 @@
&:hover { &:hover {
background-color: darken($bg-color, 10%); background-color: darken($bg-color, 10%);
border-color: darken($bg-color, 10%); border-color: darken($bg-color, 10%);
color: $text-color;
text-decoration: none; text-decoration: none;
} }

@ -119,6 +119,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/_external_link"; @import "components/_external_link";
@import "components/_label"; @import "components/_label";
@import "components/_token"; @import "components/_token";
@import "components/_dropzone";
@import "theme/dark-theme"; @import "theme/dark-theme";

@ -0,0 +1,541 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
@-webkit-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%,
70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@-moz-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%,
70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%,
70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@-webkit-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@-moz-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
@-moz-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
@keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
.dropzone-1,
.dropzone-1 * {
box-sizing: border-box;
}
.dropzone-1 {
min-height: 150px;
border: 2px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 20px 20px;
}
.dropzone-1.dz-clickable {
cursor: pointer;
}
.dropzone-1.dz-clickable * {
cursor: default;
}
.dropzone-1.dz-clickable .dz-message,
.dropzone-1.dz-clickable .dz-message * {
cursor: pointer;
}
.dropzone-1.dz-started .dz-message {
display: none;
}
.dropzone-1.dz-drag-hover {
border-style: solid;
}
.dropzone-1.dz-drag-hover .dz-message {
opacity: 0.5;
}
.dropzone-1 .dz-message {
text-align: center;
margin: 2em 0;
}
.dropzone-1 .dz-message .dz-button {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;
}
.dropzone-1 .dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px;
}
.dropzone-1 .dz-preview:hover {
z-index: 1000;
}
.dropzone-1 .dz-preview:hover .dz-details {
opacity: 1;
}
.dropzone-1 .dz-preview.dz-file-preview .dz-image {
border-radius: 20px;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd);
}
.dropzone-1 .dz-preview.dz-file-preview .dz-details {
opacity: 1;
}
.dropzone-1 .dz-preview.dz-image-preview {
background: white;
}
.dropzone-1 .dz-preview.dz-image-preview .dz-details {
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-ms-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.dropzone-1 .dz-preview .dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none;
}
.dropzone-1 .dz-preview .dz-remove:hover {
text-decoration: underline;
}
.dropzone-1 .dz-preview:hover .dz-details {
opacity: 1;
}
.dropzone-1 .dz-preview .dz-details {
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
line-height: 150%;
}
.dropzone-1 .dz-preview .dz-details .dz-size {
margin-bottom: 1em;
font-size: 16px;
}
.dropzone-1 .dz-preview .dz-details .dz-filename {
white-space: nowrap;
}
.dropzone-1 .dz-preview .dz-details .dz-filename:hover span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8);
}
.dropzone-1 .dz-preview .dz-details .dz-filename:not(:hover) {
overflow: hidden;
text-overflow: ellipsis;
}
.dropzone-1 .dz-preview .dz-details .dz-filename:not(:hover) span {
border: 1px solid transparent;
}
.dropzone-1 .dz-preview .dz-details .dz-filename span,
.dropzone-1 .dz-preview .dz-details .dz-size span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px;
}
.dropzone-1 .dz-preview:hover .dz-image img {
-webkit-transform: scale(1.05, 1.05);
-moz-transform: scale(1.05, 1.05);
-ms-transform: scale(1.05, 1.05);
-o-transform: scale(1.05, 1.05);
transform: scale(1.05, 1.05);
-webkit-filter: blur(8px);
filter: blur(8px);
}
.dropzone-1 .dz-preview .dz-image {
border-radius: 20px;
overflow: hidden;
width: 120px;
height: 120px;
position: relative;
display: block;
z-index: 10;
}
.dropzone-1 .dz-preview .dz-image img {
display: block;
}
.dropzone-1 .dz-preview.dz-success .dz-success-mark {
-webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
}
.dropzone-1 .dz-preview.dz-error .dz-error-mark {
opacity: 1;
-webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
}
.dropzone-1 .dz-preview .dz-success-mark,
.dropzone-1 .dz-preview .dz-error-mark {
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -27px;
margin-top: -27px;
}
.dropzone-1 .dz-preview .dz-success-mark svg,
.dropzone-1 .dz-preview .dz-error-mark svg {
display: block;
width: 54px;
height: 54px;
}
.dropzone-1 .dz-preview.dz-processing .dz-progress {
opacity: 1;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-ms-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear;
}
.dropzone-1 .dz-preview.dz-complete .dz-progress {
opacity: 0;
-webkit-transition: opacity 0.4s ease-in;
-moz-transition: opacity 0.4s ease-in;
-ms-transition: opacity 0.4s ease-in;
-o-transition: opacity 0.4s ease-in;
transition: opacity 0.4s ease-in;
}
.dropzone-1 .dz-preview:not(.dz-processing) .dz-progress {
-webkit-animation: pulse 6s ease infinite;
-moz-animation: pulse 6s ease infinite;
-ms-animation: pulse 6s ease infinite;
-o-animation: pulse 6s ease infinite;
animation: pulse 6s ease infinite;
}
.dropzone-1 .dz-preview .dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
background: rgba(255, 255, 255, 0.9);
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden;
}
.dropzone-1 .dz-preview .dz-progress .dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
-webkit-transition: width 300ms ease-in-out;
-moz-transition: width 300ms ease-in-out;
-ms-transition: width 300ms ease-in-out;
-o-transition: width 300ms ease-in-out;
transition: width 300ms ease-in-out;
}
.dropzone-1 .dz-preview.dz-error .dz-error-message {
display: block;
}
.dropzone-1 .dz-preview.dz-error:hover .dz-error-message {
opacity: 1;
pointer-events: auto;
}
.dropzone-1 .dz-preview .dz-error-message {
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
border-radius: 8px;
font-size: 13px;
top: 130px;
left: -10px;
width: 140px;
background: #be2626;
background: linear-gradient(to bottom, #be2626, #a92222);
padding: 0.5em 1.2em;
color: white;
}
.dropzone-1 .dz-preview .dz-error-message:after {
content: '';
position: absolute;
top: -6px;
left: 64px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #be2626;
}
// custom styles
.dropzone-1 {
border-color: $primary !important;
border-style: dashed !important;
align-items: center;
justify-content: center;
display: flex;
background: rgba($primary, 0.1) !important;
}

@ -57,6 +57,10 @@ $new-smart-contract-center-column-margin-right: 30px;
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
&.vertical {
display: block;
}
.radio-big { .radio-big {
margin-right: 20px; margin-right: 20px;

@ -5,6 +5,7 @@ import humps from 'humps'
import { subscribeChannel } from '../socket' import { subscribeChannel } from '../socket'
import { createStore, connectElements } from '../lib/redux_helpers.js' import { createStore, connectElements } from '../lib/redux_helpers.js'
import '../app' import '../app'
import Dropzone from 'dropzone'
export const initialState = { export const initialState = {
channelDisconnected: false, channelDisconnected: false,
@ -27,7 +28,7 @@ export function reducer (state = initialState, action) {
} }
case 'RECEIVED_VERIFICATION_RESULT': { case 'RECEIVED_VERIFICATION_RESULT': {
if (action.msg.verificationResult === 'ok') { if (action.msg.verificationResult === 'ok') {
return window.location.replace(window.location.href.split('/contract_verifications')[0] + '/contracts') return window.location.replace(window.location.href.split('/contract_verifications')[0].split('/verify')[0] + '/contracts')
} else { } else {
return Object.assign({}, state, { return Object.assign({}, state, {
newForm: action.msg.verificationResult newForm: action.msg.verificationResult
@ -88,6 +89,7 @@ const elements = {
} }
const $contractVerificationPage = $('[data-page="contract-verification"]') const $contractVerificationPage = $('[data-page="contract-verification"]')
const $contractVerificationChooseTypePage = $('[data-page="contract-verification-choose-type"]')
function filterNightlyBuilds (filter) { function filterNightlyBuilds (filter) {
const select = document.getElementById('smart_contract_compiler_version') const select = document.getElementById('smart_contract_compiler_version')
@ -136,6 +138,16 @@ if ($contractVerificationPage.length) {
}) })
$(function () { $(function () {
if ($('#metadata-json-dropzone').length) {
var dropzone = new Dropzone('#metadata-json-dropzone', {
autoProcessQueue: false,
acceptedFiles: 'text/plain,application/json,.sol,.json',
parallelUploads: 100,
uploadMultiple: true,
addRemoveLinks: true,
params: { address_hash: $('#smart_contract_address_hash').val() }
})
}
setTimeout(function () { setTimeout(function () {
$('.nightly-builds-false').trigger('click') $('.nightly-builds-false').trigger('click')
}, 10) }, 10)
@ -188,5 +200,27 @@ if ($contractVerificationPage.length) {
$('.js-add-contract-library-wrapper').hide() $('.js-add-contract-library-wrapper').hide()
} }
}) })
$('#verify-via-json-submit').on('click', function (e) {
if (dropzone.files.length > 0) {
dropzone.processQueue()
} else {
$('#loading').addClass('d-none')
}
})
})
} else if ($contractVerificationChooseTypePage.length) {
$('.verify-via-flattened-code').on('click', function () {
if ($(this).prop('checked')) {
$('#verify_via_flattened_code_button').show()
$('#verify_via_json_button').hide()
}
})
$('.verify-via-json').on('click', function () {
if ($(this).prop('checked')) {
$('#verify_via_flattened_code_button').hide()
$('#verify_via_json_button').show()
}
}) })
} }

@ -16,6 +16,7 @@
"clipboard": "^2.0.4", "clipboard": "^2.0.4",
"core-js": "^2.6.12", "core-js": "^2.6.12",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
"dropzone": "^5.7.2",
"eth-net-props": "^1.0.33", "eth-net-props": "^1.0.33",
"highlight.js": "^10.4.0", "highlight.js": "^10.4.0",
"https-browserify": "^1.0.0", "https-browserify": "^1.0.0",
@ -5628,6 +5629,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/dropzone": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.2.tgz",
"integrity": "sha512-5t2z51DzIsWDbTpwcJIvUlwxBbvcwdCApz0yb9ecKJwG155Xm92KMEZmHW1B0MzoXOKvFwdd0nPu5cpeVcvPHQ=="
},
"node_modules/duplexer3": { "node_modules/duplexer3": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@ -23522,6 +23528,11 @@
"is-obj": "^2.0.0" "is-obj": "^2.0.0"
} }
}, },
"dropzone": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.2.tgz",
"integrity": "sha512-5t2z51DzIsWDbTpwcJIvUlwxBbvcwdCApz0yb9ecKJwG155Xm92KMEZmHW1B0MzoXOKvFwdd0nPu5cpeVcvPHQ=="
},
"duplexer3": { "duplexer3": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",

@ -28,6 +28,7 @@
"clipboard": "^2.0.4", "clipboard": "^2.0.4",
"core-js": "^2.6.12", "core-js": "^2.6.12",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
"dropzone": "^5.7.2",
"eth-net-props": "^1.0.33", "eth-net-props": "^1.0.33",
"highlight.js": "^10.4.0", "highlight.js": "^10.4.0",
"https-browserify": "^1.0.0", "https-browserify": "^1.0.0",

@ -66,6 +66,34 @@ const awesompleteJs = {
] ]
} }
const dropzoneJs = {
entry: {
dropzone: './js/lib/dropzone.js',
},
output: {
filename: '[name].min.js',
path: path.resolve(__dirname, '../priv/static/js')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
}
]
}
]
},
optimization: {
minimizer: [
new TerserJSPlugin(jsOptimizationParams),
]
}
}
const appJs = const appJs =
{ {
entry: { entry: {
@ -183,4 +211,4 @@ const appJs =
const viewScripts = glob.sync('./js/view_specific/**/*.js').map(transpileViewScript) const viewScripts = glob.sync('./js/view_specific/**/*.js').map(transpileViewScript)
module.exports = viewScripts.concat(appJs, awesompleteJs) module.exports = viewScripts.concat(appJs, awesompleteJs, dropzoneJs)

@ -1,8 +1,12 @@
defmodule BlockScoutWeb.AddressContractVerificationController do defmodule BlockScoutWeb.AddressContractVerificationController do
use BlockScoutWeb, :controller use BlockScoutWeb, :controller
alias BlockScoutWeb.API.RPC.ContractController
alias Explorer.Chain
alias Explorer.Chain.Events.Publisher, as: EventsPublisher
alias Explorer.Chain.SmartContract alias Explorer.Chain.SmartContract
alias Explorer.SmartContract.{PublisherWorker, Solidity.CodeCompiler, Solidity.CompilerVersion} alias Explorer.SmartContract.{PublisherWorker, Solidity.CodeCompiler, Solidity.CompilerVersion}
alias Explorer.ThirdPartyIntegrations.Sourcify
def new(conn, %{"address_id" => address_hash_string}) do def new(conn, %{"address_id" => address_hash_string}) do
changeset = changeset =
@ -40,6 +44,180 @@ defmodule BlockScoutWeb.AddressContractVerificationController do
send_resp(conn, 204, "") send_resp(conn, 204, "")
end end
def create(
conn,
%{
"address_hash" => address_hash_string,
"file" => files
}
) do
files_array = if is_map(files), do: Enum.map(files, fn {_, file} -> file end), else: []
json_files =
files_array
|> Enum.filter(fn file -> file.content_type == "application/json" end)
json_file = json_files |> Enum.at(0)
if json_file do
if Chain.smart_contract_verified?(address_hash_string) do
# ... todo: we need to return an error here
EventsPublisher.broadcast(
[{:contract_verification_result, {address_hash_string, {:error, []}, conn}}],
:on_demand
)
else
case Sourcify.check_by_address(address_hash_string) do
{:ok, _verified_status} ->
get_metadata_and_publish(address_hash_string, conn)
_ ->
verify_and_publish(address_hash_string, files_array, conn)
end
end
else
EventsPublisher.broadcast(
[{:contract_verification_result, {address_hash_string, {:error, []}, conn}}],
:on_demand
)
end
send_resp(conn, 200, "ok")
end
def create(conn, _params) do
Que.add(PublisherWorker, {"", %{}, %{}, conn})
send_resp(conn, 204, "")
end
defp verify_and_publish(address_hash_string, files_array, conn) do
case Sourcify.verify(address_hash_string, files_array) do
{:ok, _verified_status} ->
case Sourcify.check_by_address(address_hash_string) do
{:ok, _verified_status} ->
get_metadata_and_publish(address_hash_string, conn)
_ ->
EventsPublisher.broadcast(
[{:contract_verification_result, {address_hash_string, {:error, []}, conn}}],
:on_demand
)
end
_ ->
EventsPublisher.broadcast(
[{:contract_verification_result, {address_hash_string, {:error, []}, conn}}],
:on_demand
)
end
end
defp get_metadata_and_publish(address_hash_string, conn) do
case Sourcify.get_metadata(address_hash_string) do
{:ok, verification_metadata} ->
%{"params_to_publish" => params_to_publish, "abi" => abi, "secondary_sources" => secondary_sources} =
parse_params_from_sourcify(address_hash_string, verification_metadata)
ContractController.publish(conn, %{
"addressHash" => address_hash_string,
"params" => params_to_publish,
"abi" => abi,
"secondarySources" => secondary_sources
})
_ ->
EventsPublisher.broadcast(
[{:contract_verification_result, {address_hash_string, {:error, []}, conn}}],
:on_demand
)
end
end
def parse_params_from_sourcify(address_hash_string, verification_metadata) do
verification_metadata_json =
verification_metadata
|> Enum.filter(fn %{"name" => name, "content" => _content} -> name =~ ".json" end)
|> Enum.at(0)
full_params_initial = parse_json_from_sourcify_for_insertion(verification_metadata_json)
verification_metadata_sol =
verification_metadata
|> Enum.filter(fn %{"name" => name, "content" => _content} -> name =~ ".sol" end)
full_params =
verification_metadata_sol
|> Enum.reduce(full_params_initial, fn %{"name" => name, "content" => content, "path" => _path} = param,
full_params_acc ->
compilation_target_file_name = Map.get(full_params_acc, "compilation_target_file_name")
if String.downcase(name) == String.downcase(compilation_target_file_name) do
%{
"params_to_publish" => extract_primary_source_code(content, Map.get(full_params_acc, "params_to_publish")),
"abi" => Map.get(full_params_acc, "abi"),
"secondary_sources" => Map.get(full_params_acc, "secondary_sources"),
"compilation_target_file_name" => Map.get(full_params_acc, "compilation_target_file_name")
}
else
secondary_sources = [
prepare_additional_source(address_hash_string, param) | Map.get(full_params_acc, "secondary_sources")
]
%{
"params_to_publish" => Map.get(full_params_acc, "params_to_publish"),
"abi" => Map.get(full_params_acc, "abi"),
"secondary_sources" => secondary_sources,
"compilation_target_file_name" => Map.get(full_params_acc, "compilation_target_file_name")
}
end
end)
full_params
end
defp prepare_additional_source(address_hash_string, %{"name" => name, "content" => content, "path" => _path}) do
%{
"address_hash" => address_hash_string,
"file_name" => name,
"contract_source_code" => content
}
end
defp extract_primary_source_code(content, params) do
params
|> Map.put("contract_source_code", content)
end
def parse_json_from_sourcify_for_insertion(verification_metadata_json) do
%{"name" => _, "content" => content} = verification_metadata_json
content_json = Sourcify.decode_json(content)
compiler_version = "v" <> (content_json |> Map.get("compiler") |> Map.get("version"))
abi = content_json |> Map.get("output") |> Map.get("abi")
settings = Map.get(content_json, "settings")
compilation_target_file_path = settings |> Map.get("compilationTarget") |> Map.keys() |> Enum.at(0)
compilation_target_file_name = compilation_target_file_path |> String.split("/") |> Enum.at(-1)
contract_name = settings |> Map.get("compilationTarget") |> Map.get("#{compilation_target_file_path}")
optimizer = Map.get(settings, "optimizer")
params =
%{}
|> Map.put("name", contract_name)
|> Map.put("compiler_version", compiler_version)
|> Map.put("evm_version", Map.get(settings, "evmVersion"))
|> Map.put("optimization", Map.get(optimizer, "enabled"))
|> Map.put("optimization_runs", Map.get(optimizer, "runs"))
|> Map.put("external_libraries", Map.get(settings, "libraries"))
|> Map.put("verified_via_sourcify", true)
%{
"params_to_publish" => params,
"abi" => abi,
"compilation_target_file_name" => compilation_target_file_name,
"secondary_sources" => []
}
end
def parse_optimization_runs(%{"runs" => runs}) do def parse_optimization_runs(%{"runs" => runs}) do
case Integer.parse(runs) do case Integer.parse(runs) do
{integer, ""} -> integer {integer, ""} -> integer

@ -0,0 +1,49 @@
defmodule BlockScoutWeb.AddressContractVerificationViaFlattenedCodeController do
use BlockScoutWeb, :controller
alias Explorer.Chain.SmartContract
alias Explorer.SmartContract.{PublisherWorker, Solidity.CodeCompiler, Solidity.CompilerVersion}
def new(conn, %{"address_id" => address_hash_string}) do
changeset =
SmartContract.changeset(
%SmartContract{address_hash: address_hash_string},
%{}
)
compiler_versions =
case CompilerVersion.fetch_versions() do
{:ok, compiler_versions} ->
compiler_versions
{:error, _} ->
[]
end
render(conn, "new.html",
changeset: changeset,
compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(),
address_hash: address_hash_string
)
end
def create(
conn,
%{
"smart_contract" => smart_contract,
"external_libraries" => external_libraries
}
) do
Que.add(PublisherWorker, {smart_contract["address_hash"], smart_contract, external_libraries, conn})
send_resp(conn, 204, "")
end
def parse_optimization_runs(%{"runs" => runs}) do
case Integer.parse(runs) do
{integer, ""} -> integer
_ -> 200
end
end
end

@ -0,0 +1,7 @@
defmodule BlockScoutWeb.AddressContractVerificationViaJsonController do
use BlockScoutWeb, :controller
def new(conn, %{"address_id" => address_hash_string}) do
render(conn, "new.html", address_hash: address_hash_string)
end
end

@ -3,6 +3,7 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
alias BlockScoutWeb.API.RPC.Helpers alias BlockScoutWeb.API.RPC.Helpers
alias Explorer.Chain alias Explorer.Chain
alias Explorer.Chain.Events.Publisher, as: EventsPublisher
alias Explorer.Chain.SmartContract alias Explorer.Chain.SmartContract
alias Explorer.SmartContract.Publisher alias Explorer.SmartContract.Publisher
@ -42,6 +43,27 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
end end
end end
def publish(conn, %{"addressHash" => address_hash, "params" => params, "abi" => abi} = input) do
params =
if Map.has_key?(input, "secondarySources") do
params
|> Map.put("secondary_sources", Map.get(input, "secondarySources"))
else
params
end
result =
case Publisher.publish_smart_contract(address_hash, params, abi) do
{:ok, _contract} = result ->
result
{:error, changeset} ->
{:error, changeset}
end
EventsPublisher.broadcast([{:contract_verification_result, {address_hash, result, conn}}], :on_demand)
end
def listcontracts(conn, params) do def listcontracts(conn, params) do
with pagination_options <- Helpers.put_pagination_options(%{}, params), with pagination_options <- Helpers.put_pagination_options(%{}, params),
{:params, {:ok, options}} <- {:params, add_filters(pagination_options, params)} do {:params, {:ok, options}} <- {:params, add_filters(pagination_options, params)} do

@ -4,7 +4,13 @@ defmodule BlockScoutWeb.Notifier do
""" """
alias Absinthe.Subscription alias Absinthe.Subscription
alias BlockScoutWeb.{AddressContractVerificationView, Endpoint}
alias BlockScoutWeb.{
AddressContractVerificationViaFlattenedCodeView,
AddressContractVerificationViaJsonView,
Endpoint
}
alias Explorer.{Chain, Market, Repo} alias Explorer.{Chain, Market, Repo}
alias Explorer.Chain.{Address, InternalTransaction, TokenTransfer, Transaction} alias Explorer.Chain.{Address, InternalTransaction, TokenTransfer, Transaction}
alias Explorer.Chain.Supply.RSK alias Explorer.Chain.Supply.RSK
@ -40,6 +46,8 @@ defmodule BlockScoutWeb.Notifier do
def handle_event( def handle_event(
{:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}} {:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}}
) do ) do
verification_from_json_upload? = Map.has_key?(conn.params, "file")
contract_verification_result = contract_verification_result =
case contract_verification_result do case contract_verification_result do
{:ok, _} = result -> {:ok, _} = result ->
@ -55,8 +63,16 @@ defmodule BlockScoutWeb.Notifier do
[] []
end end
view =
if verification_from_json_upload? do
AddressContractVerificationViaJsonView
else
AddressContractVerificationViaFlattenedCodeView
end
result = result =
View.render_to_string(AddressContractVerificationView, "new.html", view
|> View.render_to_string("new.html",
changeset: changeset, changeset: changeset,
compiler_versions: compiler_versions, compiler_versions: compiler_versions,
evm_versions: CodeCompiler.allowed_evm_versions(), evm_versions: CodeCompiler.allowed_evm_versions(),

@ -75,6 +75,28 @@ defmodule BlockScoutWeb.Router do
end end
end end
# if path != api_path do
# scope to_string(api_path) <> "/verify_smart_contract" do
# pipe_through(:api)
# if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
# post("/contract_verifications", BlockScoutWeb.AddressContractVerificationController, :create)
# else
# post("/contract_verifications", BlockScoutWeb.AddressContractVerificationViaFlattenedCodeController, :create)
# end
# end
# else
# scope "/verify_smart_contract" do
# pipe_through(:api)
# if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
# post("/contract_verifications", BlockScoutWeb.AddressContractVerificationController, :create)
# else
# post("/contract_verifications", BlockScoutWeb.AddressContractVerificationViaFlattenedCodeController, :create)
# end
# end
# end
if Application.get_env(:block_scout_web, WebRouter)[:enabled] do if Application.get_env(:block_scout_web, WebRouter)[:enabled] do
forward("/", BlockScoutWeb.WebRouter) forward("/", BlockScoutWeb.WebRouter)
else else

@ -2,6 +2,8 @@
<% minimal_proxy_template = Chain.get_minimal_proxy_template(@address.hash) %> <% minimal_proxy_template = Chain.get_minimal_proxy_template(@address.hash) %>
<% metadata_for_verification = minimal_proxy_template || Chain.get_address_verified_twin_contract(@address.hash).verified_contract %> <% metadata_for_verification = minimal_proxy_template || Chain.get_address_verified_twin_contract(@address.hash).verified_contract %>
<% smart_contract_verified = BlockScoutWeb.AddressView.smart_contract_verified?(@address) %> <% smart_contract_verified = BlockScoutWeb.AddressView.smart_contract_verified?(@address) %>
<% additional_sources_from_twin = Chain.get_address_verified_twin_contract(@address.hash).additional_sources %>
<% additional_sources = if smart_contract_verified, do: @address.smart_contract_additional_sources, else: additional_sources_from_twin %>
<section class="container"> <section class="container">
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %> <%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
@ -24,6 +26,14 @@
<% end %> <% end %>
<%= if smart_contract_verified || (!smart_contract_verified && metadata_for_verification) do %> <%= if smart_contract_verified || (!smart_contract_verified && metadata_for_verification) do %>
<% target_contract = if smart_contract_verified, do: @address.smart_contract, else: metadata_for_verification %> <% target_contract = if smart_contract_verified, do: @address.smart_contract, else: metadata_for_verification %>
<%= if @address.smart_contract.verified_via_sourcify && smart_contract_verified do %>
<div class="mb-4">
<i style="color: #f7b32b;" class="fa fa-info-circle"></i><span> <%= gettext("This contract has been verified via Sourcify.") %>
<a data-test="external_url" href=<%= sourcify_repo_url(@address.hash) %> target="_blank">
View contract in Sourcify repository <span class="external-token-icon"><%= render BlockScoutWeb.IconsView, "_external_link.html" %></span>
</a>
</div>
<% end %>
<div class="mb-4"> <div class="mb-4">
<dl class="row"> <dl class="row">
<dt class="col-md-2 text-muted"><%= gettext "Contract name:" %></dt> <dt class="col-md-2 text-muted"><%= gettext "Contract name:" %></dt>
@ -73,6 +83,22 @@
</div> </div>
</section> </section>
<%= if target_contract.verified_via_sourcify do %>
<%= Enum.map(additional_sources, fn additional_source -> %>
<section>
<div class="d-flex justify-content-between align-items-baseline">
<h3><%= additional_source.file_name %></h3>
<button type="button" class="btn-line" id="button" data-toggle="tooltip" data-placement="top" data-clipboard-text="<%= additional_source.contract_source_code %>" aria-label="Copy Contract Source Code">
<%= gettext "Copy Source Code" %>
</button>
</div>
<div class="tile tile-muted mb-4">
<pre class="pre-scrollable line-numbers" data-activate-highlight><code class="solidity"><%= for {line, number} <- contract_lines_with_index(additional_source.contract_source_code, additional_source.inserted_at) do %><div data-line-number="<%= number %>"><%= line %></div><% end %></code></pre>
</div>
</section>
<% end)%>
<% end %>
<section> <section>
<div class="d-flex justify-content-between align-items-baseline"> <div class="d-flex justify-content-between align-items-baseline">
<h3><%= gettext "Contract ABI" %></h3> <h3><%= gettext "Contract ABI" %></h3>
@ -126,9 +152,16 @@
</div> </div>
<% else %> <% else %>
<%= if !smart_contract_verified do %> <%= if !smart_contract_verified do %>
<% path =
if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
address_verify_contract_path(@conn, :new, @address.hash)
else
address_verify_contract_via_flattened_code_path(@conn, :new, @address.hash)
end
%>
<%= link( <%= link(
gettext("Verify & Publish"), gettext("Verify & Publish"),
to: address_verify_contract_path(@conn, :new, @address.hash), to: path,
class: "button button-primary button-sm float-right ml-3", class: "button button-primary button-sm float-right ml-3",
"data-test": "verify_and_publish" "data-test": "verify_and_publish"
) %> ) %>

@ -1,13 +1,4 @@
<% metadata_for_verification = Chain.get_address_verified_twin_contract(@address_hash).verified_contract %> <section data-page="contract-verification-choose-type" class="container new-smart-contract-container">
<% contract_name_value = if metadata_for_verification, do: metadata_for_verification.name, else: "" %>
<% optimization_runs_value = if metadata_for_verification, do: metadata_for_verification.optimization_runs, else: "200" %>
<% optimization = if metadata_for_verification, do: metadata_for_verification.optimization, else: true %>
<% evm_version = if metadata_for_verification, do: metadata_for_verification.evm_version, else: "default" %>
<% compiler_version = if metadata_for_verification, do: metadata_for_verification.compiler_version, else: "latest" %>
<% contract_source_code_value = if metadata_for_verification, do: metadata_for_verification.contract_source_code, else: "" %>
<% fetch_constructor_arguments_automatically = if metadata_for_verification, do: true, else: false %>
<% display_constructor_arguments_text_area = if fetch_constructor_arguments_automatically, do: "none", else: "block" %>
<section data-page="contract-verification" class="container new-smart-contract-container">
<div data-selector="channel-disconnected-message" style="display: none;"> <div data-selector="channel-disconnected-message" style="display: none;">
<div data-selector="reload-button" class="alert alert-danger"> <div data-selector="reload-button" class="alert alert-danger">
<a href="#" class="alert-link"><%= gettext "Connection Lost" %></a> <a href="#" class="alert-link"><%= gettext "Connection Lost" %></a>
@ -35,362 +26,31 @@
<div class="smart-contract-form-group"> <div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper"> <div class="smart-contract-form-group-inner-wrapper">
<%= label f, :name, gettext("Contract Name") %> <%= label f, "Verification via" %>
<div class="center-column"> <div class="center-column">
<%= text_input f, :name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block", "data-test": "contract_name", value: contract_name_value %> <div class="form-radios-group vertical">
<%= error_tag f, :name, id: "contract-name-help-block", class: "text-danger form-error" %> <div class="radio-big mb-3">
</div> <%= radio_button f, :verify_via, true, checked: true, class: "form-check-input verify-via-flattened-code", "aria-describedby": "verify_via-help-block" %>
<div class="smart-contract-form-group-tooltip">Must match the name specified in the code. For example, in <span class="tooltip-quote">contract MyContract {..}</span> <strong>MyContract</strong> is the contract name.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Include nightly builds" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :nightly_builds, false, checked: true, class: "form-check-input nightly-builds-false" %>
<div class="radio-icon"></div>
<%= label :nightly_builds, :false, gettext("No"), class: "radio-text" %>
</div>
<div class="radio-big">
<%= radio_button f, :nightly_builds, true, class: "form-check-input nightly-builds-true", "aria-describedby": "nightly_builds-help-block" %>
<div class="radio-icon"></div>
<%= label :nightly_builds, :true, gettext("Yes"), class: "radio-text" %>
</div>
</div>
<%= error_tag f, :nightly_builds, id: "nightly_builds-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">Select yes if you want to show nightly builds.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :compiler_version, gettext("Compiler") %>
<div class="center-column">
<%= select f, :compiler_version, @compiler_versions, class: "form-control border-rounded", selected: compiler_version, "aria-describedby": "compiler-help-block" %>
<%= error_tag f, :compiler_version, id: "compiler-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">The compiler version is specified in <span class="tooltip-quote">pragma solidity X.X.X</span>. Use the compiler version rather than the nightly build. If using the Solidity compiler, run <span class="tooltip-quote">solc —version</span> to check.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :evm_version, :evm_version, gettext("EVM Version") %>
<div class="center-column">
<%= select f, :evm_version, @evm_versions, class: "form-control border-rounded", selected: evm_version, "aria-describedby": "evm-version-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version. <a href="https://forum.poa.network/t/smart-contract-verification-evm-version-details/2318" target="_blank">EVM version details</a>.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Optimization" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :optimization, false, checked: !optimization, class: "form-check-input optimization-false" %>
<div class="radio-icon"></div> <div class="radio-icon"></div>
<%= label :smart_contract_optimization, :false, gettext("No"), class: "radio-text" %> <%= label :verify_via, :true, gettext("Flattened source code"), class: "radio-text" %>
</div> </div>
<div class="radio-big"> <div class="radio-big">
<%= radio_button f, :optimization, true, checked: optimization, class: "form-check-input optimization-true", "aria-describedby": "optimization-help-block" %> <%= radio_button f, :verify_via, false, class: "form-check-input verify-via-json" %>
<div class="radio-icon"></div> <div class="radio-icon"></div>
<%= label :smart_contract_optimization, :true, gettext("Yes"), class: "radio-text" %> <%= label :verify_via, :false, gettext("Sources and metadata JSON file"), class: "radio-text" %>
</div> </div>
</div> </div>
<%= error_tag f, :optimization, id: "optimization-help-block", class: "text-danger form-error" %> <%= error_tag f, :verify_via, id: "verify_via-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">If you enabled optimization during compilation, select yes.</div>
</div>
</div>
<div class="smart-contract-form-group optimization-runs">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :name, gettext("Optimization runs") %>
<div class="center-column">
<%= text_input f, :optimization_runs, value: 200, class: "form-control border-rounded", "aria-describedby": "optimization-runs-help-block", "data-test": "optimization-runs", value: optimization_runs_value %>
</div> </div>
<div class="smart-contract-form-group-tooltip"></div> <div class="smart-contract-form-group-tooltip">Choose a smart-contract verification method. Currently, Blockscout supports 2 methods:<br/>
</div> 1. Verification through flattened source code. <span
</div> data-toggle="tooltip"
data-placement="top"
<div class="smart-contract-form-group"> data-html="true"
<div class="smart-contract-form-group-inner-wrapper"> data-template="<div class='tooltip' role='tooltip'><div class='arrow'></div><div class='tooltip-inner'></div></div>"
<%= label f, :contract_source_code, gettext("Enter the Solidity Contract Code") %> title="If using a flat file for contract verification, you can use the POA Solidity flattener or the Truffle flattener">
<div class="center-column"> <i style="color: #f7b32b;" class="fa fa-info-circle ml-1" data-test="token-bridge-supply"></i></span><br/>
<%= textarea f, :contract_source_code, class: "form-control border-rounded monospace", rows: 3, "aria-describedby": "contract-source-code-help-block", value: contract_source_code_value %> 2. Verification through raw source files and standard JSON file(s) with metadata from the Solidity contract compilation process.</div>
<%= error_tag f, :contract_source_code, id: "contract-source-code-help-block", class: "text-danger form-error", "data-test": "contract-source-code-error" %>
</div>
<div class="smart-contract-form-group-tooltip">We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the <a href="https://github.com/poanetwork/solidity-flattener" target="_blank">POA solidity flattener or the <a href="https://www.npmjs.com/package/truffle-flattener" target="_blank">truffle flattener</a>.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Try to fetch contructor arguments automatically" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :autodetect_contructor_args, false, checked: !fetch_constructor_arguments_automatically, class: "form-check-input autodetectfalse" %>
<div class="radio-icon"></div>
<%= label :autodetect_contructor_args, :false, gettext("No"), class: "radio-text" %>
</div>
<div class="radio-big">
<%= radio_button f, :autodetect_contructor_args, true, checked: fetch_constructor_arguments_automatically, class: "form-check-input autodetecttrue", "aria-describedby": "autodetect_contructor_args-help-block" %>
<div class="radio-icon"></div>
<%= label :autodetect_contructor_args, :true, gettext("Yes"), class: "radio-text" %>
</div>
</div>
<%= error_tag f, :autodetect_contructor_args, id: "autodetect_contructor_args-help-block", class: "text-danger form-error" %>
</div>
</div>
</div>
<div class="smart-contract-form-group constructor-arguments" style="display: <%= display_constructor_arguments_text_area %>">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :contructor_arguments, gettext("ABI-encoded Constructor Arguments (if required by the contract)") %>
<div class="center-column">
<%= textarea f, :constructor_arguments, class: "form-control border-rounded monospace", rows: 3, "aria-describedby": "contract-constructor-arguments-help-block" %>
<%= error_tag f, :constructor_arguments, id: "contract-constructor-arguments-help-block", class: "text-danger form-error", "data-test": "contract-constructor-arguments-error" %>
</div>
<div class="smart-contract-form-group-tooltip">Add arguments in <a href="https://solidity.readthedocs.io/en/develop/abi-spec.html" target="_blank">ABI hex encoded form</a>. Constructor arguments are written right to left, and will be found at the end of the input created bytecode. They may also be <a href="https://abi.hashex.org/" target="_blank">parsed here.</a></div>
</div>
</div>
<div class="add-contract-libraries-wrapper">
<span class="btn-line js-btn-add-contract-libraries">Add Contract Libraries</span>
</div>
<div class="smart-contract-libraries-wrapper js-smart-contract-libraries-wrapper">
<h2 class="smart-contract-title margin-bottom-md"><%= gettext "Contract Libraries" %></h2>
<div class="contract-library-form-group js-contract-library-form-group active">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library1, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library1_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">A library name called in the .sol file. Multiple libraries (up to 10) may be added for each contract. Click the Add Library button to add an additional one.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library1, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library1_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">The 0x library address. This can be found in the generated json file or Truffle output (if using truffle).</div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library2, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library2_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library2, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library2_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library3, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library3_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library3, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library3_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library4, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library4_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library4, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library4_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library5, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library5_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library5, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library5_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library6, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library6_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library6, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library6_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library7, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library7_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library7, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library7_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library8, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library8_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library8, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library8_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library9, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library9_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library9, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library9_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library10, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library10_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :library10, gettext("Library Address") %>
<div class="center-column">
<%= text_input f, :library10_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="add-contract-library-wrapper js-add-contract-library-wrapper">
<span class="btn-line js-btn-add-contract-library">Add Library</span>
</div> </div>
</div> </div>
@ -408,8 +68,21 @@
</span> </span>
<%= gettext("Loading....") %> <%= gettext("Loading....") %>
</button> </button>
<%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-button-loading": "animation" %> <%= link(
<%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %> gettext("Next"),
to: address_verify_contract_via_flattened_code_path(@conn, :new, @address_hash),
id: "verify_via_flattened_code_button",
class: "btn-full-primary mr-2",
"data-button-loading": "animation"
) %>
<%= link(
gettext("Next"),
to: address_verify_contract_via_json_path(@conn, :new, @address_hash),
id: "verify_via_json_button",
class: "btn-full-primary mr-2",
style: "display: none;",
"data-button-loading": "animation"
) %>
<%= <%=
link( link(
gettext("Cancel"), gettext("Cancel"),

@ -0,0 +1,314 @@
<% metadata_for_verification = Chain.get_address_verified_twin_contract(@address_hash).verified_contract %>
<% contract_name_value = if metadata_for_verification, do: metadata_for_verification.name, else: "" %>
<% optimization_runs_value = if metadata_for_verification, do: metadata_for_verification.optimization_runs, else: "200" %>
<% optimization = if metadata_for_verification, do: metadata_for_verification.optimization, else: true %>
<% evm_version = if metadata_for_verification, do: metadata_for_verification.evm_version, else: "default" %>
<% compiler_version = if metadata_for_verification, do: metadata_for_verification.compiler_version, else: "latest" %>
<% contract_source_code_value = if metadata_for_verification, do: metadata_for_verification.contract_source_code, else: "" %>
<% fetch_constructor_arguments_automatically = if metadata_for_verification, do: true, else: false %>
<% display_constructor_arguments_text_area = if fetch_constructor_arguments_automatically, do: "none", else: "block" %>
<section data-page="contract-verification" class="container new-smart-contract-container">
<div data-selector="channel-disconnected-message" style="display: none;">
<div data-selector="reload-button" class="alert alert-danger">
<a href="#" class="alert-link"><%= gettext "Connection Lost" %></a>
</div>
</div>
<div class="new-smart-contract-form">
<h1 class="smart-contract-title"><%= gettext "New Smart Contract Verification" %></h1>
<%= form_for @changeset,
address_contract_verification_path(@conn, :create),
[],
fn f -> %>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :address_hash, gettext("Contract Address") %>
<div class="center-column">
<%= text_input f, :address_hash, class: "form-control border-rounded", "aria-describedby": "contract-address-help-block", readonly: true %>
<%= error_tag f, :address_hash, id: "contract-address-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">The 0x address supplied on contract creation.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :name, gettext("Contract Name") %>
<div class="center-column">
<%= text_input f, :name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block", "data-test": "contract_name", value: contract_name_value %>
<%= error_tag f, :name, id: "contract-name-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">Must match the name specified in the code. For example, in <span class="tooltip-quote">contract MyContract {..}</span> <strong>MyContract</strong> is the contract name.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Include nightly builds" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :nightly_builds, false, checked: true, class: "form-check-input nightly-builds-false" %>
<div class="radio-icon"></div>
<%= label :nightly_builds, :false, gettext("No"), class: "radio-text" %>
</div>
<div class="radio-big">
<%= radio_button f, :nightly_builds, true, class: "form-check-input nightly-builds-true", "aria-describedby": "nightly_builds-help-block" %>
<div class="radio-icon"></div>
<%= label :nightly_builds, :true, gettext("Yes"), class: "radio-text" %>
</div>
</div>
<%= error_tag f, :nightly_builds, id: "nightly_builds-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">Select yes if you want to show nightly builds.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :compiler_version, gettext("Compiler") %>
<div class="center-column">
<%= select f, :compiler_version, @compiler_versions, class: "form-control border-rounded", selected: compiler_version, "aria-describedby": "compiler-help-block" %>
<%= error_tag f, :compiler_version, id: "compiler-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">The compiler version is specified in <span class="tooltip-quote">pragma solidity X.X.X</span>. Use the compiler version rather than the nightly build. If using the Solidity compiler, run <span class="tooltip-quote">solc —version</span> to check.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :evm_version, :evm_version, gettext("EVM Version") %>
<div class="center-column">
<%= select f, :evm_version, @evm_versions, class: "form-control border-rounded", selected: evm_version, "aria-describedby": "evm-version-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version. <a href="https://forum.poa.network/t/smart-contract-verification-evm-version-details/2318" target="_blank">EVM version details</a>.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Optimization" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :optimization, false, checked: !optimization, class: "form-check-input optimization-false" %>
<div class="radio-icon"></div>
<%= label :smart_contract_optimization, :false, gettext("No"), class: "radio-text" %>
</div>
<div class="radio-big">
<%= radio_button f, :optimization, true, checked: optimization, class: "form-check-input optimization-true", "aria-describedby": "optimization-help-block" %>
<div class="radio-icon"></div>
<%= label :smart_contract_optimization, :true, gettext("Yes"), class: "radio-text" %>
</div>
</div>
<%= error_tag f, :optimization, id: "optimization-help-block", class: "text-danger form-error" %>
</div>
<div class="smart-contract-form-group-tooltip">If you enabled optimization during compilation, select yes.</div>
</div>
</div>
<div class="smart-contract-form-group optimization-runs">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :name, gettext("Optimization runs") %>
<div class="center-column">
<%= text_input f, :optimization_runs, value: 200, class: "form-control border-rounded", "aria-describedby": "optimization-runs-help-block", "data-test": "optimization-runs", value: optimization_runs_value %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :contract_source_code, gettext("Enter the Solidity Contract Code") %>
<div class="center-column">
<%= textarea f, :contract_source_code, class: "form-control border-rounded monospace", rows: 3, "aria-describedby": "contract-source-code-help-block", value: contract_source_code_value %>
<%= error_tag f, :contract_source_code, id: "contract-source-code-help-block", class: "text-danger form-error", "data-test": "contract-source-code-error" %>
</div>
<div class="smart-contract-form-group-tooltip">We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the <a href="https://github.com/poanetwork/solidity-flattener" target="_blank">POA solidity flattener or the <a href="https://www.npmjs.com/package/truffle-flattener" target="_blank">truffle flattener</a>.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, "Try to fetch contructor arguments automatically" %>
<div class="center-column">
<div class="form-radios-group">
<div class="radio-big">
<%= radio_button f, :autodetect_contructor_args, false, checked: !fetch_constructor_arguments_automatically, class: "form-check-input autodetectfalse" %>
<div class="radio-icon"></div>
<%= label :autodetect_contructor_args, :false, gettext("No"), class: "radio-text" %>
</div>
<div class="radio-big">
<%= radio_button f, :autodetect_contructor_args, true, checked: fetch_constructor_arguments_automatically, class: "form-check-input autodetecttrue", "aria-describedby": "autodetect_contructor_args-help-block" %>
<div class="radio-icon"></div>
<%= label :autodetect_contructor_args, :true, gettext("Yes"), class: "radio-text" %>
</div>
</div>
<%= error_tag f, :autodetect_contructor_args, id: "autodetect_contructor_args-help-block", class: "text-danger form-error" %>
</div>
</div>
</div>
<div class="smart-contract-form-group constructor-arguments" style="display: <%= display_constructor_arguments_text_area %>">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :contructor_arguments, gettext("ABI-encoded Constructor Arguments (if required by the contract)") %>
<div class="center-column">
<%= textarea f, :constructor_arguments, class: "form-control border-rounded monospace", rows: 3, "aria-describedby": "contract-constructor-arguments-help-block" %>
<%= error_tag f, :constructor_arguments, id: "contract-constructor-arguments-help-block", class: "text-danger form-error", "data-test": "contract-constructor-arguments-error" %>
</div>
<div class="smart-contract-form-group-tooltip">Add arguments in <a href="https://solidity.readthedocs.io/en/develop/abi-spec.html" target="_blank">ABI hex encoded form</a>. Constructor arguments are written right to left, and will be found at the end of the input created bytecode. They may also be <a href="https://abi.hashex.org/" target="_blank">parsed here.</a></div>
</div>
</div>
<div class="add-contract-libraries-wrapper">
<span class="btn-line js-btn-add-contract-libraries">Add Contract Libraries</span>
</div>
<div class="smart-contract-libraries-wrapper js-smart-contract-libraries-wrapper">
<h2 class="smart-contract-title margin-bottom-md"><%= gettext "Contract Libraries" %></h2>
<div class="contract-library-form-group js-contract-library-form-group active">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library1, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library1_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">A library name called in the .sol file. Multiple libraries (up to 5) may be added for each contract. Click the Add Library button to add an additional one.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library1, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library1_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip">The 0x library address. This can be found in the generated json file or Truffle output (if using truffle).</div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library2, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library2_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library2, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library2_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library3, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library3_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library3, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library3_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library4, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library4_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library4, gettext("Library Address") %>
<div class="center-column">
<%= text_input :external_libraries, :library4_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="contract-library-form-group js-contract-library-form-group">
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label :external_libraries, :library5, gettext("Library Name") %>
<div class="center-column">
<%= text_input :external_libraries, :library5_name, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<%= label f, :library5, gettext("Library Address") %>
<div class="center-column">
<%= text_input f, :library5_address, class: "form-control border-rounded", "aria-describedby": "contract-name-help-block" %>
</div>
<div class="smart-contract-form-group-tooltip"></div>
</div>
</div>
</div>
<div class="add-contract-library-wrapper js-add-contract-library-wrapper">
<span class="btn-line js-btn-add-contract-library">Add Library</span>
</div>
</div>
<div class="smart-contract-form-buttons">
<button
class="position-absolute w-118 btn-full-primary d-none mr-2"
disabled="true"
id="loading"
name="button"
type="button"
>
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span>
</span>
<%= gettext("Loading....") %>
</button>
<%= submit gettext("Verify & publish"), class: "btn-full-primary mr-2", "data-button-loading": "animation" %>
<%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %>
<%=
link(
gettext("Cancel"),
class: "btn-no-border",
to: address_contract_path(@conn, :index, @address_hash)
)
%>
</div>
<% end %>
</div>
<script defer data-cfasync="false" src="<%= static_path(@conn, "/js/verification-form.js") %>"></script>
</section>

@ -0,0 +1,59 @@
<section data-page="contract-verification" class="container new-smart-contract-container">
<div data-selector="channel-disconnected-message" style="display: none;">
<div data-selector="reload-button" class="alert alert-danger">
<a href="#" class="alert-link"><%= gettext "Connection Lost" %></a>
</div>
</div>
<div class="new-smart-contract-form">
<h1 class="smart-contract-title"><%= gettext "New Smart Contract Verification" %></h1>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<label for="smart_contract_address_hash"><%= gettext("Contract Address") %></label>
<div class="center-column">
<input aria-describedby="contract-address-help-block" class="form-control border-rounded" id="smart_contract_address_hash" name="smart_contract[address_hash]" type="text" value=<%= @address_hash %> readonly="">
</div>
<div class="smart-contract-form-group-tooltip">The 0x address supplied on contract creation.</div>
</div>
</div>
<div class="smart-contract-form-group">
<div class="smart-contract-form-group-inner-wrapper">
<label for="smart_contract_metadata_json"><%= gettext("Sources and Metadata JSON") %></label>
<div class="center-column">
<form action="<%= address_contract_verification_path(@conn, :create) %>" class="dropzone-1" id="metadata-json-dropzone" method="post">
<button class="dz-message btn-full-primary"><%= gettext("Drop sources and metadata JSON file or click here") %></button>
</form>
</div>
<div class="smart-contract-form-group-tooltip">Drop all Solidity contract source files and JSON metadata file(s) created during contract compilation into the drop zone.</div>
</div>
</div>
<div class="smart-contract-form-buttons">
<button
class="position-absolute w-118 btn-full-primary d-none mr-2"
disabled="true"
id="loading"
name="button"
type="button"
>
<span class="loading-spinner-small mr-2">
<span class="loading-spinner-block-1"></span>
<span class="loading-spinner-block-2"></span>
</span>
<%= gettext("Loading....") %>
</button>
<button id="verify-via-json-submit" class="btn-full-primary mr-2" data-button-loading="animation"><%= gettext("Verify & publish") %></button>
<%= reset gettext("Reset"), class: "btn-line mr-2 js-smart-contract-form-reset" %>
<%=
link(
gettext("Cancel"),
class: "btn-no-border",
to: address_contract_path(@conn, :index, @address_hash)
)
%>
</div>
</div>
<script defer data-cfasync="false" src="<%= static_path(@conn, "/js/verification-form.js") %>"></script>
<script defer data-cfasync="false" src="<%= static_path(@conn, "/js/dropzone.min.js") %>"></script>
</section>

@ -6,7 +6,14 @@
<%= gettext "To see accurate decoded input data, the contract must be verified." %> <%= gettext "To see accurate decoded input data, the contract must be verified." %>
<%= case @log.transaction do %> <%= case @log.transaction do %>
<% %{to_address: %{hash: hash}} -> %> <% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a> <% path =
if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
address_verify_contract_path(@conn, :new, hash)
else
address_verify_contract_via_flattened_code_path(@conn, :new, hash)
end
%>
<%= gettext "Verify the contract " %><a href="<%= path %>"><%= gettext "here" %></a>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>

@ -5,12 +5,19 @@
<%= if minimal_proxy_template do %> <%= if minimal_proxy_template do %>
<%= render BlockScoutWeb.CommonComponentsView, "_minimal_proxy_pattern.html", address_hash: metadata_for_verification.address_hash, conn: @conn %> <%= render BlockScoutWeb.CommonComponentsView, "_minimal_proxy_pattern.html", address_hash: metadata_for_verification.address_hash, conn: @conn %>
<% else %> <% else %>
<% path =
if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
address_verify_contract_path(@conn, :new, @address.hash)
else
address_verify_contract_via_flattened_code_path(@conn, :new, @address.hash)
end
%>
<div class="mb-4"> <div class="mb-4">
<%= render BlockScoutWeb.CommonComponentsView, "_info.html" %><span> <%= gettext("Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB") %> <%= link( <%= render BlockScoutWeb.CommonComponentsView, "_info.html" %><span> <%= gettext("Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB") %> <%= link(
metadata_for_verification.address_hash, metadata_for_verification.address_hash,
to: address_contract_path(@conn, :index, metadata_for_verification.address_hash)) %>.<br/> <%= gettext("All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with") %> <%= link( to: address_contract_path(@conn, :index, metadata_for_verification.address_hash)) %>.<br/> <%= gettext("All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with") %> <%= link(
gettext("Verify & Publish"), gettext("Verify & Publish"),
to: address_verify_contract_path(@conn, :new, @address.hash) to: path
) %> <%= gettext("page") %></span> ) %> <%= gettext("page") %></span>
</div> </div>
<% end %> <% end %>

@ -8,7 +8,14 @@
<%= gettext "To see accurate decoded input data, the contract must be verified." %> <%= gettext "To see accurate decoded input data, the contract must be verified." %>
<%= case @transaction do %> <%= case @transaction do %>
<% %{to_address: %{hash: hash}} -> %> <% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a> <% path =
if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
address_verify_contract_path(@conn, :new, hash)
else
address_verify_contract_via_flattened_code_path(@conn, :new, hash)
end
%>
<%= gettext "Verify the contract " %><a href="<%= path %>"><%= gettext "here" %></a>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>

@ -6,7 +6,14 @@
<%= gettext "To see accurate decoded input data, the contract must be verified." %> <%= gettext "To see accurate decoded input data, the contract must be verified." %>
<%= case @transaction do %> <%= case @transaction do %>
<% %{to_address: %{hash: hash}} -> %> <% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a> <% path =
if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
address_verify_contract_path(@conn, :new, hash)
else
address_verify_contract_via_flattened_code_path(@conn, :new, hash)
end
%>
<%= gettext "Verify the contract " %><a href="<%= path %>"><%= gettext "here" %></a>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>

@ -0,0 +1,5 @@
defmodule BlockScoutWeb.AddressContractVerificationViaFlattenedCodeView do
use BlockScoutWeb, :view
alias Explorer.Chain
end

@ -0,0 +1,3 @@
defmodule BlockScoutWeb.AddressContractVerificationViaJsonView do
use BlockScoutWeb, :view
end

@ -1,5 +1,3 @@
defmodule BlockScoutWeb.AddressContractVerificationView do defmodule BlockScoutWeb.AddressContractVerificationView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
alias Explorer.Chain
end end

@ -118,4 +118,11 @@ defmodule BlockScoutWeb.AddressContractView do
def contract_creation_code(%Address{contract_code: contract_code}) do def contract_creation_code(%Address{contract_code: contract_code}) do
{:ok, contract_code} {:ok, contract_code}
end end
def sourcify_repo_url(address_hash) do
checksummed_hash = Address.checksum(address_hash)
chain_id = Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:chain_id]
repo_url = Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:repo_url]
repo_url <> chain_id <> "/" <> checksummed_hash <> "/"
end
end end

@ -126,6 +126,36 @@ defmodule BlockScoutWeb.WebRouter do
as: :verify_contract as: :verify_contract
) )
# if Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled] do
# resources(
# "/contract_verifications",
# AddressContractVerificationController,
# only: [:new],
# as: :verify_contract
# )
# else
# resources(
# "/contract_verifications",
# AddressContractVerificationViaFlattenedCodeController,
# only: [:new],
# as: :verify_contract
# )
# end
resources(
"/verify-via-flattened-code",
AddressContractVerificationViaFlattenedCodeController,
only: [:new],
as: :verify_contract_via_flattened_code
)
resources(
"/verify-via-json",
AddressContractVerificationViaJsonController,
only: [:new],
as: :verify_contract_via_json
)
resources( resources(
"/read-contract", "/read-contract",
AddressReadContractController, AddressReadContractController,

@ -87,7 +87,8 @@ msgid "A string with the name of the module to be invoked."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:156 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:156
msgid "ABI-encoded Constructor Arguments (if required by the contract)" msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr "" msgstr ""
@ -123,7 +124,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:26
#: lib/block_scout_web/views/address_view.ex:104 #: lib/block_scout_web/views/address_view.ex:104
msgid "Address" msgid "Address"
msgstr "" msgstr ""
@ -263,7 +264,9 @@ msgid "Call Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:415 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:88
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:305
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47 #: 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 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:54
msgid "Cancel" msgid "Cancel"
@ -286,17 +289,20 @@ msgid "Clear"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:71 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:71
msgid "Compiler" msgid "Compiler"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:37 #: lib/block_scout_web/templates/address_contract/index.html.eex:47
msgid "Compiler version" msgid "Compiler version"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:13 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:13
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:4
msgid "Connection Lost" msgid "Connection Lost"
msgstr "" msgstr ""
@ -324,17 +330,19 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:56 #: lib/block_scout_web/templates/address_contract/index.html.eex:66
msgid "Constructor Arguments" msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:78 #: lib/block_scout_web/templates/address_contract/index.html.eex:104
msgid "Contract ABI" msgid "Contract ABI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:27 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:27
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:13
#: lib/block_scout_web/views/address_view.ex:102 #: lib/block_scout_web/views/address_view.ex:102
msgid "Contract Address" msgid "Contract Address"
msgstr "" msgstr ""
@ -347,8 +355,8 @@ msgid "Contract Address Pending"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:109 #: lib/block_scout_web/templates/address_contract/index.html.eex:135
#: lib/block_scout_web/templates/address_contract/index.html.eex:117 #: lib/block_scout_web/templates/address_contract/index.html.eex:143
msgid "Contract Byte Code" msgid "Contract Byte Code"
msgstr "" msgstr ""
@ -363,32 +371,34 @@ msgid "Contract Creation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:94 #: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "Contract Creation Code" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:170 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:170
msgid "Contract Libraries" msgid "Contract Libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:38 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:38
msgid "Contract Name" msgid "Contract Name"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:29 #: lib/block_scout_web/templates/address_contract/index.html.eex:39
msgid "Contract name:" msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:66 #: lib/block_scout_web/templates/address_contract/index.html.eex:76
msgid "Contract source code" msgid "Contract source code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:100 #: lib/block_scout_web/templates/address_contract/index.html.eex:126
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
@ -398,7 +408,7 @@ msgid "Contribute"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:80 #: lib/block_scout_web/templates/address_contract/index.html.eex:106
msgid "Copy ABI" msgid "Copy ABI"
msgstr "" msgstr ""
@ -411,7 +421,7 @@ msgid "Copy Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:96 #: lib/block_scout_web/templates/address_contract/index.html.eex:122
msgid "Copy Contract Creation Code" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
@ -421,7 +431,8 @@ msgid "Copy Decompiled Contract Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:68 #: lib/block_scout_web/templates/address_contract/index.html.eex:78
#: lib/block_scout_web/templates/address_contract/index.html.eex:92
msgid "Copy Source Code" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -468,20 +479,20 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:100 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:107
#: lib/block_scout_web/templates/log/_data_decoded_view.html.eex:7 #: lib/block_scout_web/templates/log/_data_decoded_view.html.eex:7
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:103 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:110
msgid "Data" msgid "Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:31 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:38
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:37 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:52 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:32 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:39
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:40 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:62
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
@ -535,7 +546,7 @@ msgid "Details"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:101 #: lib/block_scout_web/templates/address_contract/index.html.eex:127
msgid "Displaying the init data provided of the creating transaction." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -555,8 +566,8 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:78 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:85
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:113 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:120
msgid "ETH" msgid "ETH"
msgstr "" msgstr ""
@ -566,8 +577,8 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:48 #: lib/block_scout_web/templates/address_contract/index.html.eex:58
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:82 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:82
msgid "EVM Version" msgid "EVM Version"
msgstr "" msgstr ""
@ -587,7 +598,8 @@ msgid "Emission Reward"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:124 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:124
msgid "Enter the Solidity Contract Code" msgid "Enter the Solidity Contract Code"
msgstr "" msgstr ""
@ -659,18 +671,18 @@ msgid "Nonce"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:151 #: lib/block_scout_web/templates/address_contract/index.html.eex:184
msgid "External libraries" msgid "External libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:32 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:39
msgid "Failed to decode input data." msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:34 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:41
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:35 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
@ -753,7 +765,7 @@ msgid "However, in general, the"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:25
msgid "IMPORTANT: This information is a best guess based on similar functions from other verified contracts." msgid "IMPORTANT: This information is a best guess based on similar functions from other verified contracts."
msgstr "" msgstr ""
@ -911,7 +923,7 @@ msgid "Total Difficulty"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:25
#: lib/block_scout_web/views/transaction_view.ex:354 #: lib/block_scout_web/views/transaction_view.ex:354
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -964,30 +976,22 @@ msgid "Less than"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:185 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:207 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:185
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:229 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:207
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:251 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:229
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:273 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:251
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:295 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:273
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:317
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:339
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:361
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:383
msgid "Library Address" msgid "Library Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:175 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:197 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:175
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:219 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:197
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:219
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:263 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:241
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:285 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:263
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:307
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:329
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:351
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:373
msgid "Library Name" msgid "Library Name"
msgstr "" msgstr ""
@ -1016,7 +1020,9 @@ msgid "Loading..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:409 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:69
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:299
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:44
msgid "Loading...." msgid "Loading...."
msgstr "" msgstr ""
@ -1090,14 +1096,17 @@ msgid "Name"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:18
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:9
msgid "New Smart Contract Verification" msgid "New Smart Contract Verification"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:55 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:55
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:141 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:98
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:141
#: lib/block_scout_web/templates/stakes/_rows.html.eex:24 #: lib/block_scout_web/templates/stakes/_rows.html.eex:24
msgid "No" msgid "No"
msgstr "" msgstr ""
@ -1109,13 +1118,13 @@ msgid "OUT"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:33 #: lib/block_scout_web/templates/address_contract/index.html.eex:43
msgid "Optimization enabled" msgid "Optimization enabled"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:42 #: lib/block_scout_web/templates/address_contract/index.html.eex:52
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:114 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:114
msgid "Optimization runs" msgid "Optimization runs"
msgstr "" msgstr ""
@ -1166,7 +1175,7 @@ msgid "Pending Transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:17 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:24
msgid "Potential matches from our contract method database:" msgid "Potential matches from our contract method database:"
msgstr "" msgstr ""
@ -1184,7 +1193,7 @@ msgid "QR Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:82 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:89
msgid "Query" msgid "Query"
msgstr "" msgstr ""
@ -1217,7 +1226,9 @@ msgid "Request URL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:412 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:302
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:47
msgid "Reset" msgid "Reset"
msgstr "" msgstr ""
@ -1425,7 +1436,7 @@ msgid "This is useful to allow sending requests to blockscout without having to
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:19 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:26
msgid "To have guaranteed accuracy, use the link above to verify the contract's source code." msgid "To have guaranteed accuracy, use the link above to verify the contract's source code."
msgstr "" msgstr ""
@ -1442,8 +1453,8 @@ msgid "Topic"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:70 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:77
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:73 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:80
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -1568,22 +1579,24 @@ msgid "Value"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
#: lib/block_scout_web/templates/address_contract/index.html.eex:125 #: lib/block_scout_web/templates/address_contract/index.html.eex:151
#: lib/block_scout_web/templates/address_contract/index.html.eex:130 #: lib/block_scout_web/templates/address_contract/index.html.eex:163
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:12 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:19
msgid "Verify & Publish" msgid "Verify & Publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:411 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:301
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:46
msgid "Verify & publish" msgid "Verify & publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:9 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:9 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
@ -1635,7 +1648,7 @@ msgid "View transaction %{transaction} on %{subnetwork}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:112 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:119
msgid "WEI" msgid "WEI"
msgstr "" msgstr ""
@ -1650,9 +1663,10 @@ msgid "Wei"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:60 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:103 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:60
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:146 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:103
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:146
#: lib/block_scout_web/templates/stakes/_rows.html.eex:24 #: lib/block_scout_web/templates/stakes/_rows.html.eex:24
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
@ -1673,9 +1687,9 @@ msgid "false"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:9 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:9 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
msgid "here" msgid "here"
msgstr "" msgstr ""
@ -1761,7 +1775,7 @@ msgid "Loading chart"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:120
msgid "Log Index" msgid "Log Index"
msgstr "" msgstr ""
@ -1924,7 +1938,7 @@ msgid "Waiting for transaction's confirmation..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:82 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:89
msgid "Write" msgid "Write"
msgstr "" msgstr ""
@ -1950,22 +1964,22 @@ msgid "Search by address, token symbol, name, transaction hash, or block number"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:11 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:18
msgid "All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with" msgid "All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
msgid "All metadata displayed below is from that contract. In order to verify current contract, click" msgid "All metadata displayed below is from that contract. In order to verify current contract, click"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
msgid "button" msgid "button"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:14 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:21
msgid "page" msgid "page"
msgstr "" msgstr ""
@ -1976,8 +1990,8 @@ msgid "Play"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:111 #: lib/block_scout_web/templates/address_contract/index.html.eex:137
#: lib/block_scout_web/templates/address_contract/index.html.eex:121 #: lib/block_scout_web/templates/address_contract/index.html.eex:147
msgid "Copy Byte Code" msgid "Copy Byte Code"
msgstr "" msgstr ""
@ -2597,8 +2611,8 @@ msgid "Stakes"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:18 #: lib/block_scout_web/templates/address_contract/index.html.eex:20
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:9 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:16
msgid "Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB" msgid "Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB"
msgstr "" msgstr ""
@ -2754,3 +2768,36 @@ msgstr ""
#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:16 #: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:16
msgid "Your Pool Short Description (optional)" msgid "Your Pool Short Description (optional)"
msgstr "" msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:26
msgid "Drop sources and metadata JSON file or click here"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:35
msgid "Flattened source code"
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:79
msgid "Next"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:23
msgid "Sources and Metadata JSON"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Sources and metadata JSON file"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:31
msgid "This contract has been verified via Sourcify."
msgstr ""

@ -87,7 +87,8 @@ msgid "A string with the name of the module to be invoked."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:156 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:156
msgid "ABI-encoded Constructor Arguments (if required by the contract)" msgid "ABI-encoded Constructor Arguments (if required by the contract)"
msgstr "" msgstr ""
@ -123,7 +124,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:26
#: lib/block_scout_web/views/address_view.ex:104 #: lib/block_scout_web/views/address_view.ex:104
msgid "Address" msgid "Address"
msgstr "" msgstr ""
@ -263,7 +264,9 @@ msgid "Call Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:415 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:88
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:305
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:50
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:47 #: 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 #: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:54
msgid "Cancel" msgid "Cancel"
@ -286,17 +289,20 @@ msgid "Clear"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:71 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:71
msgid "Compiler" msgid "Compiler"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:37 #: lib/block_scout_web/templates/address_contract/index.html.eex:47
msgid "Compiler version" msgid "Compiler version"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:13 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:4
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:13
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:4
msgid "Connection Lost" msgid "Connection Lost"
msgstr "" msgstr ""
@ -324,17 +330,19 @@ msgid "Connection Lost, click to load newer validations"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:56 #: lib/block_scout_web/templates/address_contract/index.html.eex:66
msgid "Constructor Arguments" msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:78 #: lib/block_scout_web/templates/address_contract/index.html.eex:104
msgid "Contract ABI" msgid "Contract ABI"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:27 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:27
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:13
#: lib/block_scout_web/views/address_view.ex:102 #: lib/block_scout_web/views/address_view.ex:102
msgid "Contract Address" msgid "Contract Address"
msgstr "" msgstr ""
@ -347,8 +355,8 @@ msgid "Contract Address Pending"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:109 #: lib/block_scout_web/templates/address_contract/index.html.eex:135
#: lib/block_scout_web/templates/address_contract/index.html.eex:117 #: lib/block_scout_web/templates/address_contract/index.html.eex:143
msgid "Contract Byte Code" msgid "Contract Byte Code"
msgstr "" msgstr ""
@ -363,32 +371,34 @@ msgid "Contract Creation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:94 #: lib/block_scout_web/templates/address_contract/index.html.eex:120
msgid "Contract Creation Code" msgid "Contract Creation Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:170 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:170
msgid "Contract Libraries" msgid "Contract Libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:38 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:38
msgid "Contract Name" msgid "Contract Name"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:29 #: lib/block_scout_web/templates/address_contract/index.html.eex:39
msgid "Contract name:" msgid "Contract name:"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:66 #: lib/block_scout_web/templates/address_contract/index.html.eex:76
msgid "Contract source code" msgid "Contract source code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:100 #: lib/block_scout_web/templates/address_contract/index.html.eex:126
msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified." msgid "Contracts that self destruct in their constructors have no contract code published and cannot be verified."
msgstr "" msgstr ""
@ -398,7 +408,7 @@ msgid "Contribute"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:80 #: lib/block_scout_web/templates/address_contract/index.html.eex:106
msgid "Copy ABI" msgid "Copy ABI"
msgstr "" msgstr ""
@ -411,7 +421,7 @@ msgid "Copy Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:96 #: lib/block_scout_web/templates/address_contract/index.html.eex:122
msgid "Copy Contract Creation Code" msgid "Copy Contract Creation Code"
msgstr "" msgstr ""
@ -421,7 +431,8 @@ msgid "Copy Decompiled Contract Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:68 #: lib/block_scout_web/templates/address_contract/index.html.eex:78
#: lib/block_scout_web/templates/address_contract/index.html.eex:92
msgid "Copy Source Code" msgid "Copy Source Code"
msgstr "" msgstr ""
@ -468,20 +479,20 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:100 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:107
#: lib/block_scout_web/templates/log/_data_decoded_view.html.eex:7 #: lib/block_scout_web/templates/log/_data_decoded_view.html.eex:7
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:103 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:110
msgid "Data" msgid "Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:31 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:38
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:37 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:52 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:32 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:39
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:40 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:55 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:62
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
@ -535,7 +546,7 @@ msgid "Details"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:101 #: lib/block_scout_web/templates/address_contract/index.html.eex:127
msgid "Displaying the init data provided of the creating transaction." msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
@ -555,8 +566,8 @@ msgid "ERC-721 "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:78 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:85
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:113 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:120
msgid "ETH" msgid "ETH"
msgstr "" msgstr ""
@ -566,8 +577,8 @@ msgid "ETH RPC API Documentation"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:48 #: lib/block_scout_web/templates/address_contract/index.html.eex:58
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:82 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:82
msgid "EVM Version" msgid "EVM Version"
msgstr "" msgstr ""
@ -587,7 +598,8 @@ msgid "Emission Reward"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:124 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:124
msgid "Enter the Solidity Contract Code" msgid "Enter the Solidity Contract Code"
msgstr "" msgstr ""
@ -659,18 +671,18 @@ msgid "Nonce"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:151 #: lib/block_scout_web/templates/address_contract/index.html.eex:184
msgid "External libraries" msgid "External libraries"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:32 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:39
msgid "Failed to decode input data." msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:34 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:41
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:35 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
@ -753,7 +765,7 @@ msgid "However, in general, the"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:25
msgid "IMPORTANT: This information is a best guess based on similar functions from other verified contracts." msgid "IMPORTANT: This information is a best guess based on similar functions from other verified contracts."
msgstr "" msgstr ""
@ -911,7 +923,7 @@ msgid "Total Difficulty"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:18 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:25
#: lib/block_scout_web/views/transaction_view.ex:354 #: lib/block_scout_web/views/transaction_view.ex:354
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -964,30 +976,22 @@ msgid "Less than"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:185 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:207 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:185
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:229 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:207
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:251 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:229
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:273 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:251
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:295 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:273
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:317
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:339
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:361
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:383
msgid "Library Address" msgid "Library Address"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:175 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:197 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:175
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:219 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:197
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:241 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:219
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:263 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:241
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:285 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:263
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:307
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:329
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:351
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:373
msgid "Library Name" msgid "Library Name"
msgstr "" msgstr ""
@ -1016,7 +1020,9 @@ msgid "Loading..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:409 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:69
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:299
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:44
msgid "Loading...." msgid "Loading...."
msgstr "" msgstr ""
@ -1090,14 +1096,17 @@ msgid "Name"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:18 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:9
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:18
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:9
msgid "New Smart Contract Verification" msgid "New Smart Contract Verification"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:55 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:98 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:55
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:141 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:98
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:141
#: lib/block_scout_web/templates/stakes/_rows.html.eex:24 #: lib/block_scout_web/templates/stakes/_rows.html.eex:24
msgid "No" msgid "No"
msgstr "" msgstr ""
@ -1109,13 +1118,13 @@ msgid "OUT"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:33 #: lib/block_scout_web/templates/address_contract/index.html.eex:43
msgid "Optimization enabled" msgid "Optimization enabled"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:42 #: lib/block_scout_web/templates/address_contract/index.html.eex:52
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:114 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:114
msgid "Optimization runs" msgid "Optimization runs"
msgstr "" msgstr ""
@ -1166,7 +1175,7 @@ msgid "Pending Transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:17 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:24
msgid "Potential matches from our contract method database:" msgid "Potential matches from our contract method database:"
msgstr "" msgstr ""
@ -1184,7 +1193,7 @@ msgid "QR Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:82 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:89
msgid "Query" msgid "Query"
msgstr "" msgstr ""
@ -1217,7 +1226,9 @@ msgid "Request URL"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:412 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:302
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:47
msgid "Reset" msgid "Reset"
msgstr "" msgstr ""
@ -1425,7 +1436,7 @@ msgid "This is useful to allow sending requests to blockscout without having to
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:19 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:26
msgid "To have guaranteed accuracy, use the link above to verify the contract's source code." msgid "To have guaranteed accuracy, use the link above to verify the contract's source code."
msgstr "" msgstr ""
@ -1442,8 +1453,8 @@ msgid "Topic"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:70 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:77
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:73 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:80
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -1568,22 +1579,24 @@ msgid "Value"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
#: lib/block_scout_web/templates/address_contract/index.html.eex:125 #: lib/block_scout_web/templates/address_contract/index.html.eex:151
#: lib/block_scout_web/templates/address_contract/index.html.eex:130 #: lib/block_scout_web/templates/address_contract/index.html.eex:163
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:12 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:19
msgid "Verify & Publish" msgid "Verify & Publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:411 #:
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:301
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:46
msgid "Verify & publish" msgid "Verify & publish"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:9 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:9 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
@ -1635,7 +1648,7 @@ msgid "View transaction %{transaction} on %{subnetwork}"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:112 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:119
msgid "WEI" msgid "WEI"
msgstr "" msgstr ""
@ -1650,9 +1663,10 @@ msgid "Wei"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:60 #:
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:103 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:60
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:146 #: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:103
#: lib/block_scout_web/templates/address_contract_verification_via_flattened_code/new.html.eex:146
#: lib/block_scout_web/templates/stakes/_rows.html.eex:24 #: lib/block_scout_web/templates/stakes/_rows.html.eex:24
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
@ -1673,9 +1687,9 @@ msgid "false"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:9 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:16
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:9 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:16
msgid "here" msgid "here"
msgstr "" msgstr ""
@ -1761,7 +1775,7 @@ msgid "Loading chart"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:120
msgid "Log Index" msgid "Log Index"
msgstr "" msgstr ""
@ -1924,7 +1938,7 @@ msgid "Waiting for transaction's confirmation..."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:82 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:89
msgid "Write" msgid "Write"
msgstr "" msgstr ""
@ -1950,22 +1964,22 @@ msgid "Search by address, token symbol, name, transaction hash, or block number"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:11 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:18
msgid "All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with" msgid "All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
msgid "All metadata displayed below is from that contract. In order to verify current contract, click" msgid "All metadata displayed below is from that contract. In order to verify current contract, click"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:20 #: lib/block_scout_web/templates/address_contract/index.html.eex:22
msgid "button" msgid "button"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:14 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:21
msgid "page" msgid "page"
msgstr "" msgstr ""
@ -1976,8 +1990,8 @@ msgid "Play"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:111 #: lib/block_scout_web/templates/address_contract/index.html.eex:137
#: lib/block_scout_web/templates/address_contract/index.html.eex:121 #: lib/block_scout_web/templates/address_contract/index.html.eex:147
msgid "Copy Byte Code" msgid "Copy Byte Code"
msgstr "" msgstr ""
@ -2597,8 +2611,8 @@ msgid "Stakes"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:18 #: lib/block_scout_web/templates/address_contract/index.html.eex:20
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:9 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:16
msgid "Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB" msgid "Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB"
msgstr "" msgstr ""
@ -2754,3 +2768,36 @@ msgstr ""
#: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:16 #: lib/block_scout_web/templates/stakes/_stakes_modal_become_candidate.html.eex:16
msgid "Your Pool Short Description (optional)" msgid "Your Pool Short Description (optional)"
msgstr "" msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:26
msgid "Drop sources and metadata JSON file or click here"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:35
msgid "Flattened source code"
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:79
msgid "Next"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/address_contract_verification_via_json/new.html.eex:23
msgid "Sources and Metadata JSON"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "Sources and metadata JSON file"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_contract/index.html.eex:31
msgid "This contract has been verified via Sourcify."
msgstr ""

@ -6,7 +6,7 @@ defmodule BlockScoutWeb.ContractVerifyPage do
import Wallaby.Query import Wallaby.Query
def visit_page(session, address_hash) do def visit_page(session, address_hash) do
visit(session, "/address/#{address_hash}/contract_verifications/new") visit(session, "/address/#{address_hash}/verify-via-flattened-code/new")
end end
def fill_form(session, %{ def fill_form(session, %{

@ -241,6 +241,12 @@ config :explorer, Explorer.Chain.Cache.Uncles,
ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false), ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false),
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))
config :explorer, Explorer.ThirdPartyIntegrations.Sourcify,
server_url: System.get_env("SOURCIFY_SERVER_URL") || "https://verification.komputing.org/server",
enabled: System.get_env("ENABLE_SOURCIFY_INTEGRATION") == "true",
chain_id: System.get_env("CHAIN_ID"),
repo_url: System.get_env("SOURCIFY_REPO_URL") || "https://contractrepo.komputing.org/contracts/full_match/"
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs" import_config "#{Mix.env()}.exs"

@ -53,6 +53,7 @@ defmodule Explorer.Chain do
Log, Log,
PendingBlockOperation, PendingBlockOperation,
SmartContract, SmartContract,
SmartContractAdditionalSource,
StakingPool, StakingPool,
StakingPoolsDelegator, StakingPoolsDelegator,
Token, Token,
@ -1315,7 +1316,12 @@ defmodule Explorer.Chain do
options \\ [], options \\ [],
query_decompiled_code_flag \\ false query_decompiled_code_flag \\ false
) do ) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) necessity_by_association =
options
|> Keyword.get(:necessity_by_association, %{})
|> Map.merge(%{
smart_contract_additional_sources: :optional
})
query = query =
from( from(
@ -3364,7 +3370,7 @@ defmodule Explorer.Chain do
naming the address for reference. naming the address for reference.
""" """
@spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()} @spec create_smart_contract(map()) :: {:ok, SmartContract.t()} | {:error, Ecto.Changeset.t()}
def create_smart_contract(attrs \\ %{}, external_libraries \\ []) do def create_smart_contract(attrs \\ %{}, external_libraries \\ [], secondary_sources \\ []) do
new_contract = %SmartContract{} new_contract = %SmartContract{}
smart_contract_changeset = smart_contract_changeset =
@ -3372,10 +3378,23 @@ defmodule Explorer.Chain do
|> SmartContract.changeset(attrs) |> SmartContract.changeset(attrs)
|> Changeset.put_change(:external_libraries, external_libraries) |> Changeset.put_change(:external_libraries, external_libraries)
new_contract_additional_source = %SmartContractAdditionalSource{}
smart_contract_additional_sources_changesets =
if secondary_sources do
secondary_sources
|> Enum.map(fn changeset ->
new_contract_additional_source
|> SmartContractAdditionalSource.changeset(changeset)
end)
else
[]
end
address_hash = Changeset.get_field(smart_contract_changeset, :address_hash) address_hash = Changeset.get_field(smart_contract_changeset, :address_hash)
# Enforce ShareLocks tables order (see docs: sharelocks.md) # Enforce ShareLocks tables order (see docs: sharelocks.md)
insert_result = insert_contract_query =
Multi.new() Multi.new()
|> Multi.run(:set_address_verified, fn repo, _ -> set_address_verified(repo, address_hash) end) |> Multi.run(:set_address_verified, fn repo, _ -> set_address_verified(repo, address_hash) end)
|> Multi.run(:clear_primary_address_names, fn repo, _ -> clear_primary_address_names(repo, address_hash) end) |> Multi.run(:clear_primary_address_names, fn repo, _ -> clear_primary_address_names(repo, address_hash) end)
@ -3384,6 +3403,16 @@ defmodule Explorer.Chain do
create_address_name(repo, name, address_hash) create_address_name(repo, name, address_hash)
end) end)
|> Multi.insert(:smart_contract, smart_contract_changeset) |> Multi.insert(:smart_contract, smart_contract_changeset)
insert_contract_query_with_additional_sources =
smart_contract_additional_sources_changesets
|> Enum.with_index()
|> Enum.reduce(insert_contract_query, fn {changeset, index}, multi ->
Multi.insert(multi, "smart_contract_additional_source_#{Integer.to_string(index)}", changeset)
end)
insert_result =
insert_contract_query_with_additional_sources
|> Repo.transaction() |> Repo.transaction()
case insert_result do case insert_result do
@ -3503,7 +3532,7 @@ defmodule Explorer.Chain do
def get_address_verified_twin_contract(address_hash) do def get_address_verified_twin_contract(address_hash) do
case Repo.get(Address, address_hash) do case Repo.get(Address, address_hash) do
nil -> nil ->
%{:verified_contract => nil} %{:verified_contract => nil, :additional_sources => nil}
target_address -> target_address ->
target_address_hash = target_address.hash target_address_hash = target_address.hash
@ -3531,12 +3560,15 @@ defmodule Explorer.Chain do
verified_contract_twin_query verified_contract_twin_query
|> Repo.one(timeout: 10_000) |> Repo.one(timeout: 10_000)
verified_contract_twin_additional_sources = get_contract_additional_sources(verified_contract_twin)
%{ %{
:verified_contract => verified_contract_twin :verified_contract => verified_contract_twin,
:additional_sources => verified_contract_twin_additional_sources
} }
_ -> _ ->
%{:verified_contract => nil} %{:verified_contract => nil, :additional_sources => nil}
end end
end end
end end
@ -3587,6 +3619,21 @@ defmodule Explorer.Chain do
end end
end end
defp get_contract_additional_sources(verified_contract_twin) do
if verified_contract_twin do
verified_contract_twin_additional_sources_query =
from(
s in SmartContractAdditionalSource,
where: s.address_hash == ^verified_contract_twin.address_hash
)
verified_contract_twin_additional_sources_query
|> Repo.all()
else
[]
end
end
@spec address_hash_to_smart_contract(Hash.Address.t()) :: SmartContract.t() | nil @spec address_hash_to_smart_contract(Hash.Address.t()) :: SmartContract.t() | nil
def address_hash_to_smart_contract(address_hash) do def address_hash_to_smart_contract(address_hash) do
query = query =
@ -3612,6 +3659,16 @@ defmodule Explorer.Chain do
end end
end end
def smart_contract_verified?(address_hash) do
query =
from(
smart_contract in SmartContract,
where: smart_contract.address_hash == ^address_hash
)
if Repo.one(query), do: true, else: false
end
defp fetch_transactions(paging_options \\ nil) do defp fetch_transactions(paging_options \\ nil) do
Transaction Transaction
|> order_by([transaction], desc: transaction.block_number, desc: transaction.index) |> order_by([transaction], desc: transaction.block_number, desc: transaction.index)

@ -17,6 +17,7 @@ defmodule Explorer.Chain.Address do
Hash, Hash,
InternalTransaction, InternalTransaction,
SmartContract, SmartContract,
SmartContractAdditionalSource,
Token, Token,
Transaction, Transaction,
Wei Wei
@ -110,6 +111,7 @@ defmodule Explorer.Chain.Address do
has_many(:names, Address.Name, foreign_key: :address_hash) has_many(:names, Address.Name, foreign_key: :address_hash)
has_many(:decompiled_smart_contracts, DecompiledSmartContract, foreign_key: :address_hash) has_many(:decompiled_smart_contracts, DecompiledSmartContract, foreign_key: :address_hash)
has_many(:smart_contract_additional_sources, SmartContractAdditionalSource, foreign_key: :address_hash)
timestamps() timestamps()
end end

@ -192,6 +192,7 @@ defmodule Explorer.Chain.SmartContract do
produce `address` `t:Explorer.Chain.Address.t/0` `contract_code`. produce `address` `t:Explorer.Chain.Address.t/0` `contract_code`.
* `abi` - The [JSON ABI specification](https://solidity.readthedocs.io/en/develop/abi-spec.html#json) for this * `abi` - The [JSON ABI specification](https://solidity.readthedocs.io/en/develop/abi-spec.html#json) for this
contract. contract.
* `verified_via_sourcify` - whether contract verified through Sourcify utility or not.
""" """
@type t :: %Explorer.Chain.SmartContract{ @type t :: %Explorer.Chain.SmartContract{
@ -202,7 +203,8 @@ defmodule Explorer.Chain.SmartContract do
constructor_arguments: String.t() | nil, constructor_arguments: String.t() | nil,
evm_version: String.t() | nil, evm_version: String.t() | nil,
optimization_runs: non_neg_integer() | nil, optimization_runs: non_neg_integer() | nil,
abi: [function_description] abi: [function_description],
verified_via_sourcify: boolean | nil
} }
schema "smart_contracts" do schema "smart_contracts" do
@ -215,6 +217,7 @@ defmodule Explorer.Chain.SmartContract do
field(:optimization_runs, :integer) field(:optimization_runs, :integer)
embeds_many(:external_libraries, ExternalLibrary) embeds_many(:external_libraries, ExternalLibrary)
field(:abi, {:array, :map}) field(:abi, {:array, :map})
field(:verified_via_sourcify, :boolean)
has_many( has_many(
:decompiled_smart_contracts, :decompiled_smart_contracts,
@ -248,7 +251,8 @@ defmodule Explorer.Chain.SmartContract do
:abi, :abi,
:constructor_arguments, :constructor_arguments,
:evm_version, :evm_version,
:optimization_runs :optimization_runs,
:verified_via_sourcify
]) ])
|> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash]) |> validate_required([:name, :compiler_version, :optimization, :contract_source_code, :abi, :address_hash])
|> unique_constraint(:address_hash) |> unique_constraint(:address_hash)
@ -266,7 +270,8 @@ defmodule Explorer.Chain.SmartContract do
:address_hash, :address_hash,
:evm_version, :evm_version,
:optimization_runs, :optimization_runs,
:constructor_arguments :constructor_arguments,
:verified_via_sourcify
]) ])
|> validate_required([:name, :compiler_version, :optimization, :address_hash]) |> validate_required([:name, :compiler_version, :optimization, :address_hash])

@ -0,0 +1,63 @@
defmodule Explorer.Chain.SmartContractAdditionalSource do
@moduledoc """
The representation of a verified Smart Contract additional sources.
It is used when contract is verified with Sourcify utility.
"""
require Logger
use Explorer.Schema
alias Explorer.Chain.{Hash, SmartContract}
@typedoc """
* `file_name` - the name of the Solidity file with contract code (with extension).
* `contract_source_code` - the Solidity source code from the file with `file_name`.
"""
@type t :: %Explorer.Chain.SmartContractAdditionalSource{
file_name: String.t(),
contract_source_code: String.t()
}
schema "smart_contracts_additional_sources" do
field(:file_name, :string)
field(:contract_source_code, :string)
belongs_to(
:smart_contract,
SmartContract,
foreign_key: :address_hash,
references: :address_hash,
type: Hash.Address
)
timestamps()
end
def changeset(%__MODULE__{} = smart_contract_additional_source, attrs) do
smart_contract_additional_source
|> cast(attrs, [
:file_name,
:contract_source_code,
:address_hash
])
|> validate_required([:file_name, :contract_source_code, :address_hash])
|> unique_constraint(:address_hash)
end
def invalid_contract_changeset(%__MODULE__{} = smart_contract_additional_source, attrs, error) do
validated =
smart_contract_additional_source
|> cast(attrs, [
:file_name,
:contract_source_code,
:address_hash
])
|> validate_required([:file_name, :address_hash])
add_error(validated, :contract_source_code, error_message(error))
end
defp error_message(_), do: "There was an error validating your contract, please try again."
end

@ -45,10 +45,10 @@ defmodule Explorer.SmartContract.Publisher do
end end
end end
defp publish_smart_contract(address_hash, params, abi) do def publish_smart_contract(address_hash, params, abi) do
attrs = address_hash |> attributes(params, abi) attrs = address_hash |> attributes(params, abi)
Chain.create_smart_contract(attrs, attrs.external_libraries) Chain.create_smart_contract(attrs, attrs.external_libraries, attrs.secondary_sources)
end end
defp unverified_smart_contract(address_hash, params, error, error_message) do defp unverified_smart_contract(address_hash, params, error, error_message) do
@ -89,7 +89,9 @@ defmodule Explorer.SmartContract.Publisher do
contract_source_code: params["contract_source_code"], contract_source_code: params["contract_source_code"],
constructor_arguments: clean_constructor_arguments, constructor_arguments: clean_constructor_arguments,
external_libraries: prepared_external_libraries, external_libraries: prepared_external_libraries,
abi: abi secondary_sources: params["secondary_sources"],
abi: abi,
verified_via_sourcify: params["verified_via_sourcify"]
} }
end end

@ -0,0 +1,184 @@
defmodule Explorer.ThirdPartyIntegrations.Sourcify do
@moduledoc """
Adapter for contracts verification with https://sourcify.dev/
"""
use Tesla
alias HTTPoison.{Error, Response}
alias Tesla.Multipart
def check_by_address(address_hash_string) do
chain_id = config(:chain_id)
params = [addresses: address_hash_string, chainIds: chain_id]
http_get_request(check_by_address_url(), params)
end
def get_metadata(address_hash_string) do
get_metadata_full_url = get_metadata_url() <> "/" <> address_hash_string
http_get_request(get_metadata_full_url, [])
end
def verify(address_hash_string, files) do
chain_id = config(:chain_id)
multipart_text_params =
Multipart.new()
|> Multipart.add_field("chain", chain_id)
|> Multipart.add_field("address", address_hash_string)
multipart_body =
files
|> Enum.reduce(multipart_text_params, fn file, acc ->
if file do
acc
|> Multipart.add_file(file.path,
name: "files",
file_name: Path.basename(file.path)
)
else
acc
end
end)
http_post_request(verify_url(), multipart_body)
end
def http_get_request(url, params) do
request = HTTPoison.get(url, [], params: params)
case request do
{:ok, %Response{body: body, status_code: 200}} ->
process_sourcify_response(url, body)
{:ok, %Response{body: body, status_code: status_code}} when status_code in 400..526 ->
parse_http_error_response(body)
{:ok, %Response{status_code: status_code}} when status_code in 300..308 ->
{:error, "Sourcify redirected"}
{:ok, %Response{status_code: _status_code}} ->
{:error, "Sourcify unexpected status code"}
{:error, %Error{reason: reason}} ->
{:error, reason}
{:error, :nxdomain} ->
{:error, "Sourcify is not responsive"}
{:error, _} ->
{:error, "Unexpected response from Sourcify"}
end
end
def http_post_request(url, body) do
request = Tesla.post(url, body)
case request do
{:ok, %Tesla.Env{body: body}} ->
process_sourcify_response(url, body)
_ ->
{:error, "Unexpected response from Sourcify verify method"}
end
end
defp process_sourcify_response(url, body) do
cond do
url =~ "checkByAddresses" ->
parse_check_by_address_http_response(body)
url =~ "/verify" ->
parse_verify_http_response(body)
url =~ "/files/" ->
parse_get_metadata_http_response(body)
true ->
{:error, body}
end
end
defp parse_verify_http_response(body) do
body_json = decode_json(body)
case body_json do
%{"result" => [%{"status" => "perfect"}]} ->
{:ok, body_json}
%{"result" => [%{"status" => unknown_status}]} ->
{:error, unknown_status}
body ->
{:error, body}
end
end
defp parse_check_by_address_http_response(body) do
body_json = decode_json(body)
case body_json do
[%{"status" => "perfect"}] ->
{:ok, body_json}
[%{"status" => "false"}] ->
{:error, "Contract is not verified"}
[%{"status" => unknown_status}] ->
{:error, unknown_status}
body ->
{:error, body}
end
end
defp parse_get_metadata_http_response(body) do
body_json = decode_json(body)
case body_json do
%{"message" => message, "errors" => errors} ->
{:error, "#{message}: #{decode_json(errors)}"}
metadata ->
{:ok, metadata}
end
end
defp parse_http_error_response(body) do
body_json = decode_json(body)
if is_map(body_json) do
{:error, body_json["error"]}
else
{:error, body}
end
end
def decode_json(data) do
Jason.decode!(data)
rescue
_ -> data
end
defp config(key) do
:explorer
|> Application.get_env(__MODULE__)
|> Keyword.get(key)
end
defp base_server_url do
config(:server_url)
end
defp verify_url do
"#{base_server_url()}" <> "/verify"
end
defp check_by_address_url do
"#{base_server_url()}" <> "/checkByAddresses"
end
defp get_metadata_url do
chain_id = config(:chain_id)
"#{base_server_url()}" <> "/files/" <> chain_id
end
end

@ -47,7 +47,8 @@ defmodule Explorer.Mixfile do
do: [ do: [
:logger, :logger,
:mix, :mix,
:runtime_tools :runtime_tools,
:tesla
] ]
# Specifies your project dependencies. # Specifies your project dependencies.
@ -106,7 +107,8 @@ defmodule Explorer.Mixfile do
{:telemetry, "~> 0.4.1"}, {:telemetry, "~> 0.4.1"},
# `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0` # `Timex.Duration` for `Explorer.Counters.AverageBlockTime.average_block_time/0`
{:timex, "~> 3.6"}, {:timex, "~> 3.6"},
{:con_cache, "~> 0.13"} {:con_cache, "~> 0.13"},
{:tesla, "~> 1.3.3"}
] ]
end end

@ -0,0 +1,22 @@
defmodule Explorer.Repo.Migrations.SupportSourcify do
use Ecto.Migration
def change do
alter table(:smart_contracts) do
add(:verified_via_sourcify, :boolean, null: true)
end
create table(:smart_contracts_additional_sources) do
add(:file_name, :string, null: false)
add(:contract_source_code, :text, null: false)
add(:address_hash, references(:smart_contracts, column: :address_hash, on_delete: :delete_all, type: :bytea),
null: false
)
timestamps()
end
create(index(:smart_contracts_additional_sources, :address_hash))
end
end

@ -3229,7 +3229,12 @@ defmodule Explorer.ChainTest do
test "finds a contract address" do test "finds a contract address" do
address = address =
insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil, names: []) insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil, names: [])
|> Repo.preload([:contracts_creation_internal_transaction, :contracts_creation_transaction, :token]) |> Repo.preload([
:contracts_creation_internal_transaction,
:contracts_creation_transaction,
:token,
:smart_contract_additional_sources
])
options = [ options = [
necessity_by_association: %{ necessity_by_association: %{

@ -68,6 +68,7 @@ defmodule BlockScout.Mixfile do
defp deps do defp deps do
[ [
{:absinthe_plug, git: "https://github.com/blockscout/absinthe_plug.git", tag: "1.5.3", override: true}, {:absinthe_plug, git: "https://github.com/blockscout/absinthe_plug.git", tag: "1.5.3", override: true},
{:tesla, "~> 1.3.3"},
# Documentation # Documentation
{:ex_doc, "~> 0.19.0", only: [:dev]}, {:ex_doc, "~> 0.19.0", only: [:dev]},
{:number, "~> 1.0.3"} {:number, "~> 1.0.3"}

Loading…
Cancel
Save