49

Given the (Solidity) source code of a smart contract, is there a way to deterministically compile the code and compare it with the code on the blockchain? I want to verify that the contract does what the source code claims to do and the author hasn't tampered with it.

30

AFAIK the best way to do this at the moment is to compile the source code again with the exact same compiler version the author used (so this is something that needs to be disclosed) and to compare the bytecode.

So the match you should check is the compiled bytecode against the data of the contract creation tx.

16

To add to @thomas-bertani's answer, today etherchain.org released a verification tool for Ethereum contracts

Here's the quoted text from the How does it work page:

  • Retrieve the payload of the transaction that created the contract
  • Compile the provided source code with the provided compiler & settings
  • If the creation and the provided bytecode match it can be assumed that the provided sourcecode equals to what was previously deployed on the blockchain
10

Currently the workflow is quite annoying. You need to compile the contract with the same compiler version and the same setting (look out for the "optimization=true" flag).

Now please note that the resulting bytecode does NOT match with the bytecode that is stored on the address. The reason for that is that the compiled contract does contain an initialization part that is ran only once when the contract is submitted to the chain. So the byte code stored on the blockchain is the code without the initialization part.

To verify the code you have two options:

  1. Submit the compiled code to a (virtual) blockchain and than check with the getCode command the resulting code.
  2. Compare the compiled code with the payload of the transaction that created the contract.

Etherchain helps to do this process.

In principal pattern matching techniques could be applied to identify a contact even if not exactly the same compiler is used. A project that is doing this and in general linking high level contract (Serpent/Solidity) to Ethereum adresses is: Etherscrape

6

https://etherscan.io/verifyContract is a verification tool. By providing the Solidity Source Code it checks if the generated Bytecode matches to the contract Bytecode (under the given address). user should choose the same compiler and to enable or disable the optimimsation.

3

Another approach would be to decompile the bytecode and compare it with the source.

There is a tool called Porosity that does just that.

  • I'm fairly confident that this cannot work to any level of efficiency, especially for larger contracts. The names of the variables are not stored in the byte code, so the decompiler must create its own names. Trying to see if the decompiled code is the same as represented source would be very difficult, I would think. – Thomas Jay Rush Aug 9 '17 at 20:19
  • 1
    The Contract ABI contains all the variable names. – emx Aug 10 '17 at 22:02
  • Not always. I've seen many that don't. – Thomas Jay Rush Aug 10 '17 at 22:03
  • Noted. This would indeed make decompilation unpractical for complex contracts. – emx Aug 10 '17 at 22:26
  • I didn't realize the decompiler used the ABI. That clearly makes it a lot easier. – Thomas Jay Rush Aug 10 '17 at 23:34
1

Recommend to use the open-sourced command line tool ConsenSys just released, bytecode-verifier, respective npm package

Bytecode Verifier is a handy commandline tool for verifying locally compiled bytecode of a target Solidity contract against its actual bytecode stored in Etheruem Blockchain provided its contract address.

  • integrity/correctness of bytecode: what's actually being stored on chain is correctly compiled from particular contract, which might be helpful in case of non-trivial potential high-value holder contract deployment(e.g. MultiSig Wallet), especially the contract is deployed through a third party platform.

  • Minimimal effort, simple to use: solidity compiler envolves overtime with minor and some major changes, which complicates the verification of bytecode. (as recurring "bytecode doesn't match" questions being asked on Ethereum Stack Exchange). Bytecode Verifier has been tested against latest version all the way back to some of the oldest deployed contracts.

  • Testnet friendly: most projects launch on testnet before deploying the contract system to mainnet, this tool supports Rinkeby, Kovan and Ropsten Testnet, which constitute three active, well-maintained testnets that most ethereum developers use.

Hope it helps!

0

This is how I do it in a web3 script.

First, compile the code.

const solc = require('solc');

//contract sources
const contractPath = "../contracts/";

const input = {
  "ContractName.sol" : fs.readFileSync(contractPath + 'contractName.sol', 'utf8'),
}

let solcOutput = await solc.compile({ sources: input }, 1);

now compare byteCode

let blockCode = await web3.eth.getCode(contractAddress);
let solcCode = '0x' + (solcOutput.contracts["contractName.sol:contracName"].runtimeBytecode);}
  • This does not work, you are missing constructor parameters and auxdata – mdv Aug 23 '18 at 21:50
  • How did u test it? it works for me on all of kyber network contracts. – Ilan Dshare Oct 4 '18 at 10:12
  • @mdv Do you need to have matching constructor parameters? I'm seeing conflicting responses, but my guess is no, since the constructor is designed to put values in storage, not determine the existence of functions or state vars. – GViz Oct 5 '18 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.