Merge branch 'master' into ab-check-if-contract-has-arguments

pull/1898/head
Ayrat Badykov 6 years ago committed by GitHub
commit b2cc0ebacc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      CHANGELOG.md
  2. 2
      README.md
  3. 53
      apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
  4. 55
      apps/block_scout_web/assets/css/theme/_poa_variables.scss
  5. 41
      apps/block_scout_web/assets/static/images/ethereum_logo.svg
  6. 4
      apps/block_scout_web/assets/static/images/poa_logo.svg
  7. 17
      apps/block_scout_web/lib/block_scout_web/chain.ex
  8. 57
      apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
  9. 29
      apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex
  10. 5
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  11. 44
      apps/block_scout_web/priv/gettext/default.pot
  12. 44
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  13. 1
      apps/explorer/.gitignore
  14. 1
      apps/explorer/lib/explorer/application.ex
  15. 22
      apps/explorer/lib/explorer/chain.ex
  16. 92
      apps/explorer/lib/explorer/smart_contract/solc_downloader.ex
  17. 57
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  18. 64
      apps/explorer/priv/compile_solc.js
  19. 27
      apps/explorer/test/explorer/chain_test.exs

@ -2,6 +2,9 @@
### Features
- [#1895](https://github.com/poanetwork/blockscout/pull/1874) - add changes to poa theme and poa logo
- [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page
- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo
- [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x"
- [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page
- [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request
@ -18,6 +21,8 @@
- [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth
- [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance
- [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view
- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete
- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance
### Chore

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

@ -1,3 +1,50 @@
$primary: #16465b;
$secondary: #5ab3ff;
$tertiary: #77a4c5;
// general
$primary: #153550;
$secondary: #49a2ee;
$tertiary: #4ad7a7;
$additional-font: #89cae6;
// footer
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #89cae6;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #1c476c; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $secondary; // top border on hover
$header-icon-color-hover: $secondary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
//links & tile
.tile a { color: $secondary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $secondary;
} // tab active bg
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;

@ -1,11 +1,50 @@
$primary: #5b389f;
$secondary: #7dd79f;
$tertiary: #997fdc;
// general
$primary: #5c34a2;
$secondary: #87e1a9;
$tertiary: #bf9cff;
$additional-font: #fff;
$header-links-color-active: #333;
$button-secondary-color: $primary;
$footer-background-color: $primary;
// footer
$footer-background-color: #3c226a;
$footer-title-color: #fff;
$footer-text-color: #fff;
$footer-text-color: #bda6e7;
$footer-item-disc-color: $secondary;
.footer-logo { filter: brightness(0) invert(1); }
// dashboard
$dashboard-line-color-price: $tertiary; // price left border
$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels
$dashboard-stats-item-value-color: $additional-font; // stat values
$dashboard-stats-item-border-color: $secondary; // stat border
$dashboard-banner-gradient-start: $primary; // gradient begin
$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end
$dashboard-banner-network-plain-container-background-color: #865bd4; // stats bg
// navigation
.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow
$header-icon-border-color-hover: $primary; // top border on hover
$header-icon-color-hover: $primary; // nav icon on hover
.dropdown-item:hover, .dropdown-item:focus { background-color: $primary !important; } // dropdown item on hover
// buttons
$btn-line-bg: #fff; // button bg
$btn-line-color: $primary; // button border and font color && hover bg color
$btn-copy-color: $primary; // btn copy
$btn-qr-color: $primary; // btn qr-code
//links & tile
.tile a { color: $primary !important; } // links color for badges
.tile-type-block {
border-left: 4px solid $primary;
} // tab active bg
// card
$card-background-1: $primary;
$card-tab-active: $primary;

@ -1,40 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 532.5 106" style="enable-background:new 0 0 532.5 106;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<title>ethereum-logo</title>
<g>
<path class="st0" d="M121.6,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1H110v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C131,71,126.9,73.1,121.6,73.1z M120.9,40.7
c-2.9,0-5.3,1-7.2,3.1c-2,2.1-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C126.1,41.7,123.8,40.7,120.9,40.7z"/>
<path class="st0" d="M164.6,29.3v8.8h7.1v3.1h-7.1v22.9c0,1.9,0.3,3.3,1,4.3c0.7,0.9,1.8,1.4,3.4,1.4c0.6,0,1.7-0.1,3.1-0.3
l0.2,3.1c-1,0.4-2.3,0.5-4.1,0.5c-2.6,0-4.5-0.8-5.7-2.3c-1.2-1.5-1.8-3.7-1.8-6.7V41.2h-6.3v-3.1h6.3v-8.8H164.6z"/>
<path class="st0" d="M200.2,43.9c1.2-2.1,2.8-3.6,4.8-4.8c1.9-1.1,4.1-1.7,6.4-1.7c3.7,0,6.4,1,8.2,3.1c1.8,2.1,2.7,5.2,2.7,9.3
v22.5h-3.8V49.9c0-3.1-0.7-5.4-2-6.9c-1.3-1.5-3.3-2.3-6.1-2.3c-2.3,0-4.4,0.7-6.2,2.2c-1.8,1.5-3.1,3.5-4,6v23.5h-3.8V23.7h3.8
V43.9z"/>
<path class="st0" d="M262.3,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1h-24.5v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C271.6,71,267.6,73.1,262.3,73.1z M261.6,40.7
c-2.9,0-5.3,1-7.2,3.1c-2,2.1-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C266.8,41.7,264.4,40.7,261.6,40.7z"/>
<path class="st0" d="M315.2,41.3c-0.8-0.1-1.7-0.2-2.6-0.2c-2.4,0-4.4,0.7-6,2s-2.8,3.2-3.5,5.8v23.6h-3.8V38.1h3.7l0.1,5.5
c2-4.1,5.2-6.1,9.7-6.1c1.1,0,1.9,0.1,2.5,0.4L315.2,41.3z"/>
<path class="st0" d="M350.8,73.1c-2.9,0-5.6-0.7-7.9-2.2c-2.4-1.4-4.2-3.4-5.5-6c-1.3-2.6-2-5.5-2-8.6v-1.4c0-3.3,0.6-6.3,1.9-8.9
c1.3-2.6,3.1-4.7,5.3-6.2s4.8-2.3,7.4-2.3c4.2,0,7.5,1.4,9.9,4.3c2.4,2.8,3.7,6.7,3.7,11.7v2.1h-24.5v0.7c0,3.9,1.1,7.1,3.3,9.7
c2.2,2.6,5,3.9,8.4,3.9c2,0,3.8-0.4,5.4-1.1c1.6-0.7,3-1.9,4.2-3.6l2.4,1.8C360.1,71,356.1,73.1,350.8,73.1z M350.1,40.7
c-2.9,0-5.3,1-7.2,3.1s-3.1,4.9-3.6,8.4h20.6v-0.4c-0.1-3.3-1-6-2.8-8.1C355.3,41.7,353,40.7,350.1,40.7z"/>
<path class="st0" d="M410,68.1c-2.3,3.3-5.9,5-10.9,5c-3.7,0-6.4-1.1-8.3-3.2s-2.9-5.3-2.9-9.4V38.1h3.8v21.9
c0,6.5,2.6,9.8,7.9,9.8c5.5,0,9-2.3,10.4-6.8V38.1h3.8v34.3H410L410,68.1z"/>
<path class="st0" d="M443.9,38.1l0.1,5.6c1.3-2.1,2.9-3.6,4.8-4.7c1.9-1,4-1.6,6.3-1.6c5.4,0,8.9,2.2,10.3,6.7
c1.2-2.1,2.9-3.8,4.9-4.9c2.1-1.2,4.3-1.7,6.8-1.7c7.4,0,11.1,4,11.3,12.1v22.9h-3.8V49.8c0-3.1-0.7-5.3-2-6.8
c-1.3-1.5-3.4-2.2-6.4-2.2c-2.7,0-5,0.9-6.9,2.7c-1.9,1.7-2.9,3.8-3.1,6.3v22.7h-3.8V49.5c0-2.9-0.7-5.1-2.1-6.6
c-1.4-1.4-3.5-2.2-6.3-2.2c-2.4,0-4.4,0.7-6.2,2c-1.7,1.4-3,3.4-3.8,6.1v23.5h-3.8V38.1H443.9z"/>
</g>
<path class="st0" d="M57.5,17.7l21.7,36c-7,4.2-13.9,8.3-20.9,12.3c-0.6,0.2-1.3,0.2-1.8-0.1c-6.9-4-13.7-8-20.7-12.2
C43.1,41.7,50.2,29.8,57.5,17.7z"/>
<path class="st0" d="M78.1,58.9L57.2,88.3L36.3,58.9l0.4-0.4c1.7,1,3.4,2,5.1,3c4.5,2.6,9,5.2,13.4,7.9c1.2,0.9,2.9,1,4.1,0
c5.4-3.3,10.9-6.5,16.4-9.7c0.7-0.4,1.4-0.8,2.2-1.2L78.1,58.9z"/>
</svg>
<svg data-name="-e-eth_logo_top" xmlns="http://www.w3.org/2000/svg" width="106.094" height="30"><g data-name="1" fill-rule="evenodd"><path data-name="Фигура 1" d="M9 11.2l-9 4.4L9 0v11.2z" fill="#828083"/><path data-name="Фигура 1 копия" d="M9 10.783L0 15.2l9 5.215v-9.632z" fill="#353336"/><path data-name="Фигура 1 копия 2" d="M9 22.568l-9-5.78L9 30v-7.432z" fill="#848285"/><path data-name="Фигура 1 копия 3" d="M9 11.2l9 4.4L9 0v11.2z" fill="#2f2d30"/><path data-name="Фигура 1 копия 3" d="M9 10.783l9 4.412-9 5.215v-9.627z" fill="#121212"/><path data-name="Фигура 1 копия 3" d="M9 22.568l9-5.78L9 30v-7.432z" fill="#302e31"/></g><path d="M29.675 13.329a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.351.351 0 0 0-.289.165 3.239 3.239 0 0 1-2.77 1.395 2.9 2.9 0 0 1-2.168-.922 3.555 3.555 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.532-.013zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.6 3.6 0 0 1 1.012-2.215zm11.2-4.046a.336.336 0 1 0-.672 0v2.613h-1.728a.35.35 0 0 0 0 .7h1.728v7.01a.336.336 0 0 0 .672 0v-7.01h1.8a.35.35 0 0 0 0-.7h-1.8V9.66zm5.664 4.173V5.889a.336.336 0 1 0-.672 0v14.04a.336.336 0 0 0 .672 0v-3.492a3.921 3.921 0 0 1 .6-2.512 2.52 2.52 0 0 1 2.222-1.124 2.113 2.113 0 0 1 1.792.909 3.075 3.075 0 0 1 .621 1.962v4.258a.336.336 0 0 0 .672 0v-4.273a3.766 3.766 0 0 0-.816-2.448 2.755 2.755 0 0 0-2.28-1.1 3.047 3.047 0 0 0-2.808 1.728zm10.08-.5a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.35.35 0 0 0-.289.165 3.24 3.24 0 0 1-2.771 1.395 2.9 2.9 0 0 1-2.167-.922 3.549 3.549 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.531-.017zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.592 3.592 0 0 1 1.016-2.219zm11.108-.888a4.025 4.025 0 0 0-1.176 1.255V12.6a.336.336 0 0 0-.672 0v7.3a.336.336 0 0 0 .672 0v-3.2a4.148 4.148 0 0 1 .7-2.464 2.951 2.951 0 0 1 2.16-1.292.329.329 0 0 0 .312-.359.3.3 0 0 0-.36-.311 2.919 2.919 0 0 0-1.632.545zm5.16.511a4.417 4.417 0 0 0 .012 5.856 3.867 3.867 0 0 0 6.084-.5.332.332 0 0 0-.289-.5.353.353 0 0 0-.29.165 3.237 3.237 0 0 1-2.77 1.395 2.9 2.9 0 0 1-2.167-.922 3.549 3.549 0 0 1-1.012-2.2h6.719a.309.309 0 0 0 .361-.338 4.287 4.287 0 0 0-1.116-2.943 3.683 3.683 0 0 0-5.528-.017zm.58.377a2.994 2.994 0 0 1 4.336 0 3.6 3.6 0 0 1 1.012 2.215h-6.36a3.592 3.592 0 0 1 1.016-2.219zm15.044-1.1v2.736q0 4.44-2.785 4.44a2.144 2.144 0 0 1-1.823-.912 3.159 3.159 0 0 1-.6-1.968v-4.3a.336.336 0 1 0-.672 0v4.308a3.779 3.779 0 0 0 .817 2.455 2.747 2.747 0 0 0 2.279 1.107 2.983 2.983 0 0 0 2.785-1.9v1.392a.336.336 0 1 0 .672 0V12.61a.336.336 0 1 0-.672 0zm10.295 1.632a2.8 2.8 0 0 0-2.856-2.136 3.052 3.052 0 0 0-2.808 1.7V12.6a.336.336 0 0 0-.672 0v7.33a.336.336 0 0 0 .672 0v-3.4a4.571 4.571 0 0 1 .6-2.679 2.529 2.529 0 0 1 2.208-1.053 2.146 2.146 0 0 1 1.8.885 3.067 3.067 0 0 1 .624 1.962v4.285a.336.336 0 0 0 .672 0v-3.3a5.018 5.018 0 0 1 .624-2.56 2.4 2.4 0 0 1 2.16-1.268 2.106 2.106 0 0 1 1.8.885 3.067 3.067 0 0 1 .624 1.962v4.281a.336.336 0 0 0 .672 0v-4.3a3.84 3.84 0 0 0-.84-2.484 2.746 2.746 0 0 0-2.256-1.044 3.142 3.142 0 0 0-3.024 2.136z" fill="#1b1635" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -1 +1,3 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 784.802 295.795"><defs><style>.cls-1{fill:#fff;}</style></defs><title>poa_logo</title><path class="cls-1" d="M396.219,268.878c-67.974,3.629-128.341-52.06-131.534-121.338-3.13-67.91,51.1-129.093,117.646-132.732,73.163-4,132.938,49.141,137.089,121.875C523.353,205.623,467.972,265.048,396.219,268.878Z"/><path class="cls-1" d="M11.9,141.308c0-34.343.283-68.69-.17-103.027C11.59,27.8,15.167,23.995,25.764,24.09c44.441.4,88.889-.137,133.33.255,49.985.441,91.942,43.057,93.616,94.385,1.574,48.276-37.962,93.594-85.93,98.278a242.125,242.125,0,0,1-24.193,1.036c-7.854-.023-11.592,2.835-12.116,11.258-1.95,31.322-2.173,31.308-33.906,31.308q-33.333,0-66.666-.008c-17.414-.022-17.988-.582-18-17.477Q11.875,192.216,11.9,141.308Z"/><path class="cls-1" d="M633.094,260.608q-63.645,0-127.289-.025c-15.248-.026-18.476-5.46-10.744-18.3Q559.1,135.943,623.33,29.714c7.883-13.036,13.493-12.908,21.482.331q63.82,105.768,127.5,211.619c8.277,13.763,5.324,18.9-10.719,18.921Q697.345,260.685,633.094,260.608Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="18">
<path fill="#5C34A2" fill-rule="evenodd" d="M10.313 14.437h-.938v2.657h-.003l.003.015c0 .492-.42.891-.938.891h-7.5C.42 18 0 17.601 0 17.109l.003-.015H0V.937h.003L0 .922C0 .43.42.031.937.031h9.376c4.142 0 7.499 3.225 7.499 7.203 0 3.979-3.357 7.203-7.499 7.203zM29.062.031c5.178 0 9.375 4.023 9.375 8.985S34.24 18 29.062 18c-5.177 0-9.374-4.022-9.374-8.984S23.885.031 29.062.031zM60 17.43c0 .307-.26.556-.58.556H38.151c-.025.003-.047.014-.073.014a.57.57 0 0 1-.578-.562c0-.123.048-.23.116-.322l-.009-.018L48.165.449h.023a.566.566 0 0 1 .557-.444c.28 0 .502.192.557.444h.023L60 17.209l-.037.048a.51.51 0 0 1 .037.173z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 694 B

@ -25,7 +25,8 @@ defmodule BlockScoutWeb.Chain do
InternalTransaction,
Log,
TokenTransfer,
Transaction
Transaction,
Wei
}
alias Explorer.PagingOptions
@ -87,6 +88,16 @@ defmodule BlockScoutWeb.Chain do
Map.merge(params, paging_params(List.last(list)))
end
def paging_options(%{"hash" => hash, "fetched_coin_balance" => fetched_coin_balance}) do
with {coin_balance, ""} <- Integer.parse(fetched_coin_balance),
{:ok, address_hash} <- string_to_address_hash(hash) do
[paging_options: %{@default_paging_options | key: {%Wei{value: Decimal.new(coin_balance)}, address_hash}}]
else
_ ->
[paging_options: @default_paging_options]
end
end
def paging_options(%{
"block_number" => block_number_string,
"transaction_index" => transaction_index_string,
@ -177,6 +188,10 @@ defmodule BlockScoutWeb.Chain do
end
end
defp paging_params({%Address{hash: hash, fetched_coin_balance: fetched_coin_balance}, _}) do
%{"hash" => hash, "fetched_coin_balance" => Decimal.to_string(fetched_coin_balance.value)}
end
defp paging_params({%Reward{block: %{number: number}}, _}) do
%{"block_number" => number, "index" => 0}
end

@ -1,16 +1,55 @@
defmodule BlockScoutWeb.AddressController do
use BlockScoutWeb, :controller
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias Explorer.{Chain, Market}
alias Explorer.Chain.Address
alias Explorer.ExchangeRates.Token
def index(conn, _params) do
def index(conn, params) do
addresses =
params
|> paging_options()
|> Chain.list_top_addresses()
{addresses_page, next_page} = split_list_by_page(addresses)
cur_page_number =
cond do
!params["prev_page_number"] -> 1
params["next_page"] -> String.to_integer(params["prev_page_number"]) + 1
params["prev_page"] -> String.to_integer(params["prev_page_number"]) - 1
end
next_page_path =
case next_page_params(next_page, addresses_page, params) do
nil ->
nil
next_page_params ->
next_params =
next_page_params
|> Map.put("prev_page_path", cur_page_path(conn, params))
|> Map.put("next_page", true)
|> Map.put("prev_page_number", cur_page_number)
address_path(
conn,
:index,
next_params
)
end
render(conn, "index.html",
address_tx_count_pairs: Chain.list_top_addresses(),
address_tx_count_pairs: addresses_page,
page_address_count: Enum.count(addresses_page),
address_count: Chain.count_addresses_with_balance_from_cache(),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
total_supply: Chain.total_supply()
total_supply: Chain.total_supply(),
next_page_path: next_page_path,
prev_page_path: params["prev_page_path"],
cur_page_number: cur_page_number
)
end
@ -25,4 +64,16 @@ defmodule BlockScoutWeb.AddressController do
def validation_count(%Address{} = address) do
Chain.address_to_validation_count(address)
end
defp cur_page_path(conn, %{"hash" => _hash, "fetched_coin_balance" => _balance} = params) do
new_params = Map.put(params, "next_page", false)
address_path(
conn,
:index,
new_params
)
end
defp cur_page_path(conn, _), do: address_path(conn, :index)
end

@ -1,12 +1,28 @@
<section class="container">
<div class="card">
<div class="card-body">
<%= if @next_page_path do %>
<a href="<%= "#{@next_page_path}" %>" class="button button-secondary button-small float-right ml-1">
<%= gettext("Next") %>
</a>
<% end %>
<%= if @prev_page_path do %>
<a href="<%= "#{@prev_page_path}" %>" class="button button-secondary button-small float-right">
<%= gettext("Back") %>
</a>
<% end %>
<h1 class="card-title margin-bottom-0"><%= gettext "Addresses" %></h1>
<p class="card-subtitle">
<%= gettext "Showing 250 addresses of" %>
<%= gettext "Showing " %>
<%= Cldr.Number.to_string!(@page_address_count, format: "#,###") %>
<%= gettext " addresses of" %>
<%= Cldr.Number.to_string!(@address_count, format: "#,###") %>
<%= gettext "total addresses with a balance" %>
<%= gettext " (page" %>
<%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %>
</p>
<span data-selector="top-addresses-list">
<%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %>
<%= render "_tile.html",
@ -14,6 +30,17 @@
total_supply: @total_supply, tx_count: tx_count,
validation_count: validation_count(address) %>
<% end %>
<br>
<%= if @next_page_path do %>
<a href="<%= "#{@next_page_path}" %>" class="button button-secondary button-small float-right mt-0 mb-0 ml-1">
<%= gettext("Next") %>
</a>
<% end %>
<%= if @prev_page_path do %>
<a href="<%= "#{@prev_page_path}" %>" class="button button-secondary button-small float-right mt-0 mb-0">
<%= gettext("Back") %>
</a>
<% end %>
</span>
</div>
</div>

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

@ -104,7 +104,7 @@ msgid "Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:4
#: lib/block_scout_web/templates/address/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59
msgid "Addresses"
msgstr ""
@ -578,6 +578,8 @@ msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
#: lib/block_scout_web/templates/address/index.html.eex:36
#: lib/block_scout_web/templates/address_token/index.html.eex:22
msgid "Next"
msgstr ""
@ -712,7 +714,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""
@ -739,11 +741,6 @@ msgstr ""
msgid "Showing"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210
@ -1078,7 +1075,7 @@ msgid "string"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8
#: lib/block_scout_web/templates/address/index.html.eex:21
msgid "total addresses with a balance"
msgstr ""
@ -1708,11 +1705,6 @@ msgstr ""
msgid "ERC-721"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation"
@ -1739,3 +1731,29 @@ msgstr ""
#: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:22
msgid " (page"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:19
msgid " addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:41
msgid "Back"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:17
msgid "Showing "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""

@ -104,7 +104,7 @@ msgid "Address"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:4
#: lib/block_scout_web/templates/address/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59
msgid "Addresses"
msgstr ""
@ -578,6 +578,8 @@ msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
#: lib/block_scout_web/templates/address/index.html.eex:36
#: lib/block_scout_web/templates/address_token/index.html.eex:22
msgid "Next"
msgstr ""
@ -712,7 +714,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:111
#: lib/block_scout_web/templates/layout/_topnav.html.eex:129
#: lib/block_scout_web/templates/layout/_topnav.html.eex:128
msgid "Search"
msgstr ""
@ -739,11 +741,6 @@ msgstr ""
msgid "Showing"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:6
msgid "Showing 250 addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8
#: lib/block_scout_web/views/transaction_view.ex:210
@ -1078,7 +1075,7 @@ msgid "string"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:8
#: lib/block_scout_web/templates/address/index.html.eex:21
msgid "total addresses with a balance"
msgstr ""
@ -1708,11 +1705,6 @@ msgstr ""
msgid "ERC-721"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/api_docs/index.html.eex:4
msgid "API Documentation"
@ -1739,3 +1731,29 @@ msgstr ""
#: lib/block_scout_web/views/transaction_view.ex:341
msgid "Raw Trace"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:22
msgid " (page"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:19
msgid " addresses of"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:41
msgid "Back"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/index.html.eex:17
msgid "Showing "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:64
msgid "Total blocks"
msgstr ""

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

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

@ -1143,21 +1143,25 @@ defmodule Explorer.Chain do
end
@doc """
Lists the top 250 `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance.
Lists the top `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance and address hash.
"""
@spec list_top_addresses :: [{Address.t(), non_neg_integer()}]
def list_top_addresses do
query =
def list_top_addresses(options \\ []) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
base_query =
from(a in Address,
where: a.fetched_coin_balance > ^0,
order_by: [desc: a.fetched_coin_balance, asc: a.hash],
preload: [:names],
select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)},
limit: 250
select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)}
)
Repo.all(query)
base_query
|> page_addresses(paging_options)
|> limit(^paging_options.page_size)
|> Repo.all()
end
@doc """
@ -2293,6 +2297,12 @@ defmodule Explorer.Chain do
end)
end
defp page_addresses(query, %PagingOptions{key: nil}), do: query
defp page_addresses(query, %PagingOptions{key: {coin_balance, hash}}) do
where(query, [address], address.fetched_coin_balance <= ^coin_balance and address.hash > ^hash)
end
defp page_blocks(query, %PagingOptions{key: nil}), do: query
defp page_blocks(query, %PagingOptions{key: {block_number}}) do

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

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

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

@ -1415,6 +1415,33 @@ defmodule Explorer.ChainTest do
|> Enum.map(fn {address, _transaction_count} -> address end)
|> Enum.map(& &1.hash)
end
test "paginates addresses" do
test_hashes =
4..0
|> Enum.map(&Explorer.Chain.Hash.cast(Explorer.Chain.Hash.Address, &1))
|> Enum.map(&elem(&1, 1))
result =
4..1
|> Enum.map(&insert(:address, fetched_coin_balance: &1, hash: Enum.fetch!(test_hashes, &1 - 1)))
|> Enum.map(& &1.hash)
options = [paging_options: %PagingOptions{page_size: 1}]
[{top_address, _}] = Chain.list_top_addresses(options)
assert top_address.hash == List.first(result)
tail_options = [
paging_options: %PagingOptions{key: {top_address.fetched_coin_balance.value, top_address.hash}, page_size: 3}
]
tail_result = tail_options |> Chain.list_top_addresses() |> Enum.map(fn {address, _} -> address.hash end)
[_ | expected_tail] = result
assert tail_result == expected_tail
end
end
describe "stream_blocks_without_rewards/2" do

Loading…
Cancel
Save