# 在 Etherscan 上提交智能合約原始碼認證

By [0x0016區塊猿](https://paragraph.com/@0x0016) · 2022-04-03

---

本文亦發佈在作者網站： 最後更新：2021-11-20

[https://www.frank.hk/blog/smart-contract-sourcecode-verification/](https://www.frank.hk/blog/smart-contract-sourcecode-verification/)

這篇文章假設大家使用 [hardhat](https://hardhat.org/) 來進行智能合約開發。關於 hardhat 我有時間再詳細寫一寫懶人教學 😅。

大家如果常去 Etherscan 上查看智能合約 Smart Contract， 大概會看到兩種情況，第一種是如下這樣，在 Contract 下面看到是一堆「亂碼」，這堆「亂碼」其實是編譯過後的智能合約 ByteCode （字節碼），這明顯不是給人類閱讀的。

screen 20211119231007

另一種則是如下圖所示，在 Contract Tab 旁邊能夠看到一個綠色的✓，下面能夠看到智能合約的原始代碼，並且可以直接在 Etherscan 上讀取，調用智能合約的 function。

screen 20211119234126

明顯第二種合約給人的感覺會自信很多， 因為所有人都能夠清楚看到智能合約具體的運行邏輯，一切公開透明，不怕「黑箱作業」。

#### 那麼如何做到在 Etherscan 上「開放原始碼」呢？

一種方法是手動在 Etherscan 上提交原始碼，透過提交智能合約的地址，選擇編譯器版本，上載智能合約的原始碼等等一系列步驟之後便可以做到。

screen 20211119234857

但這種方法的壞處是非常麻煩，要確保選對編譯器版本，上載所有需要上載的檔案，包括一些第三方的 library。一旦上載的原始碼檔案出現錯漏，則無法完成認證。

有沒有更好的方法呢？

#### 隆重介紹 @nomiclabs/hardhat-etherscan

使用 @nomiclabs/hardhat-etherscan 這個 npm package，能夠超級簡單的完成智能合約認證。這個 package 集成了 Etherscan 的 API，透過 API 的形式自動完成原始碼認證，免去了繁瑣的手動步驟。

### 第一步

首先我們需要在 Etherscan 上有一個賬戶，然後免費申請一個 API key。 [按此前往](https://etherscan.io/myapikey)。

screen 20211119235848

在上述頁面中按下「ADD」即可申請一個全新的 API Key。得到這個 API Key 之後，將它放入你的 .env 檔案中。（假設你用 .env 檔案來保存環境變數）

    API_URL = xxx
    PUBLIC_KEY = xxx
    PRIVATE_KEY = xxx
    ETHERSCAN_API_KEY = 這裡填上你上面得到的 API Key 
    

### 第二步

安裝 `@nomiclabs/hardhat-etherscan`‌ ， 使用 npm 或者 yarn 的方式安裝。這個應該不用多說了吧，是人都會了。

    yarn add @nomiclabs/hardhat-etherscan‌ -D
    

### 第三步

現在我們需要設定 `hardhat.config.js` 。

首先，要在 `hardhat.config.js` 頂部引入這個 package

    require("@nomiclabs/hardhat-etherscan");‌
    

然後，在 `hardhat.config.js` 添加如下設定：

    module.exports = {
      solidity: "0.8.4",
      networks: {
        rinkeby: { xxx }, // xxx 是省略的意思哦，你應該不會照抄吧 😒
      },
      etherscan: {
        // 下面這個就是 Etherscan 的 API Key 哦 
        // 和上面第一步中 .env 檔案中的對應
        apiKey: process.env.ETHERSCAN_API_KEY
     }
    };
    

### 第四步

在完成智能合約編譯後，透過以下指令即可驗證智能合約原始碼：

    npx hardhat verify --network rinkeby <你的已發佈智能合約地址>
    

舉例：

    frank@MacBook demo % hh compile
    Compiling 1 files with 0.8.4
    Compilation finished successfully
    
    
    frank@MacBook demo % npx hardhat run --network rinkeby scripts/DeployDemo.js                     
    Deploying demo contract ... 
    Waiting for 2 confirmations...
    Contract deployed to:  0x4451ED9cD559Ac5e552c7AD757a642Af533EbD88
    
    
    frank@MacBook demo % npx hardhat verify --network rinkeby 0x4451ED9cD559Ac5e552c7AD757a642Af533EbD88
    Nothing to compile
    Compiling 1 file with 0.8.4
    Successfully submitted source code for contract
    contracts/Demo.sol:Demo at 0x4451ED9cD559Ac5e552c7AD757a642Af533EbD88
    for verification on Etherscan. Waiting for verification result...
    
    Successfully verified contract Demo on Etherscan.
    https://rinkeby.etherscan.io/address/0x4451ED9cD559Ac5e552c7AD757a642Af533EbD88#code
    

至此，打開 [Etherscan](https://rinkeby.etherscan.io/address/0x4451ED9cD559Ac5e552c7AD757a642Af533EbD88#code) ，就可以看到我們的智能合約已經認證成功啦。

DeployDemo.js 參考：

    
    const { ethers } = require("hardhat")
    
    async function main() {
    
      console.info(`Deploying demo contract ... `)
      const Demo = await ethers.getContractFactory("Demo");
      const demo = await Demo.deploy();
      
      console.info(`Waiting for 2 confirmations...`)
      let transcation = demo.deployTransaction
      const receipt = await transcation.wait(2)
      const { gasUsed } = receipt
      console.log("Contract deployed to: ", demo.address);
      console.info(`Gas used           : ${gasUsed} `)
    
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

技術交流，其他諮詢等，請[按此聯絡](https://www.frank.hk/contact)。

---

*Originally published on [0x0016區塊猿](https://paragraph.com/@0x0016/etherscan)*
