Michal Zalecki
Michal Zalecki
software development, testing, JavaScript,
TypeScript, Node.js, React, and other stuff

How to verify smart contract on Etherscan?

Why would you like to verify your smart contract? It depends. It mostly depends on your use case. It always comes down to being transparent. If I were into ICOs, I would want to make sure that the token and the crowdsale contract code enforces cryptoeconomics described in the whitepaper (or, ugh..., in the video). Open sourcing the code on GitHub is a great idea but gives no guarantees that the code in the repository is even remotely similar to the one running on-chain. It is a contract after all so it would be good to give other parties a chance to familiarize with the conditions they are going to "sign". Verify the source code even if not everyone has programming skills to read it.

For addresses that point to smart contracts, it is possible to get their code.

web3.eth.getCode("0xd49d7704b72b373f7c7adc14623511e25ecc4a2d");

Since this gives you binary code in hex representation, it is not feasible to try to understand what the contract is doing.

Etherscan is very popular (if not the most popular) blockchain explorer. A lot of people use Etherscan to learn more about the transaction or particular address on Ethereum blockchain. It provides multiple services on top of its exploring capabilities. One of them is confirming that binary data under specific address is a result of compilation of the specified source code (that you can read and analyze).

Sample project

To make it more interesting, our sample project will have a constructor that accepts a parameter and extends Ownable contract from zeppelin-solidity. Those simple elements will showcase a few challenges you might come across while trying to verify contract on your own.

pragma solidity 0.4.23;

import "zeppelin-solidity/contracts/ownership/Ownable.sol";


contract MessageOfTheDay is Ownable {
    string public message;

    constructor(string _message) public {
        message = _message;
    }

    function setMessage(string _message) public onlyOwner returns (bool) {
        message = _message;
        return true;
    }
}

The full source code is available on GitHub. You can clone it, deploy it and try to follow my steps to confirm your instance on Etherscan.

$ ./node_modules/.bin/truffle migrate --network kovan

Using network 'kovan'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x1124628216610c4683fe4a81107dd9a34a2532a44e2a39f6e8cf7918517be8d8
  Migrations: 0x16a49d6fe6831760e5208590435d911e7a462560
Saving successful migration to network...
  ... 0xf1c727123800989592d55c988aacc62b928b0ad36fc44c6bff97cce43f6a49cb
Saving artifacts...
Running migration: 2_message_of_the_day.js
  Deploying MessageOfTheDay...
  ... 0xb610d6ad2c1ac2eb742216a7248d49b65671d0712bf4e4863e006c1c1baf0e81
  MessageOfTheDay: 0x91926e1e9c7bdb0be4d2226caf7036392cc06763
Saving successful migration to network...
  ... 0x065eece5dc0fc260bca4e71589c575b9f43ca5a69336738b6f4c7f4e91c4897a
Saving artifacts...

Preparations

Before we start, we need to prepare ABI-encoded constructor arguments. You can do it by encoding values using web3. Much quicker is to do it using abi.hashex.org or read them straight from the transaction output that created the contract.

ABI-encoded representation of a single string argument:

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001948656c6c6f2c206d696368616c7a616c65636b692e636f6d2100000000000000

We have to prepare a single file that contains entire source code of the contract such that it has no import statements. Let's install Truffle Flattener.

npm install -D truffle-flattener
./node_modules/.bin/truffle-flattener ./contracts/MessageOfTheDay.sol > flattened.sol

You can now look into flattened.sol and find the source code of Ownable.sol contract in place of import statement.

Verification

To start the process go to Etherscan Verify Contract Code page. Make sure to use the network to which you deployed the contract and 2.0 version (with verifyContract2 in the URL).

  1. Paste contract address
  2. Enter the name of the contract
  3. Select compiler version you have used to compile the project. You can check it by running truffle version
  4. Set optimization accordingly to your project settings. Remember to also set the correct number of runs
  5. Paste flattened source code
  6. Paste ABI-encoded constructor arguments
  7. Click "Verify And Publish"

https://res.cloudinary.com/michal/image/upload/v1524928257/MessageOfTheDay.png

That's it, you have successfully verified your smart contract!

Photo by rawpixel on Unsplash.