Eu recentemente comecei a estudar solidity novamente, revisando os detalhes e escrevendo um "WTF Solidity Guia Básico" para iniciantes. Serão lançadas de 1 a 3 aulas por semana.
Siga-me no Twitter: @0xAA_Science
Comunidade técnica do WTF no Discord, com informações sobre como entrar no grupo do WeChat: link
Todo o código e tutoriais estão disponíveis no GitHub: github.com/AmazingAng/WTF-Solidity
Hardhat é o ambiente de desenvolvimento mais popular para Ethereum. Ele pode ajudar você a compilar e implantar contratos inteligentes e fornece suporte para testar e executar Solidity na rede Hardhat. Nesta aula, vamos aprender como instalar o Hardhat, escrever e compilar contratos usando o Hardhat e executar testes simples.
Você pode usar o nvm para instalar o Node.js
Abra o terminal e digite:
mkdir hardhat-demo
cd hardhat-demo
npm init -y
npm install --save-dev hardhat
Abra o terminal e digite:
cd hardhat-demo
npx hardhat
Escolha a terceira opção: "Create an empty hardhat.config.js"
👷 Welcome to Hardhat v2.9.9 👷
? What do you want to do? …
Create a JavaScript project
Create a TypeScript project
❯ Create an empty hardhat.config.js
Quit
npm install --save-dev @nomicfoundation/hardhat-toolbox
Adicione o plugin ao seu arquivo de configuração do hardhat hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.9",
};
Se você já usou o Remix, ao salvar o contrato ele será compilado automaticamente. Mas no ambiente de desenvolvimento local do Hardhat, você precisa compilar o contrato manualmente.
Crie um diretório chamado contracts
e adicione o contrato ERC20 da aula 31.
Use o contrato da aula 31 do WTF Solidity
// SPDX-License-Identifier: MIT
// WTF Solidity by 0xAA
pragma solidity ^0.8.21;
import "./IERC20.sol";
contract ERC20 is IERC20 {
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;
uint256 public override totalSupply; // 代币总供给
string public name; // 名称
string public symbol; // 符号
uint8 public decimals = 18; // 小数位数
// @dev 在合约部署的时候实现合约名称和符号
constructor(string memory name_, string memory symbol_){
name = name_;
symbol = symbol_;
}
// @dev 实现`transfer`函数,代币转账逻辑
function transfer(address recipient, uint amount) external override returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
// @dev 实现 `approve` 函数, 代币授权逻辑
function approve(address spender, uint amount) external override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
// @dev 实现`transferFrom`函数,代币授权转账逻辑
function transferFrom(
address sender,
address recipient,
uint amount
) external override returns (bool) {
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
// @dev 铸造代币,从 `0` 地址转账给 调用者地址
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
// @dev 销毁代币,从 调用者地址 转账给 `0` 地址
function burn(uint amount) external {
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
}
npx hardhat compile
Se você vir a seguinte saída, significa que o contrato foi compilado com sucesso:
Compiling 2 Solidity files successfully
Após a compilação, você verá a pasta artifacts
no diretório, que contém os arquivos json
resultantes da compilação.
Os testes unitários são muito simples e apenas verificam se o contrato foi implantado corretamente (se o endereço do contrato é válido).
Crie uma pasta chamada test
e dentro dela crie um arquivo chamado test.js
. Nos testes unitários, usaremos as bibliotecas chai
e ethers.js
, que são usadas para testar e interagir com a blockchain, respectivamente. Se você não está familiarizado com o ethers.js
, pode dar uma olhada nas primeiras 6 aulas do WTF Ethers Tutorial. Nos próximos tutoriais, vamos explorar mais detalhes sobre o chai
e o mocha
.
const { expect } = require('chai');
const { ethers } = require('hardhat');
describe("Teste do contrato ERC20", ()=>{
it("Implantação do contrato", async () => {
// ethers.getSigners, representa as contas eth
// ethers é uma função global que pode ser chamada diretamente
const [owner, addr1, addr2] = await ethers.getSigners();
// O ContractFactory em ethers.js é usado para implantar novos contratos inteligentes, então aqui o Token é a fábrica de instâncias do contrato de token. ERC20 representa o arquivo ERC20.sol na pasta contracts
const Token = await ethers.getContractFactory("ERC20");
// Implantação do contrato, passando os argumentos do construtor do ERC20.sol, que são name e symbol, ambos chamados de WTF
const hardhatToken = await Token.deploy("WTF", "WTF");
// Obtendo o endereço do contrato
const ContractAddress = await hardhatToken.address;
expect(ContractAddress).to.properAddress;
});
})
No terminal, digite o seguinte comando para executar os testes:
npx hardhat test
# Se você tiver vários arquivos de teste e quiser executar um arquivo específico, use
npx mocha test/test.js
Se você vir a seguinte saída, significa que os testes foram executados com sucesso.
Teste do contrato ERC20
✔ Implantação do contrato (1648ms)
1 passing (2s)
No Remix, basta clicar em "deploy" para implantar o contrato. Mas no Hardhat local, precisamos escrever um script de implantação.
Crie uma pasta chamada scripts
e escreva um script de implantação do contrato. Em seguida, crie um arquivo chamado deploy.js
dentro dessa pasta.
Digite o seguinte código:
// Podemos executar o script desejado usando npx hardhat run <script>
// Aqui você pode usar npx hardhat run deploy.js para executar
const hre = require("hardhat");
async function main() {
const Contract = await hre.ethers.getContractFactory("ERC20");
const token = await Contract.deploy("WTF","WTF");
await token.deployed();
console.log("Contrato implantado com sucesso:", token.address);
}
// Executando o script
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Execute o seguinte comando para implantar o contrato na rede de teste local:
O Hardhat fornece uma rede padrão, consulte: Rede padrão do Hardhat
npx hardhat run --network hardhat scripts/deploy.js
Se você vir a seguinte saída, significa que o contrato foi implantado com sucesso:
(node:45779) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Contrato implantado com sucesso: 0x5FbDB2315678afecb367f032d93F642f64180aa3
- Solicite uma chave de API da Alchemy Consulte Aula 4: Alchemy, API Blockchain e Infraestrutura de Nós
- Solicite tokens de teste Goerli Clique aqui para solicitar Faça login na sua conta Alchemy e você poderá receber 0,2 tokens de teste por dia.
- Exporte a chave privada Como precisamos implantar o contrato na rede de teste Goerli, a conta de teste deve ter alguns tokens de teste. Exporte a chave privada da conta de teste que já possui tokens de teste para implantar o contrato.
- Solicite uma chave de API do Etherscan para verificar o contrato Clique aqui para solicitar
No arquivo hardhat.config.js
, podemos configurar várias redes, aqui vamos configurar a rede de teste Goerli.
Edite o arquivo hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
// Solicite uma chave de API da Alchemy
const ALCHEMY_API_KEY = "KEY";
// Substitua esta chave privada pela chave privada da sua conta de teste
// Exporte sua chave privada do Metamask, abra o Metamask e vá para "Detalhes da conta"> "Exportar chave privada"
// Atenção: nunca coloque ETH real em uma conta de teste
const GOERLI_PRIVATE_KEY = "YOUR GOERLI PRIVATE KEY";
// Solicite uma chave de API do Etherscan
const ETHERSCAN_API_KEY = "YOUR_ETHERSCAN_API_KEY";
module.exports = {
solidity: "0.8.9", // Versão de compilação do solidity
networks: {
goerli: {
url: `https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [GOERLI_PRIVATE_KEY]
}
},
etherscan: {
apiKey: ETHERSCAN_API_KEY,
},
};
Após a configuração, execute o seguinte comando para implantar o contrato na rede de teste Goerli:
npx hardhat run --network goerli scripts/deploy.js
Agora você implantou seu contrato na rede de teste Goerli.
Se você vir a seguinte saída, significa que o contrato foi implantado com sucesso na rede de teste Goerli:
(node:46996) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46999) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Contrato implantado com sucesso: 0xeEAcef71084Dd1Ae542***9D8F64E3c68e15****
Você pode verificar o contrato no etherscan
Da mesma forma, você pode configurar várias redes, como mainnet
, rinkeby
, etc.
Por fim, verifique seu contrato:
npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1"
Nesta aula, aprendemos o básico do Hardhat. Com o Hardhat, podemos criar projetos de Solidity de forma mais estruturada e ele fornece muitos recursos úteis. Nos próximos artigos, exploraremos recursos avançados do Hardhat, como plugins e frameworks de teste.