Easy multifile verification on block explorers

Abstract

Many developers flatten contracts to verify, we need support for easy multifile verification on block explorers. To do this we need the ecosystem to support.

Previously discussed indirectly: https://github.com/ethereum/solidity/issues/8989
Originally posted as issue: https://github.com/ethereum/solidity/issues/9650

Motivation

There is a community expectation that code controlling any value will be verified on block explorers.

Etherscan verify API currently only supports flattened files

from: https://etherscan.io/apis#contracts
Contracts that use “imports” will need to have the code concatenated into one file as we do not support “imports” in separate files. You can try using the Blockcat solidity-flattener or SolidityFlattery

This means that many developers flatten their contracts to verify.

Flattening with SPDX License Identifiers is now a problem as developers either need to ensure that they use a single compatible license otherwise they could be changing/removing the license of third party code that they are importing.

Etherscan web interface supports multiple files but the files have to be in a single directory and the imports changed so that the imports use a single directory.

Raising awareness of the problem so that we can solve for the ecosystem.

If we could make multifile verification easy for all developers then there would no longer be a need to flatten.

A short term workaround could be a tool that copies a contract and it’s dependencies to a single directory and updates the imports to be local to the directory. This would enable use of Etherscans web based verification.

Though long term we need deploy tools to verify to block explorers and/or sourcify via APIs automagically.

Unfortunately the community will still flatten contracts until we have easy multifile verification.

Example

The following simple ERC20 token inheriting from the OpenZeppelin Contracts ERC20 implementation was deployed to Rinkeby using Truffle.

SimpleToken.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**
 * @title SimpleToken
 * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` functions.
 */
contract SimpleToken is ERC20 {

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
    constructor () public ERC20("Simple Token", "SIM") {
        _mint(msg.sender, 1000000 * (10 ** uint256(decimals())));
    }
}

To verify as multifile, the SimpleToken.sol contract along with the five imported contracts had to be placed in a single directory, copying the required contracts from node_modules/@openzeppelin/contracts and then modifying any imports whether relative or from @openzeppelin/contracts to be relative to a single directory.

The contract could then be verified uploading the files from the one directory:

1)  Address.sol |   | (6078 Bytes)
2)  Context.sol |   | (933 Bytes)
3)  ERC20.sol |   | (10765 Bytes)
4)  IERC20.sol |   | (2696 Bytes)
5)  SafeMath.sol |   | (5201 Bytes)
6)  SimpleToken.sol |   | (559 Bytes)

The end result is the six contracts being verified, but the contracts still had to have their imports modified, so they are not the exact same text as what was used to compile/deploy.


Compare with the process of flattening (or even using a tool that connects to the API) - except for the issue of multiple SPDX License identifiers since Solidity 0.6.8

$ npx truffle-flattener ./contracts/SimpleToken.sol > ./FlatSimpleToken.sol
npx: installed 64 in 13.339s

I verified manually on Etherscan, after compiling with buidler Standard Json Input in cache\solc-input.json and this then displays the individual files, which appears to work ok.

An even nicer solution is the buidler-etherscan plugin: