{"content":{"title":"怎样通过 Etherscan 验证智能合约","body":"Web3 被称为去中心化版本的英特网 ，它有一个优点是任何人都可以与部署在区块链上的智能合约交互。众所周知，智能合约就是你在区块链上运行的一段电脑程序，这些程序的源代码是公开的，任何人都可以验证。如果想要和合约交互，任何人都可以运行一个区块链客户端然后通过命令行工具创建交易来实现，而不需要网页 UI 与其进行交互。<\/p>\r\n\r\nEtherscan 是一个对于众多区块链网络的区块浏览器，这些区块链网络包括：Ethereum，Polygon，Arbitrum，Optimism 和很多其他别的。如果你想要了解如何通过 Etherscan 和智能合约交互，请阅读最近这篇[通过 Etherscan 读取智能合约](https:\/\/learnblockchain.cn\/article\/4561)。<\/p>\r\n\r\n但是在上篇文章中，我们只可以在 Etherscan 上和验证过的智能合约进行交互。在本篇文章中，你将会学到如何在 Etherscan 上验证智能合约。<\/p>\r\n\r\n## 验证单一 Solidity 文件\r\n在开始验证之前，我们需要首先部署智能合约。进入 [Remix IDE](https:\/\/remix.ethereum.org\/)，创建一个叫做“Counter.sol”的新文件。复制粘贴下面的代码：<\/p>\r\n```js\r\n\/\/ SPDX-License-Identifier: MIT\r\n\r\npragma solidity ^0.8.0;\r\ncontract Counter {\r\n    uint256 internal counter;\r\n    function increment() external {\r\n        unchecked {\r\n            ++counter;\r\n        }\r\n    }\r\n\r\n   function getCurrent() external view returns(uint256) {\r\n        return counter;\r\n    }\r\n}\r\n```\r\n在部署之前，我们必须关注一下我们使用的 Solidity 编译器是哪个版本，和在合约代码最上方 “SPDX-License-Identifier” 中标注的 license 类型。\r\n\r\n因为我们在合约文件中标注了“^0.8.0”，所以这个合约可以被任何版本号为 0.8.0 和 0.9.0 之间的 solidity 编译器编译，这样就包含多个版本的比如 0.8.0，0.8.1，0.8.2 等等。\r\n\r\n在“Solidity Compiler”下，选择 Solidity 的编译器版本（可以是任何 0.8 的版本），然后点击“Compile Counter.sol”。在这个例子中，我们会使用 0.8.7 版本。\r\n<br>\r\n![1-1.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/WUSRH9bH63159a3b63d91.png)\r\n\r\n<br>\r\n在成功编译以后，到“Deploy & Run Transactions”下面，在“Environment”的下拉菜单中，选择“Injected Provider - Metamask”，它会自动链接你的 Metamask 到 Remix IDE。在此之后，你就可以在钱包中选择你要部署的区块链网络。\r\n\r\n我们会将合约部署到 Rinkeby 中，因此我们需要在 Metamask 中选择“Rinkeby Test Network”。在部署的时候需要使用 Rinkeby 的 ETH，你可以在 Chainlink 水龙头中获取一些。在获取的时候，注意在右上角选择的是 Ethereum Rinkeby 网络。\r\n<br>\r\n![1-2.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/khcP0R1E63159a5b6f47f.png)\r\n<br>\r\n最后，点击橙色的按钮“Deploy”，然后通过 Metamask 对交易进行签名。可能需要等待大概 15 秒钟，你的交易会被确认。当然现在我们就可以通过 Remix IDE 的 UI 与智能合约交互，但是如果我们想让更多人和我们的智能合约交互，这个方式就不可行了。\r\n\r\n现在，可以通过交易哈希或者合约地址在 Etherscan 上看到我们刚部署的合约。如果我们现在在 Contract 之下查看合约，只能看到 Bytecode，这意味着我们需要验证我们的智能合约，然后才能在 Etherscan 上使用它。 \r\n<br>\r\n\r\n![1-3.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/dDr0xmT563159a848de0d.png)\r\n<br>\r\n点击“Verify and Publish”这个蓝色的链接，下面这个页面会出现。\r\n<br>\r\n\r\n\r\n![1-4.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/o9FebGXw63159ab2e542d.png)\r\n<br>\r\n在第一个输入栏中输入你的合约地址，如果没有自动跳出来的话。在 Compiler Type 的下拉菜单中，选择“Solidity (Single File)”。接下来，“Compiler Version”的下拉菜单将会出现，这里需要选择我们用来编译这个合约的编译器版本，在这个例子中是 0.8.7。最后，在“Open Source License Type”下拉菜单中，选择在 Solidity 文件中“SPDX-License-Identifier” 中标记的 License。在我们的例子中是 MIT。点击继续，进入到下一个页面。\r\n<br>\r\n \r\n![1-5.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/wP1nmUA163159aef3e67f.png)\r\n\r\n<br>\r\n将合约的源代码复制到“Enter the Solidity Contract Code below”这个输入框之下，过了人机测试，点击“Verify and Publish”的蓝色按钮。你应该就会看到在“Contract”上会有一个绿色的对勾，这就表示你的合约已经验证成功，然后我们现在就可以与其交互了。\r\n<br><br>\r\n\r\n![1-6.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/0Gm3WDL863159b169586b.png)\r\n\r\n<br>\r\n点击“Read Contract”按钮，你应该可以调用“getCurrent”函数，然后看到 counter 这个变量的值，现在是默认值 0。\r\n<br><br>\r\n\r\n\r\n![1-7.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/yMEowFcE63159b3fd43a6.png)\r\n\r\n<br>\r\n点击“Write Contract”按钮，你应该可以把你的钱包连接到 Etherscan 网站上，然后调用“increment”函数。在点击按钮以后，MetaMask 会弹出，对交易签名（注意你需要使用 Rinkeby 网络）。在你的交易被成功写入区块以后，你可以回到“Read Contact”区域，然后再次调用“getCurrent”函数，会发现现在的 counter 变量变成 1 了。\r\n<br><br>\r\n\r\n![1-8.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/JxxXvAXy63159b634c6c8.png)\r\n\r\n\r\n## 通过 Flattener 插件验证多 Solidity 文件的\r\n<p>刚才是在 Etherscan 上的合约验证过程，但是刚才的例子是单一 Solidity 文件，通常情况下我们要处理的不是单一的 Solidity 文件，因为你在智能合约中经常会引入其他的合约，接口和库。<\/p>\r\n\r\n让我们使用 Chainlink 的 Price Feed Consumer 合约作为例子，创建一个新的 Solidity 文件，名字叫“PriceFeedConsumer.sol”，下面的代码是从[ Chainlink 官方文档](https:\/\/docs.chain.link\/docs\/get-the-latest-price\/)中粘贴的：\r\n\r\n```\r\n\/\/ SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.7;\r\nimport \"@chainlink\/contracts\/src\/v0.8\/interfaces\/AggregatorV3Interface.sol\";\r\n\r\ncontract PriceConsumerV3 {\r\n    AggregatorV3Interface internal priceFeed;\r\n    \/**\r\n     * Network: Rinkeby\r\n     * Aggregator: ETH\/USD\r\n     * Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e\r\n     *\/\r\n   constructor() {\r\n        priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);\r\n    }\r\n\r\n   \/**\r\n     * Returns the latest price\r\n     *\/\r\n\r\n   function getLatestPrice() public view returns (int) {\r\n        (\r\n            \/*uint80 roundID*\/,\r\n            int price,\r\n            \/*uint startedAt*\/,\r\n            \/*uint timeStamp*\/,\r\n            \/*uint80 answeredInRound*\/\r\n       ) = priceFeed.latestRoundData();\r\n        return price;\r\n    }\r\n}\r\n```\r\n\r\n\r\n`“import “@chainlink\/contracts\/src\/v0.8\/interfaces\/AggregatorV3Interface.sol”;”`这一行意味着我们需要引入其他接口，接口不是一个智能合约，它会列出相关的函数，但是没有实现的函数体。接口有两个作用，第一个是被某一个智能合约继承从而实现列出的函数，第二个是用来调用实现了这些函数的某个合约。在这个例子中，我们会用到它的第二个作用，即调用 Chainlink Aggregator 合约中的“latestRoundData”函数。<\/p>\r\n\r\n我们还是通过 0.8.7 的 Solidity 编译器版本，License 还是使用 MIT，我们可以从第一行中看到。<\/p>\r\n\r\n在成功部署以后，回到 Remix IDE，找到“PriceFeedConsumer.sol”，右键点击，然后点击“Flatten”。\r\n<br>\r\n\r\n![1-9.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/UcdTvQta63159d9486ac6.png)\r\n\r\n<br>\r\n这个命令会生成一个新的文件叫做“PriceFeedConsumer_flat.sol”，这个文件将会把所有的 import 都换成被引入合约，接口或者库的源代码。\r\n<br>\r\n\r\n![1-10.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/rARN2Il263159db69326c.png)\r\n\r\n<br>\r\n可以注意一下 Remix IDE 有一个 “Flatten”的页面，会被自动激活。第二种将合约 flatten 的方法就是点击左下角的“Extension”按钮（在“Settings”按钮之上，样子是一个电源插头）然后点击“Flattener”旁边的绿色的“Activate”按钮。\r\n<br><br>\r\n\r\n![1-11.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/XPsTHMKG63159ddd47fcf.png)\r\n<br>\r\n然后，到 Flattener extension 页面，点击“Flatten PriceFeedConsumer.sol”按钮。注意这个动作不会创建新的文件，而是将已经 flatten 的源代码复制到剪切板，以便我们可以将它粘贴到 Etherscan 的验证页面。\r\n\r\n用哪种方法来 flatten 你的合约取决与你。\r\n现在，当我们到 Etherscan 的验证页面后，像上次操作一样，选择：\r\n- For Compiler Type — Solidity (Single File)\r\n- For Compiler Version—- v0.8.7+commit.e28d00a7\r\n- For Open Source License Type — MIT License (MIT)\r\n\r\n然后点击“Continue”按钮。\r\n\r\n在接下来的页面，在文本框“Enter the Solidity Contract Code below”中，粘贴“PriceFeedConsumer_flat.sol”文件。\r\n\r\n完成人机验证，然后点击“Verify and Publish”按钮。\r\n\r\n## 使用 Etherscan 插件完成多个 Solidity 文件的验证\r\n\r\n另外一种验证包含多个 Solidity 文件合约的方法是使用“Etherscan – Contract Verification”这个Remix IDE 插件。\r\n\r\n我们使用已经写好的“PriceFeedConsumer.sol”合约，再次部署它。在此之后，在 Extension 中激活 “Etherscan – Contract Verification” 插件。\r\n<br>\r\n\r\n![1-12.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/M65L6QUN63159e854252f.png)\r\n\r\n<br>\r\n现在到 [Etherscan](https:\/\/etherscan.io\/register) 然后注册一个账户，在你的账户设置中，找到“API Keys”部分，生成一个免费的 API key。\r\n\r\n然后回到 Remix IDE，点击“Etherscan – Contract Verification”，将你的 API Key 粘贴在这里，点击“Save API key”按钮。\r\n\r\n<br>\r\n\r\n![1-13.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/6cYS9SG863159ebed3bf6.png)\r\n\r\n<br>\r\n然后选择你想要验证的的合约，提供合约地址，点击“Verify Contract”。好了，你的合约现在就已经在 Etherscan 中被验证了。\r\n<br><br>\r\n\r\n![1-14.png](https:\/\/img.learnblockchain.cn\/attachments\/2022\/09\/yT9Ljh7B63159ed63b092.png)\r\n\r\n\r\n## 总结\r\n\r\n在这篇文章中，我们学会了如何通过 Remix 和 Etherscan 以多种方法验证智能合约。\r\n您可以关注 Chainlink 预言机并且私信加入开发者社区，有大量关于智能合约的学习资料以及关于区块链的话题！"},"author":{"user":"https:\/\/learnblockchain.cn\/people\/398","address":null},"history":"Qmd7jgBmYWBUp2d5rbVjTxBFgRUJNJszFmwVueFD6Ygv9W","timestamp":1662362227,"version":1}