12  Prática sobre Ferramentas de Desenvolvimento e Frameworks Ethereum: Testes e Deploy de Contratos com Hardhat

Introdução aos Testes e Deploy com Hardhat

Resumo
Nesta aula são apresentadas algumas ferramentas de Desenvolvimento e Frameworks para o desenvolvimento e implantação de Contratos Inteligentes. Introduzimos o hardhat, que como vimos pode ser utilizado para testar, e agora vamos explorar o comando migrate para fazermos a implantação dos contratos. Iremos fazer o deploy para as redes simuladas do hardhat e para a Rede Privada Local, a etherprivate.

12.1 Introdução

O HardHat é um toolkit parecido com o Truffle. É uma suíte de ferramentas para ajudar na criação de contratos inteligentes, automatizando o desenvolvimento. É desenvolvido em Node.js e por isso que precisamos ter o Node instalado antes.

12.2 Instalação das Ferramentas

Para instalar o HardHat vamos usar o npm, o gerenciador de pacotes do Node. Primeiro crie uma pasta para o seu projeto, vou chamar de projeto-hello-solidity-hardhat e depois inicialize ela com o npm e instale o HardHat, como abaixo.

  1. Instale o VSCode e a extensão Solidity da empresa Nomic Foundation.

  2. Instale o Hardhat.

$ npm init -y
$ npm install -D hardhat

Comandos possíves com o Hardhat:

$ npx hardhat --help
Hardhat version 2.22.15

Usage: hardhat [GLOBAL OPTIONS] [SCOPE] <TASK> [TASK OPTIONS]

GLOBAL OPTIONS:

  --config              A Hardhat config file. 
  --emoji               Use emoji in messages. 
  --flamegraph          Generate a flamegraph of your Hardhat tasks 
  --help                Shows this message, or a task's help if its name is provided 
  --max-memory          The maximum amount of memory that Hardhat can use. 
  --network             The network to connect to. 
  --show-stack-traces   Show stack traces (always enabled on CI servers). 
  --tsconfig            A TypeScript config file. 
  --typecheck           Enable TypeScript type-checking of your scripts/tests 
  --verbose             Enables Hardhat verbose logging 
  --version             Shows hardhat's version. 


AVAILABLE TASKS:

  check                 Check whatever you need
  clean                 Clears the cache and deletes all artifacts
  compile               Compiles the entire project, building all artifacts
  console               Opens a hardhat console
  coverage              Generates a code coverage report for tests
  flatten               Flattens and prints contracts and their dependencies. If no file is passed, all the contracts in the project will be flattened.
  gas-reporter:merge 
  help                  Prints this message
  node                  Starts a JSON-RPC server on top of Hardhat Network
  run                   Runs a user-defined script after compiling the project
  test                  Runs mocha tests
  typechain             Generate Typechain typings for compiled contracts
  verify                Verifies a contract on Etherscan or Sourcify


AVAILABLE TASK SCOPES:

  ignition              Deploy your smart contracts using Hardhat Ignition
  vars                  Manage your configuration variables

To get help for a specific task run: npx hardhat help [SCOPE] <TASK>

Mais detalhes de como utilizar o Hardhat podem ser vistos no tutorial do luiztools.

12.3 Criando a estrutura básica do projeto com Hardhat

Iremos criar a estrutura de um projeto básico. Crie um diretório com o nome do projeto, aqui estou utilizando o nome projeto-hello-solidity-hardhat-v2-ts, para a versão \(2\) do hardhat e que utilizará TypeScript. Crie e acesse o diretório e o acesse:

$ mkdir projeto-hello-solidity-hardhat-v2-ts
$ mv package.json projeto-hello-solidity-hardhat-v2-ts/
$ cd projeto-hello-solidity-hardhat-v2-ts/
[projeto-hello-solidity-hardhat-v2-ts]$

Utilizaremos o node \(22\):

[projeto-hello-solidity-hardhat-v2-ts]$ nvm install 22
Downloading and installing node v22.20.0...
Downloading https://nodejs.org/dist/v22.20.0/node-v22.20.0-linux-x64.tar.xz...
################################################################ 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v22.20.0 (npm v10.9.3)

Se a versão \(22\) já estiver instalada a mensagem de confirmação irá ser exibida:

[projeto-hello-solidity-hardhat-v2-ts]$ nvm install 22
v22.20.0 is already installed.
Now using node v22.20.0 (npm v10.9.3)
[projeto-hello-solidity-hardhat-v2-ts]$ 

Utilize o comando npm init -y para inicializar os recursos do node:

[projeto-hello-solidity-hardhat-v2-ts]$ npm init -y
Wrote to /home/rag/projeto-hello-solidity-hardhat-v2-ts/package.json:

{
  "name": "projeto-hello-solidity-hardhat-v2-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Inicialize o hardhat no projeto e escolha entre a versão \(2\) ou \(3\):

[rag@backporting projeto-hello-solidity-hardhat-v2-ts]$ npx hardhat --init

 █████  █████                         ███  ███                  ███      ██████
░░███  ░░███                         ░███ ░███                 ░███     ███░░███
 ░███   ░███   ██████  ████████   ███████ ░███████    ██████  ███████  ░░░  ░███
 ░██████████  ░░░░░███░░███░░███ ███░░███ ░███░░███  ░░░░░███░░░███░      ████░
 ░███░░░░███   ███████ ░███ ░░░ ░███ ░███ ░███ ░███   ███████  ░███      ░░░░███
 ░███   ░███  ███░░███ ░███     ░███ ░███ ░███ ░███  ███░░███  ░███ ███ ███ ░███
 █████  █████░░███████ █████    ░░███████ ████ █████░░███████  ░░█████ ░░██████
░░░░░  ░░░░░  ░░░░░░░ ░░░░░      ░░░░░░░ ░░░░ ░░░░░  ░░░░░░░    ░░░░░   ░░░░░░
 
👷 Welcome to Hardhat v3.0.6 👷

? Which version of Hardhat would you like to use? … 
▸ Hardhat 3 Beta (recommended for new projects)
  Hardhat 2 (older version)

Escolhendo a versão \(2\) e o tipo de projeto “A Typescript project using Mocha and Ethers.js”:

[projeto-hello-solidity-hardhat-v2-ts]$ npx hardhat --init 

 █████  █████                         ███  ███                  ███      ██████
░░███  ░░███                         ░███ ░███                 ░███     ███░░███
 ░███   ░███   ██████  ████████   ███████ ░███████    ██████  ███████  ░░░  ░███
 ░██████████  ░░░░░███░░███░░███ ███░░███ ░███░░███  ░░░░░███░░░███░      ████░
 ░███░░░░███   ███████ ░███ ░░░ ░███ ░███ ░███ ░███   ███████  ░███      ░░░░███
 ░███   ░███  ███░░███ ░███     ░███ ░███ ░███ ░███  ███░░███  ░███ ███ ███ ░███
 █████  █████░░███████ █████    ░░███████ ████ █████░░███████  ░░█████ ░░██████
░░░░░  ░░░░░  ░░░░░░░ ░░░░░      ░░░░░░░ ░░░░ ░░░░░  ░░░░░░░    ░░░░░   ░░░░░░
 
👷 Welcome to Hardhat v3.0.6 👷

✔ Which version of Hardhat would you like to use? · hardhat-2
✔ Where would you like to initialize the project?

Please provide either a relative or an absolute path: · .
? What type of project would you like to initialize? … 
  A Javascript project using Mocha and Ethers.js
  A Javascript project using Mocha and Ethers.js (ESM)
▸ A Typescript project using Mocha and Ethers.js
  A Typescript project using Mocha and Viem
  An empty config file (hardhat.config.js)

Escolhendo a versão \(3\):

[projeto-hello-solidity-hardhat-v3-ts]$ npx hardhat --init 

 █████  █████                         ███  ███                  ███      ██████
░░███  ░░███                         ░███ ░███                 ░███     ███░░███
 ░███   ░███   ██████  ████████   ███████ ░███████    ██████  ███████  ░░░  ░███
 ░██████████  ░░░░░███░░███░░███ ███░░███ ░███░░███  ░░░░░███░░░███░      ████░
 ░███░░░░███   ███████ ░███ ░░░ ░███ ░███ ░███ ░███   ███████  ░███      ░░░░███
 ░███   ░███  ███░░███ ░███     ░███ ░███ ░███ ░███  ███░░███  ░███ ███ ███ ░███
 █████  █████░░███████ █████    ░░███████ ████ █████░░███████  ░░█████ ░░██████
░░░░░  ░░░░░  ░░░░░░░ ░░░░░      ░░░░░░░ ░░░░ ░░░░░  ░░░░░░░    ░░░░░   ░░░░░░
 
👷 Welcome to Hardhat v3.0.6 👷

✔ Which version of Hardhat would you like to use? · hardhat-3
✔ Where would you like to initialize the project?

Please provide either a relative or an absolute path: · .
? What type of project would you like to initialize? … 
  A Javascript project using Mocha and Ethers.js
  A Javascript project using Mocha and Ethers.js (ESM)
▸ A Typescript project using Mocha and Ethers.js
  A Typescript project using Mocha and Viem
  An empty config file (hardhat.config.js)

Escolhendo a versão Typescript:

[projeto-hello-solidity-hardhat-v3-ts]$ npx hardhat --init 

 █████  █████                         ███  ███                  ███      ██████
░░███  ░░███                         ░███ ░███                 ░███     ███░░███
 ░███   ░███   ██████  ████████   ███████ ░███████    ██████  ███████  ░░░  ░███
 ░██████████  ░░░░░███░░███░░███ ███░░███ ░███░░███  ░░░░░███░░░███░      ████░
 ░███░░░░███   ███████ ░███ ░░░ ░███ ░███ ░███ ░███   ███████  ░███      ░░░░███
 ░███   ░███  ███░░███ ░███     ░███ ░███ ░███ ░███  ███░░███  ░███ ███ ███ ░███
 █████  █████░░███████ █████    ░░███████ ████ █████░░███████  ░░█████ ░░██████
░░░░░  ░░░░░  ░░░░░░░ ░░░░░      ░░░░░░░ ░░░░ ░░░░░  ░░░░░░░    ░░░░░   ░░░░░░
 
👷 Welcome to Hardhat v3.0.6 👷

✔ Which version of Hardhat would you like to use? · hardhat-3
✔ Where would you like to initialize the project?

Please provide either a relative or an absolute path: · .
✔ What type of project would you like to initialize? · mocha-ethers-ts
✨ Template files copied ✨
✔ You need to install the necessary dependencies using the following command:
npm install --save-dev "@nomicfoundation/hardhat-chai-matchers@^2.0.0" "@nomicfoundation/hardhat-ethers@^3.0.0" "@nomicfoundation/hardhat-ignition@^0.15.0" "@nomicfoundation/hardhat-ignition-ethers@^0.15.0" "@nomicfoundation/hardhat-network-helpers@^1.0.0" "@nomicfoundation/hardhat-toolbox@^6.0.0" "@nomicfoundation/hardhat-verify@^2.0.0" "@typechain/ethers-v6@^0.5.0" "@typechain/hardhat@^9.0.0" "@types/chai@^4.2.0" "@types/mocha@>=9.1.0" "@types/node@>=20.0.0" "chai@^4.2.0" "ethers@^6.4.0" "hardhat@^2.14.0" "hardhat-gas-reporter@^2.3.0" "solidity-coverage@^0.8.0" "ts-node@>=8.0.0" "typechain@^8.3.0" "typescript@>=4.5.0"

Do you want to run it now? (Y/n) · true


npm install --save-dev "@nomicfoundation/hardhat-chai-matchers@^2.0.0" "@nomicfoundation/hardhat-ethers@^3.0.0" "@nomicfoundation/hardhat-ignition@^0.15.0" "@nomicfoundation/hardhat-ignition-ethers@^0.15.0" "@nomicfoundation/hardhat-network-helpers@^1.0.0" "@nomicfoundation/hardhat-toolbox@^6.0.0" "@nomicfoundation/hardhat-verify@^2.0.0" "@typechain/ethers-v6@^0.5.0" "@typechain/hardhat@^9.0.0" "@types/chai@^4.2.0" "@types/mocha@>=9.1.0" "@types/node@>=20.0.0" "chai@^4.2.0" "ethers@^6.4.0" "hardhat@^2.14.0" "hardhat-gas-reporter@^2.3.0" "solidity-coverage@^0.8.0" "ts-node@>=8.0.0" "typechain@^8.3.0" "typescript@>=4.5.0"
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated lodash.isequal@4.5.0: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@5.0.15: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported

added 583 packages, and audited 584 packages in 36s

115 packages are looking for funding
  run `npm fund` for details

15 low severity vulnerabilities

To address all issues possible (including breaking changes), run:
  npm audit fix --force

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.
✨ Dependencies installed ✨
Give Hardhat a star on Github if you're enjoying it! ⭐✨

     https://github.com/NomicFoundation/hardhat
[rag@backporting projeto-hello-solidity-hardhat]$ 
[projeto-hello-solidity-hardhat]$ npx hardhat --init

 █████  █████                         ███  ███                  ███      ██████
░░███  ░░███                         ░███ ░███                 ░███     ███░░███
 ░███   ░███   ██████  ████████   ███████ ░███████    ██████  ███████  ░░░  ░███
 ░██████████  ░░░░░███░░███░░███ ███░░███ ░███░░███  ░░░░░███░░░███░      ████░
 ░███░░░░███   ███████ ░███ ░░░ ░███ ░███ ░███ ░███   ███████  ░███      ░░░░███
 ░███   ░███  ███░░███ ░███     ░███ ░███ ░███ ░███  ███░░███  ░███ ███ ███ ░███
 █████  █████░░███████ █████    ░░███████ ████ █████░░███████  ░░█████ ░░██████
░░░░░  ░░░░░  ░░░░░░░ ░░░░░      ░░░░░░░ ░░░░ ░░░░░  ░░░░░░░    ░░░░░   ░░░░░░
 
👷 Welcome to Hardhat v3.0.6 👷

✔ Which version of Hardhat would you like to use? · hardhat-3
✔ Where would you like to initialize the project?

Please provide either a relative or an absolute path: · .
✔ What type of project would you like to initialize? · mocha-ethers
✔ Hardhat only supports ESM projects. Would you like to change "./package.json" to turn your project into ESM? (Y/n) · true

✨ Template files copied ✨
✔ You need to install the necessary dependencies using the following command:
npm install --save-dev "hardhat@^3.0.6" "@nomicfoundation/hardhat-toolbox-mocha-ethers@^3.0.0" "@nomicfoundation/hardhat-ignition@^3.0.0" "@types/chai@^4.2.0" "@types/chai-as-promised@^8.0.1" "@types/mocha@>=10.0.10" "@types/node@^22.8.5" "chai@^5.1.2" "ethers@^6.14.0" "forge-std@foundry-rs/forge-std#v1.9.4" "mocha@^11.0.0" "typescript@~5.8.0"

Do you want to run it now? (Y/n) · true


npm install --save-dev "hardhat@^3.0.6" "@nomicfoundation/hardhat-toolbox-mocha-ethers@^3.0.0" "@nomicfoundation/hardhat-ignition@^3.0.0" "@types/chai@^4.2.0" "@types/chai-as-promised@^8.0.1" "@types/mocha@>=10.0.10" "@types/node@^22.8.5" "chai@^5.1.2" "ethers@^6.14.0" "forge-std@foundry-rs/forge-std#v1.9.4" "mocha@^11.0.0" "typescript@~5.8.0"
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported

added 274 packages, and audited 275 packages in 36s

71 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
✨ Dependencies installed ✨
Give Hardhat a star on Github if you're enjoying it! ⭐✨

     https://github.com/NomicFoundation/hardhat

Executando o comando ls é possível verificarmos que a estrutura para o projeto foi criada.


[projeto-hello-solidity-hardhat]$ ls
contracts          node_modules       README.md  tsconfig.json
hardhat.config.ts  package.json       scripts
ignition           package-lock.json  test
[projeto-hello-solidity-hardhat]$ 

Se verificarem na versão \(2\) do hardhat, os diretórios criados contracts e test e estão com os arquivos Lock.sol e Lock.ts de exemplo, e foi criado um arquivo de configuração hardhat.config.ts.

Já na versão \(3\) do hardhat, os diretórios criados contracts e test e estão com os arquivos Counter.sol e Counter.t.sol em contracts e Counter.ts no diretório test. São arquivos de um exemplo de contrato e seu teste. Também foi criado um arquivo de configuração hardhat.config.ts.

  • contracts: diretório para os contratos.
  • test: diretório para os arquivos de teste.
  • hardhat.config.ts: Arquivo de configuração do Hardhat.

Executando outra vez o npm init -y, percebam que a lista de dependências foi atualizada para a versão \(2\):

[projeto-hello-solidity-hardhat-v2-ts]$ npm init -y
Wrote to /home/rag/projeto-hello-solidity-hardhat-v2-ts/package.json:

{
  "name": "projeto-hello-solidity-hardhat",
  "version": "1.0.0",
  "description": "This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@nomicfoundation/hardhat-chai-matchers": "^2.1.0",
    "@nomicfoundation/hardhat-ethers": "^3.1.0",
    "@nomicfoundation/hardhat-ignition": "^0.15.13",
    "@nomicfoundation/hardhat-ignition-ethers": "^0.15.14",
    "@nomicfoundation/hardhat-network-helpers": "^1.1.0",
    "@nomicfoundation/hardhat-toolbox": "^6.1.0",
    "@nomicfoundation/hardhat-verify": "^2.1.1",
    "@typechain/ethers-v6": "^0.5.1",
    "@typechain/hardhat": "^9.1.0",
    "@types/chai": "^4.3.20",
    "@types/mocha": "^10.0.10",
    "@types/node": "^24.6.2",
    "chai": "^4.5.0",
    "ethers": "^6.15.0",
    "hardhat": "^2.26.3",
    "hardhat-gas-reporter": "^2.3.0",
    "solidity-coverage": "^0.8.16",
    "ts-node": "^10.9.2",
    "typechain": "^8.3.2",
    "typescript": "^5.9.3"
  },
  "directories": {
    "test": "test"
  },
  "dependencies": {
    "abbrev": "^1.0.9",
    "abitype": "^1.1.0",
    "acorn": "^8.15.0",
    "acorn-walk": "^8.3.4",
    "adm-zip": "^0.4.16",
    "aes-js": "^4.0.0-beta.5",
    "agent-base": "^6.0.2",
    "aggregate-error": "^3.1.0",
    "ajv": "^8.17.1",
    "amdefine": "^1.0.1",
    "ansi-align": "^3.0.1",
    "ansi-colors": "^4.1.3",
    "ansi-escapes": "^4.3.2",
    "ansi-regex": "^5.0.1",
    "ansi-styles": "^4.3.0",
    "anymatch": "^3.1.3",
    "arg": "^4.1.3",
    "argparse": "^2.0.1",
    "array-back": "^3.1.0",
    "array-union": "^2.1.0",
    "assertion-error": "^1.1.0",
    "astral-regex": "^2.0.0",
    "async": "^1.5.2",
    "asynckit": "^0.4.0",
    "at-least-node": "^1.0.0",
    "available-typed-arrays": "^1.0.7",
    "axios": "^1.12.2",
    "balanced-match": "^1.0.2",
    "base-x": "^3.0.11",
    "binary-extensions": "^2.3.0",
    "blakejs": "^1.2.1",
    "bn.js": "^5.2.2",
    "boxen": "^5.1.2",
    "brace-expansion": "^2.0.2",
    "braces": "^3.0.3",
    "brorand": "^1.1.0",
    "brotli-wasm": "^2.0.1",
    "browser-stdout": "^1.3.1",
    "browserify-aes": "^1.2.0",
    "bs58": "^4.0.1",
    "bs58check": "^2.1.2",
    "buffer-from": "^1.1.2",
    "buffer-xor": "^1.0.3",
    "bytes": "^3.1.2",
    "call-bind": "^1.0.8",
    "call-bind-apply-helpers": "^1.0.2",
    "call-bound": "^1.0.4",
    "camelcase": "^6.3.0",
    "cbor": "^8.1.0",
    "chai-as-promised": "^7.1.2",
    "chalk": "^4.1.2",
    "charenc": "^0.0.2",
    "check-error": "^1.0.3",
    "chokidar": "^4.0.3",
    "ci-info": "^2.0.0",
    "cipher-base": "^1.0.7",
    "clean-stack": "^2.2.0",
    "cli-boxes": "^2.2.1",
    "cli-table3": "^0.6.5",
    "cliui": "^7.0.4",
    "color-convert": "^2.0.1",
    "color-name": "^1.1.4",
    "combined-stream": "^1.0.8",
    "command-exists": "^1.2.9",
    "command-line-args": "^5.2.1",
    "command-line-usage": "^6.1.3",
    "commander": "^8.3.0",
    "concat-map": "^0.0.1",
    "cookie": "^0.4.2",
    "core-util-is": "^1.0.3",
    "create-hash": "^1.2.0",
    "create-hmac": "^1.1.7",
    "create-require": "^1.1.1",
    "cross-spawn": "^7.0.6",
    "crypt": "^0.0.2",
    "death": "^1.1.0",
    "debug": "^4.4.3",
    "decamelize": "^4.0.0",
    "deep-eql": "^4.1.4",
    "deep-extend": "^0.6.0",
    "deep-is": "^0.1.4",
    "define-data-property": "^1.1.4",
    "delayed-stream": "^1.0.0",
    "depd": "^2.0.0",
    "diff": "^5.2.0",
    "difflib": "^0.2.4",
    "dir-glob": "^3.0.1",
    "dunder-proto": "^1.0.1",
    "eastasianwidth": "^0.2.0",
    "elliptic": "^6.6.1",
    "emoji-regex": "^8.0.0",
    "enquirer": "^2.4.1",
    "env-paths": "^2.2.1",
    "es-define-property": "^1.0.1",
    "es-errors": "^1.3.0",
    "es-object-atoms": "^1.1.1",
    "es-set-tostringtag": "^2.1.0",
    "escalade": "^3.2.0",
    "escape-string-regexp": "^4.0.0",
    "escodegen": "^1.8.1",
    "esprima": "^2.7.3",
    "estraverse": "^1.9.3",
    "esutils": "^2.0.3",
    "ethereum-bloom-filters": "^1.2.0",
    "ethereum-cryptography": "^0.1.3",
    "ethereumjs-util": "^7.1.5",
    "ethjs-unit": "^0.1.6",
    "eventemitter3": "^5.0.1",
    "evp_bytestokey": "^1.0.3",
    "fast-deep-equal": "^3.1.3",
    "fast-glob": "^3.3.3",
    "fast-levenshtein": "^2.0.6",
    "fast-uri": "^3.1.0",
    "fastq": "^1.19.1",
    "fill-range": "^7.1.1",
    "find-replace": "^3.0.0",
    "find-up": "^5.0.0",
    "flat": "^5.0.2",
    "follow-redirects": "^1.15.11",
    "for-each": "^0.3.5",
    "foreground-child": "^3.3.1",
    "form-data": "^4.0.4",
    "fp-ts": "^1.19.3",
    "fs-extra": "^10.1.0",
    "fs.realpath": "^1.0.0",
    "function-bind": "^1.1.2",
    "get-caller-file": "^2.0.5",
    "get-func-name": "^2.0.2",
    "get-intrinsic": "^1.3.0",
    "get-proto": "^1.0.1",
    "ghost-testrpc": "^0.0.2",
    "glob": "^10.4.5",
    "glob-parent": "^5.1.2",
    "global-modules": "^2.0.0",
    "global-prefix": "^3.0.0",
    "globby": "^10.0.2",
    "gopd": "^1.2.0",
    "graceful-fs": "^4.2.11",
    "handlebars": "^4.7.8",
    "has-flag": "^4.0.0",
    "has-property-descriptors": "^1.0.2",
    "has-symbols": "^1.1.0",
    "has-tostringtag": "^1.0.2",
    "hash-base": "^3.1.2",
    "hash.js": "^1.1.7",
    "hasown": "^2.0.2",
    "he": "^1.2.0",
    "heap": "^0.2.7",
    "hmac-drbg": "^1.0.1",
    "http-errors": "^2.0.0",
    "https-proxy-agent": "^5.0.1",
    "iconv-lite": "^0.4.24",
    "ignore": "^5.3.2",
    "immer": "^10.0.2",
    "immutable": "^4.3.7",
    "indent-string": "^4.0.0",
    "inflight": "^1.0.6",
    "inherits": "^2.0.4",
    "ini": "^1.3.8",
    "interpret": "^1.4.0",
    "io-ts": "^1.10.4",
    "is-binary-path": "^2.1.0",
    "is-callable": "^1.2.7",
    "is-extglob": "^2.1.1",
    "is-fullwidth-code-point": "^3.0.0",
    "is-glob": "^4.0.3",
    "is-hex-prefixed": "^1.0.0",
    "is-number": "^7.0.0",
    "is-plain-obj": "^2.1.0",
    "is-typed-array": "^1.1.15",
    "is-unicode-supported": "^0.1.0",
    "isarray": "^2.0.5",
    "isexe": "^2.0.0",
    "isows": "^1.0.7",
    "jackspeak": "^3.4.3",
    "js-sha3": "^0.8.0",
    "js-yaml": "^4.1.0",
    "json-schema-traverse": "^1.0.0",
    "json-stream-stringify": "^3.1.6",
    "json-stringify-safe": "^5.0.1",
    "json5": "^2.2.3",
    "jsonfile": "^6.2.0",
    "jsonschema": "^1.5.0",
    "keccak": "^3.0.4",
    "kind-of": "^6.0.3",
    "kleur": "^3.0.3",
    "levn": "^0.3.0",
    "locate-path": "^6.0.0",
    "lodash": "^4.17.21",
    "lodash.camelcase": "^4.3.0",
    "lodash.clonedeep": "^4.5.0",
    "lodash.isequal": "^4.5.0",
    "lodash.truncate": "^4.4.2",
    "log-symbols": "^4.1.0",
    "loupe": "^2.3.7",
    "lru-cache": "^10.4.3",
    "lru_map": "^0.3.3",
    "make-error": "^1.3.6",
    "markdown-table": "^2.0.0",
    "math-intrinsics": "^1.1.0",
    "md5.js": "^1.3.5",
    "memorystream": "^0.3.1",
    "merge2": "^1.4.1",
    "micro-eth-signer": "^0.14.0",
    "micro-ftch": "^0.3.1",
    "micro-packed": "^0.7.3",
    "micromatch": "^4.0.8",
    "mime-db": "^1.52.0",
    "mime-types": "^2.1.35",
    "minimalistic-assert": "^1.0.1",
    "minimalistic-crypto-utils": "^1.0.1",
    "minimatch": "^9.0.5",
    "minimist": "^1.2.8",
    "minipass": "^7.1.2",
    "mkdirp": "^0.5.6",
    "mnemonist": "^0.38.5",
    "ms": "^2.1.3",
    "ndjson": "^2.0.0",
    "neo-async": "^2.6.2",
    "node-addon-api": "^2.0.2",
    "node-emoji": "^1.11.0",
    "node-gyp-build": "^4.8.4",
    "nofilter": "^3.1.0",
    "nopt": "^3.0.6",
    "normalize-path": "^3.0.0",
    "number-to-bn": "^1.7.0",
    "obliterator": "^2.0.5",
    "once": "^1.4.0",
    "optionator": "^0.8.3",
    "ordinal": "^1.0.3",
    "os-tmpdir": "^1.0.2",
    "ox": "^0.9.6",
    "p-limit": "^3.1.0",
    "p-locate": "^5.0.0",
    "p-map": "^4.0.0",
    "package-json-from-dist": "^1.0.1",
    "path-exists": "^4.0.0",
    "path-is-absolute": "^1.0.1",
    "path-key": "^3.1.1",
    "path-parse": "^1.0.7",
    "path-scurry": "^1.11.1",
    "path-type": "^4.0.0",
    "pathval": "^1.1.1",
    "pbkdf2": "^3.1.5",
    "picocolors": "^1.1.1",
    "picomatch": "^2.3.1",
    "pify": "^4.0.1",
    "possible-typed-array-names": "^1.1.0",
    "prelude-ls": "^1.1.2",
    "prettier": "^2.8.8",
    "process-nextick-args": "^2.0.1",
    "prompts": "^2.4.2",
    "proxy-from-env": "^1.1.0",
    "queue-microtask": "^1.2.3",
    "randombytes": "^2.1.0",
    "raw-body": "^2.5.2",
    "readable-stream": "^3.6.2",
    "readdirp": "^4.1.2",
    "rechoir": "^0.6.2",
    "recursive-readdir": "^2.2.3",
    "reduce-flatten": "^2.0.0",
    "repeat-string": "^1.6.1",
    "require-directory": "^2.1.1",
    "require-from-string": "^2.0.2",
    "resolve": "^1.17.0",
    "reusify": "^1.1.0",
    "ripemd160": "^2.0.3",
    "rlp": "^2.2.7",
    "run-parallel": "^1.2.0",
    "safe-buffer": "^5.2.1",
    "safer-buffer": "^2.1.2",
    "sc-istanbul": "^0.4.6",
    "scrypt-js": "^3.0.1",
    "secp256k1": "^4.0.4",
    "semver": "^6.3.1",
    "serialize-javascript": "^6.0.2",
    "set-function-length": "^1.2.2",
    "setimmediate": "^1.0.5",
    "setprototypeof": "^1.2.0",
    "sha.js": "^2.4.12",
    "sha1": "^1.1.1",
    "shebang-command": "^2.0.0",
    "shebang-regex": "^3.0.0",
    "shelljs": "^0.8.5",
    "signal-exit": "^4.1.0",
    "sisteransi": "^1.0.5",
    "slash": "^3.0.0",
    "slice-ansi": "^4.0.0",
    "solc": "^0.8.26",
    "source-map": "^0.2.0",
    "source-map-support": "^0.5.21",
    "split2": "^3.2.2",
    "sprintf-js": "^1.0.3",
    "stacktrace-parser": "^0.1.11",
    "statuses": "^2.0.1",
    "string-format": "^2.0.0",
    "string-width": "^4.2.3",
    "string-width-cjs": "^4.2.3",
    "string_decoder": "^1.3.0",
    "strip-ansi": "^6.0.1",
    "strip-ansi-cjs": "^6.0.1",
    "strip-hex-prefix": "^1.0.0",
    "strip-json-comments": "^3.1.1",
    "supports-color": "^7.2.0",
    "table": "^6.9.0",
    "table-layout": "^1.0.2",
    "through2": "^4.0.2",
    "tinyglobby": "^0.2.15",
    "tmp": "^0.0.33",
    "to-buffer": "^1.2.2",
    "to-regex-range": "^5.0.1",
    "toidentifier": "^1.0.1",
    "ts-command-line-args": "^2.5.1",
    "ts-essentials": "^7.0.3",
    "tslib": "^2.7.0",
    "tsort": "^0.0.1",
    "type-check": "^0.3.2",
    "type-detect": "^4.1.0",
    "type-fest": "^0.21.3",
    "typed-array-buffer": "^1.0.3",
    "typical": "^4.0.0",
    "uglify-js": "^3.19.3",
    "undici": "^5.29.0",
    "undici-types": "^7.13.0",
    "universalify": "^2.0.1",
    "unpipe": "^1.0.0",
    "utf8": "^3.0.0",
    "util-deprecate": "^1.0.2",
    "uuid": "^8.3.2",
    "v8-compile-cache-lib": "^3.0.1",
    "viem": "^2.37.11",
    "web3-utils": "^1.10.4",
    "which": "^2.0.2",
    "which-typed-array": "^1.1.19",
    "widest-line": "^3.1.0",
    "word-wrap": "^1.2.5",
    "wordwrap": "^1.0.0",
    "wordwrapjs": "^4.0.1",
    "workerpool": "^6.5.1",
    "wrap-ansi": "^7.0.0",
    "wrap-ansi-cjs": "^7.0.0",
    "wrappy": "^1.0.2",
    "ws": "^8.17.1",
    "y18n": "^5.0.8",
    "yargs": "^16.2.0",
    "yargs-parser": "^20.2.9",
    "yargs-unparser": "^2.0.0",
    "yn": "^3.1.1",
    "yocto-queue": "^0.1.0"
  }
}

Executando outra vez o npm init -y, percebam que a lista de dependências foi atualizada para a versão \(3\):

[projeto-hello-solidity-hardhat-v3-ts]$ npm init -y
Wrote to /home/rag/projeto-hello-solidity-hardhat-v3-ts/package.json:

{
  "name": "projeto-hello-solidity-hardhat",
  "version": "1.0.0",
  "description": "This project showcases a Hardhat 3 Beta project using `mocha` for tests and the `ethers` library for Ethereum interactions.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
  "devDependencies": {
    "@nomicfoundation/hardhat-ignition": "^3.0.3",
    "@nomicfoundation/hardhat-toolbox-mocha-ethers": "^3.0.0",
    "@types/chai": "^4.3.20",
    "@types/chai-as-promised": "^8.0.2",
    "@types/mocha": "^10.0.10",
    "@types/node": "^22.18.7",
    "chai": "^5.3.3",
    "ethers": "^6.15.0",
    "forge-std": "github:foundry-rs/forge-std#v1.9.4",
    "hardhat": "^3.0.6",
    "mocha": "^11.7.3",
    "typescript": "~5.8.0"
  },
  "directories": {
    "test": "test"
  },
  "dependencies": {
    "adm-zip": "^0.4.16",
    "aes-js": "^4.0.0-beta.5",
    "ansi-colors": "^4.1.3",
    "ansi-regex": "^5.0.1",
    "ansi-styles": "^6.2.3",
    "argparse": "^2.0.1",
    "array-back": "^3.1.0",
    "assertion-error": "^2.0.1",
    "balanced-match": "^1.0.2",
    "bn.js": "^5.2.2",
    "brace-expansion": "^2.0.2",
    "brorand": "^1.1.0",
    "browser-stdout": "^1.3.1",
    "camelcase": "^6.3.0",
    "cbor2": "^1.12.0",
    "chai-as-promised": "^8.0.2",
    "chalk": "^5.6.2",
    "check-error": "^2.1.1",
    "chokidar": "^4.0.3",
    "cliui": "^8.0.1",
    "color-convert": "^2.0.1",
    "color-name": "^1.1.4",
    "command-line-args": "^5.2.1",
    "command-line-usage": "^6.1.3",
    "concat-map": "^0.0.1",
    "cross-spawn": "^7.0.6",
    "debug": "^4.4.3",
    "decamelize": "^4.0.0",
    "deep-eql": "^5.0.2",
    "deep-extend": "^0.6.0",
    "diff": "^7.0.0",
    "eastasianwidth": "^0.2.0",
    "elliptic": "^6.6.1",
    "emoji-regex": "^9.2.2",
    "enquirer": "^2.4.1",
    "env-paths": "^2.2.1",
    "esbuild": "^0.25.10",
    "escalade": "^3.2.0",
    "escape-string-regexp": "^4.0.0",
    "ethereum-cryptography": "^2.2.1",
    "fast-equals": "^5.3.2",
    "find-replace": "^3.0.0",
    "find-up": "^5.0.0",
    "flat": "^5.0.2",
    "foreground-child": "^3.3.1",
    "fs-extra": "^7.0.1",
    "fs.realpath": "^1.0.0",
    "get-caller-file": "^2.0.5",
    "get-tsconfig": "^4.10.1",
    "glob": "^10.4.5",
    "graceful-fs": "^4.2.11",
    "has-flag": "^4.0.0",
    "hash.js": "^1.1.7",
    "he": "^1.2.0",
    "hmac-drbg": "^1.0.1",
    "immer": "^10.0.2",
    "inflight": "^1.0.6",
    "inherits": "^2.0.4",
    "is-fullwidth-code-point": "^3.0.0",
    "is-plain-obj": "^2.1.0",
    "is-unicode-supported": "^0.1.0",
    "isexe": "^2.0.0",
    "jackspeak": "^3.4.3",
    "js-sha3": "^0.8.0",
    "js-yaml": "^4.1.0",
    "json-stream-stringify": "^3.1.6",
    "json-stringify-safe": "^5.0.1",
    "json5": "^2.2.3",
    "jsonfile": "^4.0.0",
    "kleur": "^3.0.3",
    "locate-path": "^6.0.0",
    "lodash": "^4.17.21",
    "lodash-es": "^4.17.21",
    "lodash.camelcase": "^4.3.0",
    "log-symbols": "^4.1.0",
    "loupe": "^3.2.1",
    "lru-cache": "^10.4.3",
    "micro-eth-signer": "^0.14.0",
    "micro-packed": "^0.7.3",
    "minimalistic-assert": "^1.0.1",
    "minimalistic-crypto-utils": "^1.0.1",
    "minimatch": "^9.0.5",
    "minimist": "^1.2.8",
    "minipass": "^7.1.2",
    "mkdirp": "^1.0.4",
    "ms": "^2.1.3",
    "ndjson": "^2.0.0",
    "once": "^1.4.0",
    "p-limit": "^3.1.0",
    "p-locate": "^5.0.0",
    "p-map": "^7.0.3",
    "package-json-from-dist": "^1.0.1",
    "path-exists": "^4.0.0",
    "path-is-absolute": "^1.0.1",
    "path-key": "^3.1.1",
    "path-scurry": "^1.11.1",
    "pathval": "^2.0.1",
    "picocolors": "^1.1.1",
    "prettier": "^2.8.8",
    "prompts": "^2.4.2",
    "randombytes": "^2.1.0",
    "readable-stream": "^3.6.2",
    "readdirp": "^4.1.2",
    "reduce-flatten": "^2.0.0",
    "require-directory": "^2.1.1",
    "resolve-pkg-maps": "^1.0.0",
    "resolve.exports": "^2.0.3",
    "rfdc": "^1.4.1",
    "safe-buffer": "^5.2.1",
    "semver": "^7.7.2",
    "serialize-javascript": "^6.0.2",
    "shebang-command": "^2.0.0",
    "shebang-regex": "^3.0.0",
    "signal-exit": "^4.1.0",
    "sisteransi": "^1.0.5",
    "split2": "^3.2.2",
    "string-format": "^2.0.0",
    "string-width": "^5.1.2",
    "string-width-cjs": "^4.2.3",
    "string_decoder": "^1.3.0",
    "strip-ansi": "^6.0.1",
    "strip-ansi-cjs": "^6.0.1",
    "strip-json-comments": "^3.1.1",
    "supports-color": "^8.1.1",
    "table-layout": "^1.0.2",
    "through2": "^4.0.2",
    "ts-command-line-args": "^2.5.1",
    "ts-essentials": "^7.0.3",
    "tslib": "^2.7.0",
    "tsx": "^4.20.6",
    "typechain": "^8.3.2",
    "typical": "^4.0.0",
    "undici": "^6.21.3",
    "undici-types": "^6.21.0",
    "universalify": "^0.1.2",
    "util-deprecate": "^1.0.2",
    "which": "^2.0.2",
    "wordwrapjs": "^4.0.1",
    "workerpool": "^9.3.4",
    "wrap-ansi": "^8.1.0",
    "wrap-ansi-cjs": "^7.0.0",
    "wrappy": "^1.0.2",
    "ws": "^8.17.1",
    "y18n": "^5.0.8",
    "yargs": "^17.7.2",
    "yargs-parser": "^21.1.1",
    "yargs-unparser": "^2.0.0",
    "yocto-queue": "^0.1.0",
    "zod": "^3.25.76"
  }
}

[projeto-hello-solidity-hardhat-v3-ts]$

12.4 Criando um novo contrato

Vamos criar um contrato com nome de HelloWorld para testarmos. Na versão \(2\), no diretório projeto-hello-solidity-hardhat-v2-ts, crie o arquivo HelloWorld.sol no diretório contracts e insira o conteúdo apresentado no Código:

// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

contract HelloWorld {
    string public message = "Hello World!";

    function helloWorld() public view returns (string memory) {
        return message;
    }
}

Para testar o contrato HelloWorld.sol crie o arquivo HelloWorld.test.ts no diretório test com o conteúdo:

const {
  time,
  loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
const { expect } = require("chai");
const { ethers } = require ("hardhat");

describe("HelloWorld", function() {
 
});

async function deployFixture() {
    const [owner, otherAccount] = await ethers.getSigners();
   
    const HelloWorld = await ethers.getContractFactory("HelloWorld");
    const helloWorld = await HelloWorld.deploy();
   
    return { helloWorld, owner, otherAccount };
}

describe("Say Hello", function () {
    it("Should Hello the world", async () => {
      const { helloWorld } = await loadFixture(deployFixture);
   
      expect(await helloWorld.helloWorld()).equal("Hello World!");
    });    
  });

Para executar o teste para o contrato basta executar o comando npx hardhat test. Serão testados todos os contratos HelloWorld e o Lock:

[projeto-hello-solidity-hardhat]$ npx hardhat test


  Say Hello
    ✔ Should Hello the world (53ms)

  Lock
    Deployment
      ✔ Should set the right unlockTime
      ✔ Should set the right owner
      ✔ Should receive and store the funds to lock
      ✔ Should fail if the unlockTime is not in the future
    Withdrawals
      Validations
        ✔ Should revert with the right error if called too soon
        ✔ Should revert with the right error if called from another account
        ✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
      Events
        ✔ Should emit an event on withdrawals
      Transfers
        ✔ Should transfer the funds to the owner


  10 passing (118ms)

·············································································································
|  Solidity and Network Configuration                                                                       │
························|·················|···············|·················|································
|  Solidity: 0.8.28     ·  Optim: false   ·  Runs: 200    ·  viaIR: false   ·     Block: 30,000,000 gas     │
························|·················|···············|·················|································
|  Methods                                                                                                  │
························|·················|···············|·················|················|···············
|  Contracts / Methods  ·  Min            ·  Max          ·  Avg            ·  # calls       ·  usd (avg)   │
························|·················|···············|·················|················|···············
|  Lock                 ·                                                                                   │
························|·················|···············|·················|················|···············
|      withdraw         ·              -  ·            -  ·         34,096  ·             7  ·           -  │
························|·················|···············|·················|················|···············
|  Deployments                            ·                                 ·  % of limit    ·              │
························|·················|···············|·················|················|···············
|  HelloWorld           ·              -  ·            -  ·        247,165  ·         0.8 %  ·           -  │
························|·················|···············|·················|················|···············
|  Lock                 ·              -  ·            -  ·        326,112  ·         1.1 %  ·           -  │
························|·················|···············|·················|················|···············
|  Key                                                                                                      │
·············································································································
|  ◯  Execution gas for this method does not include intrinsic gas overhead                                 │
·············································································································
|  △  Cost was non-zero but below the precision setting for the currency display (see options)              │
·············································································································
|  Toolchain:  hardhat                                                                                      │
·············································································································
[projeto-hello-solidity-hardhat]$ 

Se a versão do hardhat escolhida foi a \(3\):

[projeto-hello-solidity-hardhat-v3-ts]$ npx hardhat test
Compiling your Solidity contracts...
Compiled 2 Solidity files with solc 0.8.28 (evm target: cancun)

Running Solidity tests

  contracts/Counter.t.sol:CounterTest
    ✔ test_InitialValue()
    ✔ test_IncByZero()
    ✔ testFuzz_Inc(uint8) (runs: 256)


  3 passing

Running Mocha tests


  ✔ Should Hello the world (79ms)
  Counter
    ✔ Should emit the Increment event when calling the inc() function
    ✔ The sum of the Increment events should match the current value (116ms)


  3 passing (229ms)


[projeto-hello-solidity-hardhat-v3-ts]$ 

Vamos adicionar o contrato HelloWorld. Na versão \(2\), no diretório projeto-hello-solidity-hardhat-v3-ts, crie o arquivo HelloWorld.sol no diretório contracts e insira o conteúdo apresentado no Código:

// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

contract HelloWorld {
    string public message = "Hello World!";

    function helloWorld() public view returns (string memory) {
        return message;
    }
}

Para testar o contrato HelloWorld.sol crie o arquivo HelloWorld.test.ts no diretório test com o conteúdo:

import { expect } from "chai";
import { network } from "hardhat";

const { ethers } = await network.connect();

describe("HelloWorld", () => {

});

it("Should Hello the world", async () => {
    const helloWorld = await ethers.deployContract("HelloWorld");
    const deploymentBlockNumber = await ethers.provider.getBlockNumber();

    expect(await helloWorld.helloWorld()).to.equal("Hello World!");
});

Para executar o teste para o contrato basta executar o comando npx hardhat test. Serão testados todos os contratos HelloWorld e o Counter:

[projeto-hello-solidity-hardhat-v3-ts]$ npx hardhat test
Compiling your Solidity contracts...

Nothing to compile

Running Solidity tests



  0 passing

Running Mocha tests


  HelloWorld
    ✔ Should Hello the world (56ms)


  1 passing (56ms)


[projeto-hello-solidity-hardhat-v3-ts]$ 

12.5 Iniciando uma simulada pelo Hardhat

Para iniciarmos uma rede simulada que responderá no endereço http://127.0.0.1:8545. Para isso é necessário que coloquemos no arquivo hardhat.config.js as configurações da rede local:

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.19",
  networks: {
    local: {
      chainId: 31337,
      url: "http://localhost:8545/",
      accounts: {
        mnemonic: "test test test test test test test test test test test junk"
      }
    }
  }
};

Executando o comando npx hardhat node --network hardhat a rede será criada e \(20\) contas serão criadas com o saldo de \(10000 ETH\) cada uma.

[rag@backporting projeto-hello-solidity-hardhat-v2-ts]$ npx hardhat node --network hardhat
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

Accounts
========

WARNING: These accounts, and their private keys, are publicly known.
Any funds sent to them on Mainnet or any other live network WILL BE LOST.

Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

Account #2: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000 ETH)
Private Key: 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a

Account #3: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (10000 ETH)
Private Key: 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6

Account #4: 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (10000 ETH)
Private Key: 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a

Account #5: 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc (10000 ETH)
Private Key: 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba

Account #6: 0x976EA74026E726554dB657fA54763abd0C3a0aa9 (10000 ETH)
Private Key: 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e

Account #7: 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 (10000 ETH)
Private Key: 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356

Account #8: 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f (10000 ETH)
Private Key: 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97

Account #9: 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000 ETH)
Private Key: 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6

Account #10: 0xBcd4042DE499D14e55001CcbB24a551F3b954096 (10000 ETH)
Private Key: 0xf214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897

Account #11: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 (10000 ETH)
Private Key: 0x701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82

Account #12: 0xFABB0ac9d68B0B445fB7357272Ff202C5651694a (10000 ETH)
Private Key: 0xa267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1

Account #13: 0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec (10000 ETH)
Private Key: 0x47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd

Account #14: 0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097 (10000 ETH)
Private Key: 0xc526ee95bf44d8fc405a158bb884d9d1238d99f0612e9f33d006bb0789009aaa

Account #15: 0xcd3B766CCDd6AE721141F452C550Ca635964ce71 (10000 ETH)
Private Key: 0x8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61

Account #16: 0x2546BcD3c84621e976D8185a91A922aE77ECEc30 (10000 ETH)
Private Key: 0xea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0

Account #17: 0xbDA5747bFD65F08deb54cb465eB87D40e51B197E (10000 ETH)
Private Key: 0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd

Account #18: 0xdD2FD4581271e230360230F9337D5c0430Bf44C0 (10000 ETH)
Private Key: 0xde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0

Account #19: 0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 (10000 ETH)
Private Key: 0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e

WARNING: These accounts, and their private keys, are publicly known.
Any funds sent to them on Mainnet or any other live network WILL BE LOST.

12.6 Adicionando a Rede para ser listada em um block explorer

Inicie o expediton conforme Prática sobre Instalação de Block Explorers Locais para as Redes de Testes: Instalando Block Explorers Locais para as Redes de Testes.

$ cd expedition
[expediton]$ export NODE_OPTIONS=--openssl-legacy-provider
[expediton]$ npm start

Compiled successfully!

You can now view @xops.net/expedition in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.100.104:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

Configure a rede Hardhat Network no expedition.

Configurando Rede Hardhat no expedition

Acessando as informações da rede Hardhat no expedition.

Expedition listando as informações

Ao ser configurada a rede no expedition irão aparecer as mensagens de sincronização no terminal em que a rede do hardhat foi iniciada.

eth_blockNumber
net_peerCount
eth_chainId
eth_gasPrice
eth_getBlockByNumber (3)
eth_blockNumber
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
eth_syncing
eth_blockNumber
eth_syncing
eth_blockNumber (2)
...

Vamos adicionar a rede Hardhat Network e as duas primeiras contas no Metamask:

Adicionando a Hardhat Network no Metamask

Adicionando a Hardhat Network no Metamask

Adicionando a Hardhat Network no Metamask

Adicionando as contas da Rede do Hardhat no Metamask:

Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

Na lista de contas do Metamask adicione as duas contas utilizando a chave privada gerada pelo Hardhat para a rede simulada.

Adicionando uma conta

Adicionando uma conta pela chave

Todas as contas foram criadas e inicializadas com \(10000 ETH\). Vamos enviar um valor da Account 9 para a Account 10.

Carteira da Account 9

Selecionamos a conta que irá receber a transferência, no exemplo a Account 10.

Seleção de conta destino

Indicamos o valor de \(100 ETH\) a ser transferido e clicamos em continuar.

Envio da Transação

Após o envio será necessário confirmarmos a transação.

Confirmação da Transação

O registro da transação enviada irá aparecer no console onde a rede simulada está executando.

eth_blockNumber (2)
eth_sendRawTransaction
  Transaction: 0xdf06078a30c28d74d25d75934d714b69229f4e0119123e6c4a9069d6a886032c
  From:        0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:          0x70997970c51812dc3a010c7d01b50e0d17dc79c8
  Value:       100 ETH
  Gas used:    21000 of 21001
  Block #1:    0x46701cf40a4890d9865c4e29b4c9d1b92caadb0a3c5e48d581880cb1fdb6867d

eth_blockNumber
eth_getBlockByNumber
eth_getTransactionReceipt
eth_getBalance (10)
eth_getBlockByHash
eth_gasPrice

Na interface do Metamask irá aparecer que a transação foi confirmada.

Transação Confirmada

E clicando sobre o status de confirmação podemos acessar os detalhes da transação "Ver no explorador de blocos" que irá para o link no expedition. Ou podemos copiar o ID da transação 0xdf06078a30c28d74d25d75934d714b69229f4e0119123e6c4a9069d6a886032c e pesquisar na consulta do expedition.

Detalhes da Transação no Metamask

A lista de blocos pode ser acessada na interface do expedition.

Blocos criados

As informações do bloco \(1\) podem ser acessadas pelo link na coluna Block number http://localhost:3000/block/0x46701cf40a4890d9865c4e29b4c9d1b92caadb0a3c5e48d581880cb1fdb6867d?network=Hardhat%20-%20Network.

As informações do bloco irão ser apresentadas na interface do expedition.

Informação do bloco

Clicando sobre a transação, as informações serão apresentadas.

Transação: 0xdf06078a30c28d74d25d75934d714b69229f4e0119123e6c4a9069d6a886032c

Se no console da rede simulada do Hardhat aparecer a mensagem:

eth_sendRawTransaction

  Nonce too high. Expected nonce to be 0 but got 1. Note that transactions can't be queued when automining.

É só ir no Metamask em Configurações, então em Avançado e clique em Clear activity and nonce data.

12.7 Considerações Finais

Nesta aula vimos uma introdução ao uso do hardhat para fazer testes e deploy de contratos inteligentes em redes locais e de testes.

12.8 Leitura Recomendada

13 Word Cloud

13.1 Referências