Samouczek Waffle „powiedz Hello World” za pomocą hardhat i ethers
Z tego samouczka Waffle dowiemy się, jak skonfigurować prosty projekt inteligentnego kontraktu „Hello world”, używając hardhat i ethers.js. Następnie dowiemy się, jak dodać nową funkcjonalność do naszego inteligentnego kontraktu i jak przetestować go z Waffle.
Zacznijmy od tworzenia nowego projektu:
yarn init
lub
npm init
i instalowania wymaganych pakietów:
yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai
lub
npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai
Następnym krokiem jest stworzenie przykładowego projektu hardhat, uruchamiając npx hardhat
.
888 888 888 888 888888 888 888 888 888888 888 888 888 8888888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888888 888 "88b 888P" d88" 888 888 "88b "88b 888888 888 .d888888 888 888 888 888 888 .d888888 888888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888👷 Welcome to Hardhat v2.0.3 👷? What do you want to do? …❯ Create a sample projectCreate an empty hardhat.config.jsQuitPokaż wszystko
Wybierz Create a sample project
Nasza struktura projektów powinna wyglądać tak:
1MyWaffleProject2├── contracts3│ └── Greeter.sol4├── node_modules5├── scripts6│ └── sample-script.js7├── test8│ └── sample-test.js9├── .gitattributs10├── .gitignore11├── hardhat.config.js12└── package.json13Pokaż wszystko
Teraz porozmawiajmy o niektórych z tych plików:
- Greeter.sol - nasz inteligentny kontrakt napisany w Solidity;
1contract Greeter {2string greeting;34constructor(string memory _greeting) public {5console.log("Deploying a Greeter with greeting:", _greeting);6greeting = _greeting;7}89function greet() public view returns (string memory) {10return greeting;11}1213function setGreeting(string memory _greeting) public {14console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);15greeting = _greeting;16}17}18Pokaż wszystkoKopiuj
Nasz inteligentny kontrakt można podzielić na trzy części:
- konstruktor — gdzie deklarujemy zmienną typu string o nazwie
greeting
, - funkcja greet — funkcja, która zwróci powitanie
greeting
po wywołaniu, - funkcja setGreeting — funkcja, która pozwala nam zmienić wartość zmiennej
greeting
.
- sample-test.js — nasz plik testowy
1describe("Greeter", function () {2 it("Should return the new greeting once it's changed", async function () {3 const Greeter = await ethers.getContractFactory("Greeter")4 const greeter = await Greeter.deploy("Hello, world!")56 await greeter.deployed()7 expect(await greeter.greet()).to.equal("Hello, world!")89 await greeter.setGreeting("Hola, mundo!")10 expect(await greeter.greet()).to.equal("Hola, mundo!")11 })12})13Pokaż wszystkoKopiuj
Kolejny krok to skompilowanie kontraktu i uruchomienie testów:
Testy Waffle wykorzystują Mocha (framework do tworzenia tesów) razem z Chai (biblioteka asercji). Wszystko, co musisz zrobić, to uruchomić npx test hardhat
i poczekać na pojawienie się następującej wiadomości.
✓ Should return the new greeting once it's changed
Wszystko wygląda dobrze i prosto do tej pory, dodajmy trochę więcej złożoności do naszego projektu :)
Wyobraź sobie, że dostajesz od kogoś pustą wiadomość jako powitanie. To nie byłoby ciepłe powitanie, prawda?
Upewnijmy się, że tak się nie stanie:
Chcemy użyć Solidity revert
, gdy ktoś przekaże pusty ciąg. Dobrze, że możemy łatwo przetestować tę funkcjonalność z wyrażeniem matcher chai z Waffle to.bo.revertedWith()
.
1it("Should revert when passing an empty string", async () => {2 const Greeter = await ethers.getContractFactory("Greeter")3 const greeter = await Greeter.deploy("Hello, world!")45 await greeter.deployed()6 await expect(greeter.setGreeting("")).to.be.revertedWith(7 "Greeting should not be empty"8 )9})10Pokaż wszystkoKopiuj
Wygląda na to, że nasz nowy test nie przeszedł:
Deploying a Greeter with greeting: Hello, world!Changing greeting from 'Hello, world!' to 'Hola, mundo!'✓ Should return the new greeting once it's changed (1514ms)Deploying a Greeter with greeting: Hello, world!Changing greeting from 'Hello, world!' to ''1) Should revert when passing an empty string1 passing (2s)1 failingPokaż wszystko
Zastosujmy tę funkcję do naszego inteligentnego kontraktu:
1require(bytes(_greeting).length > 0, "Greeting message is empty");2Kopiuj
Teraz nasza funkcja setGreeting wygląda tak:
1function setGreeting(string memory _greeting) public {2require(bytes(_greeting).length > 0, "Greeting should not be empty");3console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);4greeting = _greeting;5}6Kopiuj
Wykonajmy testy ponownie:
✓ Should return the new greeting once it's changed (1467ms)✓ Should revert when passing an empty string (276ms)2 passing (2s)
Gratulacje! Udało się :)
Podsumowanie
Stworzyliśmy prosty projekt z Waffle, Hardhat i ethers.js. Nauczyliśmy się, jak skonfigurować projekt, dodać test i wdrożyć nową funkcjonalność.
Aby dowiedzieć się więcej o znakomitych wyrażeniach matcher chai do testowania inteligentnych kontraktów, sprawdź oficjalne dokumenty Waffle'a.