前面提到嘉竟,我最近在看 Web3,這不記錄下最近看到的好玩的挺智。
忘了在哪里看到的一句話扎筒,Web3 這個(gè)東西,剛看時(shí)讓人摸不到頭腦的點(diǎn)在于涣仿,你很難知道要用哪些東西去組裝勤庐,去哪里拿數(shù)據(jù)。
比如都說(shuō)區(qū)塊鏈人人可訪問(wèn)好港,我要到哪里看到它愉镰?畢竟看得見(jiàn)的東西更讓人心安。
給俺瞧瞧钧汹。
我到哪里去看區(qū)塊鏈上的數(shù)據(jù)凰兑?不給你 區(qū)塊鏈瀏覽器
這個(gè)關(guān)鍵詞寞缝,大概很難知曉。
一個(gè)經(jīng)常會(huì)看到的疑問(wèn)是如何與合約交互,比如桩警,合約里存了一個(gè)字符串,我現(xiàn)在要將其展示到頁(yè)面上哄陶,如何搞琳省?
這玩意是去中心化的呀,沒(méi)有一個(gè) API 地址讓你去連呀嗤形,于是就迷茫了精偿。。。
笔咽。搔预。。
叶组。拯田。。
甩十。船庇。。
其實(shí) Web3 里的很多東西侣监,就是一張紙鸭轮,沒(méi)啥,與智能合約交互其實(shí)就是要和節(jié)點(diǎn)交互橄霉,但維護(hù)全節(jié)點(diǎn)也太難受了窃爷。
那么就換一種方案就是使用別人維護(hù)的節(jié)點(diǎn),其實(shí)就是連接輕節(jié)點(diǎn)提供商姓蜂,比如 MetaMask 或者 Alchemy按厘,當(dāng)然了,這里有去中心化的取舍了钱慢。
廢話說(shuō)完了逮京,進(jìn)入正題。
通過(guò)使用 Hardhat Alchemy Solidity 來(lái)走一下智能合約開(kāi)發(fā)部署流程滩字。
- Hardhat 創(chuàng)建項(xiàng)目
- 實(shí)現(xiàn)一個(gè) Hello World 智能合約
- mocha 來(lái)測(cè)試合約
- 如何將合約部署到區(qū)塊網(wǎng)絡(luò)
- 如何驗(yàn)證已經(jīng)部署的合約
1. 環(huán)境搭建
前提條件造虏,前端常用的環(huán)境 node 就不多說(shuō)了。
打開(kāi) Hardhat 官網(wǎng)麦箍,照著文檔一把梭漓藕,把它當(dāng)成一個(gè)幫你創(chuàng)建合約項(xiàng)目的一個(gè)腳手架就完了。
注意挟裂,Hardhat 更新很快享钞,一些教程可能不是很準(zhǔn)確,沒(méi)事看看官網(wǎng)文檔就好了诀蓉。
npx hardhat
下面是執(zhí)行時(shí)終端輸出:
cemcoe@cemcoe MINGW64 ~/workplace/web3gogogo/contracts (main)
$ npx hardhat
Need to install the following packages:
hardhat
Ok to proceed? (y) y
888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
Welcome to Hardhat v2.10.2
? What do you want to do? ...
> Create a JavaScript project
Create a TypeScript project
Create an empty hardhat.config.js
Quit
選擇 Create a JavaScript project
栗竖,并回車(chē)。注意渠啤,按照輸出狐肢,這里還需要裝點(diǎn)東西:
cemcoe@cemcoe MINGW64 ~/workplace/web3gogogo/contracts (main)
$ npx hardhat
Need to install the following packages:
hardhat
Ok to proceed? (y) y
888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
Welcome to Hardhat v2.10.2
√ What do you want to do? · Create a JavaScript project
√ Hardhat project root: · C:\Users\cemcoe\workplace\web3gogogo\contracts
√ Do you want to add a .gitignore? (Y/n) · y
You need to install these dependencies to run the sample project:
npm install --save-dev "hardhat@^2.10.2" "@nomicfoundation/hardhat-toolbox@^1.0.1"
Project created
See the README.md file for some example tasks you can run
Give Hardhat a star on Github if you're enjoying it!
https://github.com/NomicFoundation/hardhat
聽(tīng)話,按照它說(shuō)的做沥曹,把依賴(lài)都裝上:
npm install --save-dev "hardhat@^2.10.2" "@nomicfoundation/hardhat-toolbox@^1.0.1"
基本環(huán)境就好了份名,可以開(kāi)心寫(xiě)合約玩了碟联。
2. 看下目錄
哦,天呀僵腺,小寶貝鲤孵,打開(kāi)目錄看一下吧。
國(guó)際慣例辰如,寫(xiě)個(gè) HelloWorld 先普监。
到 contracts 目錄下按照 Lock.sol 來(lái)畫(huà) HelloWorld,這個(gè)文件要盡可能簡(jiǎn)單琉兜,現(xiàn)在的重點(diǎn)在于合約的編譯部署和驗(yàn)證凯正。
合約大概長(zhǎng)這樣:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract HelloWorld {
string public _string = "Hello, World! My Name is cemcoe!";
}
好了,合約不用管了呕童,畢竟不是本文的重點(diǎn)漆际。
3. 寫(xiě)個(gè)測(cè)試
下面為合約寫(xiě)個(gè)測(cè)試,不同于前端夺饲,合約的安全是重重重重點(diǎn),畢竟里面存的是資產(chǎn)施符,測(cè)試就不能少了往声。
https://hardhat.org/hardhat-runner/docs/guides/test-contracts
這里測(cè)試是 Chai 和 Mocha 提供的能力,需要注意的是 chai 僅僅是一個(gè)assertion library戳吝,不是JavaScript test framework浩销。
下面代碼中的 describe 以及 it 并不是由 chai 提供的,所以在 chai 的官網(wǎng)你是找不到這倆貨的听哭,我在 chai 的官網(wǎng)找半天it慢洋。。陆盘。
到 test 下創(chuàng)建同名文件來(lái)測(cè)試一下合約普筹,測(cè)試寫(xiě)完那就運(yùn)行一下。
主要是下面的代碼沒(méi)有 mocha 的影子隘马,但其實(shí) Hardhat 的文檔里有提到太防。
const {
time,
loadFixture,
} = require("@nomicfoundation/hardhat-network-helpers");
const { expect } = require("chai");
// chai 僅僅是一個(gè)assertion library,不是JavaScript test framework
// 下面describe以及it并不是由chai提供的酸员,所以在chai的官網(wǎng)你是找不到這倆貨的
// https://mochajs.org/
// 比起簡(jiǎn)單的語(yǔ)法蜒车,上面的認(rèn)知還是蠻重要的
describe("HelloWorld", function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deployOneYearLockFixture() {
// Contracts are deployed using the first signer/account by default
const [owner] = await ethers.getSigners();
const CONTRACT = await ethers.getContractFactory("HelloWorld");
const contract = await CONTRACT.deploy();
return { contract, owner };
}
describe("Deployment", function () {
it("Should set the right string", async function () {
const { contract } = await loadFixture(deployOneYearLockFixture);
expect(await contract._string()).to.equal(
"Hello, World! My Name is cemcoe!"
);
});
});
});
運(yùn)行一下測(cè)試腳本
$ npx hardhat test ./test/0.HelloWorld.test.js
Compiled 3 Solidity files successfully
HelloWorld
Deployment
? Should set the right string (3150ms)
1 passing (3s)
bingo,測(cè)試完成幔嗦。
4. 部署到測(cè)試網(wǎng)絡(luò)
目前為止酿愧,其實(shí)一直是關(guān)上門(mén)稱(chēng)王稱(chēng)霸,現(xiàn)在將合約發(fā)布到測(cè)試網(wǎng)絡(luò)吧邀泉。
這里要找一個(gè)服務(wù)商嬉挡,幫忙上鏈钝鸽,什么,你不想要中間商棘伴,嗯寞埠,把握重點(diǎn)吧伙計(jì)。
到這里 https://www.alchemy.com/ 注冊(cè)一個(gè)賬號(hào)拿到key焊夸,并將相應(yīng)信息配置到hardhat.config.js
文件中仁连,像下面這樣:
networks: {
goerli: {
url: GOERLI_URL,
accounts: [PRIVATE_KEY],
},
polygonMumbai: {
url: process.env.MUMBAI_URL,
accounts: [process.env.PRIVATE_KEY],
},
optimismGoerli: {
url: OPTIMISM_GOERLI_URL,
accounts: [PRIVATE_KEY],
},
},
當(dāng)然,我這里用了一下 dotenv 來(lái)存敏感信息阱穗,為了體驗(yàn)編譯部署流程可以直接寫(xiě)死在文件中饭冬。
你可以只配置一個(gè)網(wǎng)絡(luò),比如 polygonMumbai揪阶,其中 MUMBAI_URL 是申請(qǐng)的URL昌抠,而 PRIVATE_KEY 是你錢(qián)包地址的私鑰,做好自己的風(fēng)險(xiǎn)控制鲁僚,別把自己存有資產(chǎn)的錢(qián)包密鑰泄露炊苫。
配置文件搞好以后就來(lái)寫(xiě)一個(gè)部署腳本好了。其實(shí)很簡(jiǎn)單冰沙。
const hre = require("hardhat");
async function main() {
const CONTRACT = await hre.ethers.getContractFactory("HelloWorld");
const contract = await CONTRACT.deploy();
await contract.deployed();
console.log(`contract deployed to ${contract.address}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
核心代碼就三句侨艾。。拓挥。
配置文件和部署腳本都寫(xiě)好以后就可以開(kāi)始部署了唠梨。
npx hardhat run scripts/0.HelloWorld.deploy.js --network polygonMumbai
$ npx hardhat run scripts/0.HelloWorld.deploy.js --network polygonMumbai
Compiled 1 Solidity file successfully
contract deployed to 0x8487Ec50f29d1d36Cb422d6f45AA1ef38Cd2bBA2
5. 驗(yàn)證合約
驗(yàn)證合約的目的是讓合約代碼在區(qū)塊瀏覽器上可讀。
和部署合約類(lèi)似要先寫(xiě)一下申請(qǐng)賬號(hào)侥啤,再配置文件当叭,然后運(yùn)行腳本,一步一步來(lái)盖灸。
先到對(duì)應(yīng)的區(qū)塊瀏覽器去申請(qǐng)key蚁鳖,這里是 https://mumbai.polygonscan.com/
然后將key配置到hardhat.config.js文件中。
etherscan: {
apiKey: {
goerli: process.env.ETHERSCAN_API_KEY,
polygonMumbai: process.env.POLYGONSCAN_API_KEY,
// optimismGoerli 不在默認(rèn)配置中
optimismGoerli: "abc",
},
},
當(dāng)然了糠雨,仍然是按需配置才睹,需要什么網(wǎng)絡(luò)就到對(duì)應(yīng)的區(qū)塊瀏覽器去拿key再配置進(jìn)去。
有了key甘邀,配置文件琅攘,再加上部署的合約的地址,就可以驗(yàn)證合約了松邪。
npx hardhat verify --network polygonMumbai 0x8487Ec50f29d1d36Cb422d6f45AA1ef38Cd2bBA2
一條龍完成坞琴。
$ npx hardhat verify --network polygonMumbai 0x8487Ec50f29d1d36Cb422d6f45AA1ef38Cd2bBA2
Nothing to compile
Successfully submitted source code for contract
contracts/0.HelloWorld.sol:HelloWorld at 0x8487Ec50f29d1d36Cb422d6f45AA1ef38Cd2bBA2
for verification on the block explorer. Waiting for verification result...
Successfully verified contract HelloWorld on Etherscan.
https://mumbai.polygonscan.com/address/0x8487Ec50f29d1d36Cb422d6f45AA1ef38Cd2bBA2#code
注意, goerli 或其它網(wǎng)絡(luò)驗(yàn)證合約時(shí)逗抑,因網(wǎng)絡(luò)原因會(huì)出現(xiàn) Error in plugin @nomiclabs/hardhat-etherscan: Failed to send contract verification request. 的情況剧辐。
$ npx hardhat verify --network goerli 0x7520A14646eF8d8123e88937DcB39604E8E70CeA
Nothing to compile
Error in plugin @nomiclabs/hardhat-etherscan: Failed to send contract verification request.
Endpoint URL: https://api-goerli.etherscan.io/api
Reason: Connect Timeout Error