{"id":920,"date":"2018-10-29T14:08:18","date_gmt":"2018-10-29T22:08:18","guid":{"rendered":"https:\/\/www.pnfsoftware.com\/blog\/?p=920"},"modified":"2022-07-07T07:40:36","modified_gmt":"2022-07-07T15:40:36","slug":"ethereum-smart-contract-decompiler","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/ethereum-smart-contract-decompiler\/","title":{"rendered":"Ethereum Smart Contract Decompiler"},"content":{"rendered":"<p><em><strong>Update: March 8, 2022:<br \/>\n<\/strong>&#8211; The most up-to-date version of this document can be found <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/ethereum\/\">in the Manual<\/a>\u00a0<strong><br \/>\n<\/strong><\/em><em><strong>Update: Dec 8, 2021:<br \/>\n<\/strong>&#8211; Reference section with list of special translations for EVM opcodes<strong><br \/>\nUpdate: Jan 2, 2019:<\/strong><br \/>\n&#8211; The full EVM decompiler shipped with JEB 3.0-beta.8<br \/>\n&#8211; Download <a href=\"https:\/\/github.com\/pnfsoftware\/jeb-samplecode\/blob\/master\/scripts\/WalkEvmDecomp.py\">a sample JEB Python script<\/a> showing how to use the API<br \/>\n<\/em><em><strong>Update: Nov 20, 2018:<\/strong><br \/>\n<\/em><em>&#8211; We uploaded <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/assets\/evmdec\/polyswarmChallenge_2e4d2a597a2fcbdf6cc55eb5c973e76aa19ac410.html\">the decompiled code of an interested contract<\/a>, the second part of the PolySwarm challenge (a good write-up can be found <a href=\"https:\/\/raz0r.name\/writeups\/polyswarm-smart-contract-hacking-challenge-writeup\/\">here<\/a>)<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/2e3973b19e723a56ad3ced9a9e9d4815.png\" width=\"70\" height=\"70\" \/>We&#8217;re excited to announce that the pre-release of our Ethereum smart contract decompiler is available.\u00a0We hope that it will become a tool of choice for security auditors, vulnerability researchers, and reverse engineers examining opaque smart contracts running on Ethereum platforms.<\/p>\n<p><strong>TL;DR: <\/strong><a href=\"https:\/\/www.pnfsoftware.com\/jeb\/demo\"><strong>Download the demo build and start reversing contracts<\/strong><\/a><\/p>\n<p>Keep on reading to learn about the current features of the decompiler; how to use it and understand its output; its current limitations, and planned additions.<\/p>\n<figure style=\"width: 383px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/f4f19eae1318b2332a865f6ed724ef31.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/f4f19eae1318b2332a865f6ed724ef31.png\" alt=\"\" width=\"383\" height=\"484\" \/><\/a><figcaption class=\"wp-caption-text\">This opaque multisig wallet is holding more than USD $22 million as of 10\/26\/2018 (on mainnet, address 0x3DBB3E8A5B1E9DF522A441FFB8464F57798714B1)<\/figcaption><\/figure>\n<h2>Overall decompiler features<\/h2>\n<p>The decompiler modules provide the following specific capabilities:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The EVM decompiler takes compiled smart contract EVM <sup class='footnote'><a href='#fn-920-1' id='fnref-920-1' onclick='return fdfootnote_show(920)'>1<\/a><\/sup> code as input, and decompiles them to <a href=\"https:\/\/solidity.readthedocs.io\/en\/latest\/index.html\">Solidity<\/a>-like source code.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The initial EVM code analysis passes determine contract\u2019s public and private methods, including implementations of public methods synthetically generated by compilers.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Code analysis attempts to determine method and event names and prototypes, without access to an ABI.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The decompiler also attempts to recover various high-level constructs, including:<\/span>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Implementations of well-known interfaces, such as ERC20 for standard tokens, ERC721 for non-fungible tokens, MultiSigWallet contracts, etc.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Storage variables and types<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">High-level Solidity artifacts and idioms, including:<\/span>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li><span style=\"font-weight: 400;\">Function mutability attributes<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Function payability state<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Event emission, including event name<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Invocations of address.send() or address.transfer()<\/span><\/li>\n<li>Precompiled contracts invocations<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>On top of the above, the JEB back-end and client platform provide the following standard functionality:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The decompiler uses JEB\u2019s optimizations pipeline to produce high-level clean code.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">It uses JEB code analysis core features, and therefore permits: code refactoring (eg, consistently renaming methods or fields), commenting and annotating, navigating (eg, cross references), typing, graphing, etc.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Users have access to the intermediate-level IR representation as well as high-level AST representations though the JEB API.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">More generally, the API allows power-users to write extensions, ranging from simple scripts in Python to complex plugins in Java.<\/span><\/li>\n<\/ul>\n<p>Our Ethereum modules were tested on thousands of smart contracts active on Ethereum mainnet and testnets.<\/p>\n<h2>Basic usage<\/h2>\n<p>Open a contract via the &#8220;<em>File, Download Ethereum Contract&#8230;&#8221;<\/em>\u00a0menu entry.<\/p>\n<p>You will be offered two options:<\/p>\n<ul>\n<li>Open a binary file already stored on disk<\/li>\n<li>Download <sup class='footnote'><a href='#fn-920-2' id='fnref-920-2' onclick='return fdfootnote_show(920)'>2<\/a><\/sup> and open a contract from one of the principal Ethereum networks: <em>mainnet<\/em>, <em>rinkeby<\/em>, <em>ropsten<\/em>, or <em>kovan<\/em>:\n<ul>\n<li>Select the network<\/li>\n<li>Provide the contract 20-byte address<\/li>\n<li>Click Download and select a file destination<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<figure style=\"width: 692px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/88043e4e15f5dbcedb315eeffb34778c.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/88043e4e15f5dbcedb315eeffb34778c.png\" alt=\"\" width=\"692\" height=\"382\" \/><\/a><figcaption class=\"wp-caption-text\">Open a contract via the File, Open smart contract menu entry<\/figcaption><\/figure>\n<p>Note that to be recognized as EVM code, a file must:<\/p>\n<ul>\n<li>either have a &#8220;.evm-bytecode&#8221; extension: in this case, the file may contain binary or hex-encoded code;<\/li>\n<li>or have be a &#8220;.runtime&#8221; or &#8220;.bin-runtime&#8221; extension (as generated by the solc Solidity compiler), and contain hex-encoded Solidity generated code.<\/li>\n<\/ul>\n<p>If you are opening raw files, we recommend you append the &#8220;.evm-extension&#8221; to them in order to guarantee that they will be processed as EVM contract code.<\/p>\n<h4>Contract Processing<\/h4>\n<p>JEB will process your contract file and generate a <em>DecompiledContract<\/em> class item to represent it:<\/p>\n<figure style=\"width: 938px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/02c689c49d721af0e362009f9c7f41d3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/02c689c49d721af0e362009f9c7f41d3.png\" alt=\"\" width=\"938\" height=\"616\" \/><\/a><figcaption class=\"wp-caption-text\">The Assembly view on the right panel shows the processed code.<\/figcaption><\/figure>\n<p><span style=\"text-decoration: underline;\">To switch to the decompiled view, select the &#8220;Decompiled Contract&#8221; node in the Hierarchy view, and press TAB<\/span>\u00a0(or right-click, <em>Decompile<\/em>).<\/p>\n<figure style=\"width: 348px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/3a869895df2b1c6c1abd5119d7ee68c6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/3a869895df2b1c6c1abd5119d7ee68c6.png\" alt=\"\" width=\"348\" height=\"286\" \/><\/a><figcaption class=\"wp-caption-text\">Right-click on items to bring up context menus showing the principal commands and shortcuts.<\/figcaption><\/figure>\n<figure style=\"width: 450px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/6e9ffbd2d9e279911ce2c1a519ee76fd.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/6e9ffbd2d9e279911ce2c1a519ee76fd.png\" alt=\"\" width=\"450\" height=\"842\" \/><\/a><figcaption class=\"wp-caption-text\">The decompiled view of a contract.<\/figcaption><\/figure>\n<p>The decompiled contract is rendered in Solidity-like code: it is mostly Solidity code, but not entirely; constructs that are illegal in Solidity are used throughout the code to represent instructions that the decompiler could not represent otherwise. Examples include: low-level statements representing some low-level EVM instructions, memory accesses, or very rarely, goto statements. Do not expect a DecompiledContract to be easily recompiled.<\/p>\n<h4>Code views<\/h4>\n<p>You may adjust the View panels to have side-by-side views if you wish to navigate the assembly and high-level code at the same time.<\/p>\n<ul>\n<li>In the assembly view, within a routine, press Space to visualize its control flow graph.<\/li>\n<li>To navigate from assembly to source, and back, press the TAB key. The caret will be positioned on the closest matching instruction.<\/li>\n<\/ul>\n<figure style=\"width: 1468px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/d37611d97124b63b42864976a19574b4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/d37611d97124b63b42864976a19574b4.png\" alt=\"\" width=\"1468\" height=\"934\" \/><\/a><figcaption class=\"wp-caption-text\">Side by side views: assembly and source<\/figcaption><\/figure>\n<h4>Contract information<\/h4>\n<p>In the Project Explorer panel, double click the contract node (the node with the official Ethereum Foundation logo), and then select the Description tab in the opened view to see interesting information about the processed contract, such as:<\/p>\n<ul>\n<li>The detected compiler and\/or its version (currently supported are variants of Solidity and Vyper compilers).<\/li>\n<li>The list of detected routines (private and public, with their hashes).<\/li>\n<li>The Swarm hash of the metadata file, if any.<\/li>\n<\/ul>\n<figure style=\"width: 764px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/911f7968c7ef2d15a9dc25e8de1a2c1e.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/911f7968c7ef2d15a9dc25e8de1a2c1e.png\" alt=\"\" width=\"764\" height=\"490\" \/><\/a><figcaption class=\"wp-caption-text\">The contract was identified as being compiled with Solidity &lt;= 0.4.21<\/figcaption><\/figure>\n<h4>Commands<\/h4>\n<p>The usual commands can be used to refactor and annotate the assembly or decompiled code. You will find the exhaustive list in the <em>Action<\/em> and <em>Native<\/em> menus. Here are basic commands:<\/p>\n<ul>\n<li>Rename items (methods, variables, globals, &#8230;) using the N key<\/li>\n<li>Navigate the code by examining cross-references, using the X key (eg, find all callers of a method and jump to one of them)<\/li>\n<li>Comment using the Slash key<\/li>\n<li>As said earlier, the TAB key is useful to navigate back and forth from the low-level EVM code to high-level decompiled code<\/li>\n<\/ul>\n<p>We recommend you to browser the <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/\">general user manual<\/a> to get up to speed on how to use JEB.<\/p>\n<figure style=\"width: 654px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/85e9fad894c6477cacfec84ec7a49a04.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/85e9fad894c6477cacfec84ec7a49a04.png\" alt=\"\" width=\"654\" height=\"450\" \/><\/a><figcaption class=\"wp-caption-text\">Rename an item (eg, a variable) by pressing the N key<\/figcaption><\/figure>\n<p>Remember that you can change immediate number bases and rendering by using the B key. In the example below, you can see a couple of strings present in the <a href=\"https:\/\/etherscan.io\/address\/0xdd9fd6b6f8f7ea932997992bbe67eabb3e316f3c\">bad Fomo3D<\/a> contract, initially rendered in Hex:<\/p>\n<figure style=\"width: 746px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/491154e6a7af32941dd95a4b2fee9c77.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/491154e6a7af32941dd95a4b2fee9c77.png\" alt=\"\" width=\"746\" height=\"562\" \/><\/a><figcaption class=\"wp-caption-text\">All immediates are rendered as hex-strings by default.<\/figcaption><\/figure>\n<figure style=\"width: 846px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/4de6163e6ba7bf5554b5dd37f3068f41.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/4de6163e6ba7bf5554b5dd37f3068f41.png\" alt=\"\" width=\"846\" height=\"554\" \/><\/a><figcaption class=\"wp-caption-text\">Use the B key to cycle through base (10, 16, etc.) and rendering (number, ascii)<\/figcaption><\/figure>\n<h2>Understanding decompiled contracts<\/h2>\n<p>This section highlights idioms you will encounter throughout decompiled pseudo-Solidity code. The examples below show the JEB UI Client with an assembly on the left side, and high level decompiled code on the right side. The contracts used as examples are live contracts currently active Ethereum <em>mainnet<\/em>.<\/p>\n<p><span style=\"text-decoration: underline;\">We also highlight current limitations and planned additions.<\/span><\/p>\n<h4>Dispatcher and public functions<\/h4>\n<p>The entry-point function of a contract, at address 0, is generally its dispatcher. It is named start() by JEB, and in most cases will consist in an if-statement comparing the input calldata hash (the first 4 bytes) to pre-calculated hashes, to determine which routine is to be executed.<\/p>\n<ul>\n<li>JEB attempts to determine public method names by using a hash dictionary (currently containing more than 140,000 entries).<\/li>\n<li>Contracts compiled by Solidity generally use synthetic (compiler generated) methods as bridges between public routines, that use the public Ethereum ABI, and internal routines, using a compiler-specific ABI. Those routines are identified as well and, if their corresponding public method was named, will be assigned a similar name <em>__impl_{PUBLIC_NAME}<\/em>.<\/li>\n<\/ul>\n<p>NOTE\/PLANNED ADDITION: currently, JEB does not attempt to process input data of public routines and massage it back into an explicit prototype with regular variables. Therefore, you will see low-level access to CALLDATA bytes within public methods.<\/p>\n<figure style=\"width: 1576px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/24aaf655345b6b8ba46f0a7aef15a51d.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/24aaf655345b6b8ba46f0a7aef15a51d.png\" alt=\"\" width=\"1576\" height=\"454\" \/><\/a><figcaption class=\"wp-caption-text\">A dispatcher.<\/figcaption><\/figure>\n<p>Below, see the public method collectToken(), which is retrieving its first parameter &#8211; a 20 byte address &#8211; from the calldata.<\/p>\n<figure style=\"width: 1572px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/9ef9328769da56845c59d3c403170b6e.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/9ef9328769da56845c59d3c403170b6e.png\" alt=\"\" width=\"1572\" height=\"552\" \/><\/a><figcaption class=\"wp-caption-text\">A public method reading its arguments from CALLDATA bytes.<\/figcaption><\/figure>\n<h4>Interface discovery<\/h4>\n<p>At the time of writing, implementation of the following interfaces can be detected: ERC20, ERC165, ERC721,\u00a0ERC721TokenReceiver, ERC721Metadata, ERC721Enumerable,\u00a0ERC820, ERC223, ERC777, TokenFallback used by ERC223\/ERC777 interfaces, as well as the common MultiSigWallet interface.<\/p>\n<p>Eg, the contract below was identified as an ERC20 token implementation:<\/p>\n<figure style=\"width: 338px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/2898d7969f445803c18c2ca1776ecefd.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/2898d7969f445803c18c2ca1776ecefd.png\" alt=\"\" width=\"338\" height=\"294\" \/><\/a><figcaption class=\"wp-caption-text\">This contract implements all methods specified by the ERC20 interface.<\/figcaption><\/figure>\n<h4>Function attributes<\/h4>\n<p>JEB does its best to retrieve:<\/p>\n<ul>\n<li>low-level state mutability attributes (pure, read-only, read-write)<\/li>\n<li>the high-level Solidity &#8216;payable&#8217; attribute, reserved for public methods<\/li>\n<\/ul>\n<p>Explicitly non-payable functions have lower-level synthetic stubs that verify that no Ether is being received. They REVERT if it is is the case. If JEB decides to remove this stub, the function will always have an inline comment <strong>\/* non payable *\/<\/strong>\u00a0to avoid any ambiguity.<\/p>\n<p>The contract below shows two public methods, one has a default mutability state (non-payable); the other one is payable. (Note that the hash 0xFF03AD56 was not resolved, therefore the name of the method is unknown and was set to sub_AF; you may also see a call to the collect()&#8217;s bridge function __impl_collect(), as was mentioned in the previous section).<\/p>\n<figure style=\"width: 592px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/80989a5d4aa44b04f6808ffda43d2c32.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/80989a5d4aa44b04f6808ffda43d2c32.png\" alt=\"\" width=\"592\" height=\"560\" \/><\/a><figcaption class=\"wp-caption-text\">Two public methods, one is payable, the other is not and will revert if it receives Ether.<\/figcaption><\/figure>\n<h4>Storage variables<\/h4>\n<p>The pre-release decompiler ships with a limited storage reconstructor module.<\/p>\n<ul>\n<li>Accesses to primitives (int8 to int256, uint8 to uint256) is reconstructed in most cases<\/li>\n<li>Packed small primitives in storage words are extracted (eg, a 256-bit storage word containing 2x uint8 and 1x int32, and accessed as such throughout the code, will yield 3 contract variables, as one would expect to see in a Solidity contract<\/li>\n<\/ul>\n<figure style=\"width: 843px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/9018d9db9ab777ddcc5660cce861aea7.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/9018d9db9ab777ddcc5660cce861aea7.png\" alt=\"\" width=\"843\" height=\"627\" \/><\/a><figcaption class=\"wp-caption-text\">Four primitive storage variables were reconstructed.<\/figcaption><\/figure>\n<p>However, currently, accesses to complex storage variables, such as mappings, mappings of mappings, mappings of structures, etc. are not simplified.\u00a0This limitation will be addressed in the full release.<\/p>\n<p>When a storage variable is not resolved, you will see simple &#8220;storage[&#8230;]&#8221; assignments, such as:<\/p>\n<figure style=\"width: 1252px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/605eb425bb9efb55e2ccb025eb3d308e.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/605eb425bb9efb55e2ccb025eb3d308e.png\" alt=\"\" width=\"1252\" height=\"618\" \/><\/a><figcaption class=\"wp-caption-text\">Unresolved storage assignment, here, to a mapping.<\/figcaption><\/figure>\n<p>Due to how storage on Ethereum is designed (a key-value store of uint256 to uint256), Solidity internally uses a two-or-more indirection level for computing actual storage keys. Those low-level storage keys depend on the position of the high level storage variables. The KECCAK256 opcode is used to calculate intermediate and final keys. We will detail this mechanism in detail in a future blog post.<\/p>\n<h4>Precompiled contracts<\/h4>\n<p>Ethereum defines <a href=\"https:\/\/github.com\/ethereum\/aleth\/blob\/master\/libethereum\/ChainParams.cpp#L41\">four pre-compiled contracts<\/a> at addresses 1, 2, 3, 4. (Other addresses (5-8) are being reserved for additional pre-compiled contracts, but this is still at the ERC stage.)<\/p>\n<p>JEB identifies CALLs that will eventually lead to pre-compiled code execution, and marks them as such in decompiled code: <em>call_{specific}<\/em>.<\/p>\n<p>The example below shows the <em>__impl_Receive<\/em> (named recovered) method of the <a href=\"https:\/\/etherscan.io\/address\/0x949a6ac29b9347b3eb9a420272a9dd7890b787a3\">34C3 CTF contract<\/a>, which calls into address #2, a pre-compiled contract providing a fast implementation of SHA-256.<\/p>\n<figure style=\"width: 1572px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/0ebd5c150d948c4a4cf0f04c8e55ffb6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/0ebd5c150d948c4a4cf0f04c8e55ffb6.png\" alt=\"\" width=\"1572\" height=\"630\" \/><\/a><figcaption class=\"wp-caption-text\">This contract calls address 2 to calculate the SHA-256 of a binary blob.<\/figcaption><\/figure>\n<h4>Ether send()<\/h4>\n<p>Solidity&#8217;s <em>send<\/em> can be translated into a lower-level call with a standard gas stipend and zero parameters. It is essentially used to send Ether to a contract through the target contract fallback function.<\/p>\n<p>NOTE: Currently, JEB renders them as send(address, amount) instead of address.send(amount)<\/p>\n<p>The contract below is live on mainnet. It is a simple forwarder, that does not store ether: it forwards the received amount to another contract.<\/p>\n<figure style=\"width: 1576px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/ca30667cbf1bc65fcd4026b93c85f8bf.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/ca30667cbf1bc65fcd4026b93c85f8bf.png\" alt=\"\" width=\"1576\" height=\"934\" \/><\/a><figcaption class=\"wp-caption-text\">This contract makes use of address.send(&#8230;) to send Ether<\/figcaption><\/figure>\n<h4>Ether transfer()<\/h4>\n<p>Solidity&#8217;s transfer is an even higher-level variant of send that checks and REVERTs with data if CALL failed. JEB identifies those calls as well.<\/p>\n<p>NOTE: Currently, JEB renders them as transfer(address, amount) instead of address.transfer(amount)<\/p>\n<figure style=\"width: 1572px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/aa674f06ddec85f831cc6f54e622e570.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/aa674f06ddec85f831cc6f54e622e570.png\" alt=\"\" width=\"1572\" height=\"552\" \/><\/a><figcaption class=\"wp-caption-text\">This contract makes use of address.transfer(&#8230;) to send Ether<\/figcaption><\/figure>\n<h4>Event emission<\/h4>\n<p>JEB attempts to partially reconstruct LOGx (x in 1..4) opcodes back into high-level Solidity &#8220;emit Event(&#8230;)&#8221;. The event name is resolved by reversing the Event method prototype hash. At the time of writing, our dictionary contains more than 20,000 entries.<\/p>\n<p>If JEB cannot reverse a LOGx instruction, or if LOG0 is used, then a lower-level log(&#8230;) call will be used.<\/p>\n<p>NOTE: currently, the event parameters are not processed; therefore, the <em>emit<\/em>\u00a0construct used in the decompiled code has the following form: emit Event(memory, size[, topic2[, topic3[, topic4]]]). topic1 is always used to store the event prototype hash.<\/p>\n<figure style=\"width: 1574px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/f3585532f369ae03e8ceb4b5e1b35464.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/10\/f3585532f369ae03e8ceb4b5e1b35464.png\" alt=\"\" width=\"1574\" height=\"928\" \/><\/a><figcaption class=\"wp-caption-text\">An Invocation of LOG4 reversed to an &#8220;emit Deposit(&#8230;)&#8221; event emission<\/figcaption><\/figure>\n<h2>API<\/h2>\n<p>JEB API allows automation of complex or repetitive tasks. Back-end plugins or complex scripts can be written in Python or Java. The API update that ship with JEB 3.0-beta.6 allow users to query decompiled contract code:<\/p>\n<ul>\n<li>access to the intermediate representation (IR)<\/li>\n<li>access to the final Solidity-like representation (AST)<\/li>\n<\/ul>\n<p>API use is out-of-scope here. We will provide examples either in a subsequent blog post or on our public <a href=\"https:\/\/github.com\/pnfsoftware\/\">GitHub repository<\/a>.<\/p>\n<h2>Additional References<\/h2>\n<p>List of EVM opcodes that receive special translation: <a href=\"https:\/\/gist.github.com\/nfalliere\/a8723af39762db6263bae870ab4b63d6\">link<\/a> (on GitHub)<\/p>\n<h2>Conclusion<\/h2>\n<p>As said in the introduction, if you are reverse engineering opaque contracts (that is, most contracts on Ethereum&#8217;s mainnet), we believe you will find JEB useful.<\/p>\n<p>You may give a try to the pre-release by downloading the demo <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/demo\">here.<\/a>\u00a0Please let us know your feedback: we are planning a full release before the end of the year.<\/p>\n<p>As always, thank you to all our users and supporters. -Nicolas<\/p>\n<div class='footnotes' id='footnotes-920'>\n<div class='footnotedivider'><\/div>\n<ol>\n<li id='fn-920-1'> EVM: Ethereum Virtual Machine <span class='footnotereverse'><a href='#fnref-920-1'>&#8617;<\/a><\/span><\/li>\n<li id='fn-920-2'> This Open plugin uses <a href=\"http:\/\/etherscan.io\">Etherscan<\/a>\u00a0to retrieve the contract code <span class='footnotereverse'><a href='#fnref-920-2'>&#8617;<\/a><\/span><\/li>\n<\/ol>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Update: March 8, 2022: &#8211; The most up-to-date version of this document can be found in the Manual\u00a0 Update: Dec 8, 2021: &#8211; Reference section with list of special translations for EVM opcodes Update: Jan 2, 2019: &#8211; The full EVM decompiler shipped with JEB 3.0-beta.8 &#8211; Download a sample JEB Python script showing how &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/ethereum-smart-contract-decompiler\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Ethereum Smart Contract Decompiler<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,19,18],"tags":[],"class_list":["post-920","post","type-post","status-publish","format-standard","hentry","category-decompilation","category-ethereum","category-jeb3"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=920"}],"version-history":[{"count":0,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/920\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}