Kaip įdiegti išmaniąją sutartį Ethereum tinkle naudojant dRPC API raktą ir galinį tašką
Įvadas
Suprasdami Web3 DApp kūrimo technologijų rinkinį, turite išmokti pagrindines žiniatinklio 3 dApp kūrimo technologijas, RPC vaidmenį kuriant dApp ir kaip naudoti dRPC kuriant paskyrą, generuojant API raktą, galinius taškus, galinių taškų analizę. , pridėkite lėšų į savo dRPC sąskaitą ir patikrinkite balansą.
dRPC vaidmuo diegiant išmaniąsias sutartis yra supaprastinti Ethereum mazgo nustatymo procesą, kad kūrėjams būtų lengviau bendrauti ir diegti naudojant tik vieną kodo eilutę.
Šiame straipsnyje jūs parašysite, sudarysite, išbandysite ir įdiegsite išmaniąją kavos mokėjimo sutartį su Ethereum Sepolia Testnet naudodami dRPC galutinį tašką ir API raktą.
Funkcijos apima:
- Apmokėjimas už kavą
- Kavos kainos peržiūra
- Nuskaitomas bendras parduotos kavos skaičius ir bendra uždirbtų pinigų suma
Sutepsim rankas.
Būtinos sąlygos
- Jau papildykite savo sąskaitą naudodami Sepolia Faucet.
- Turėkite piniginę, pvz., „Metamask“.
- Kodo redaktorius.
- Jau įdiegėte visas jūsų pasirinktas Js bibliotekas ar sistemas (pvz., React.js, Next.js ir tt).
- Stiklainis vandens.
- Solidumas.
- React.js naudojant Vite.js(Typescript)
- Hardhat.
- Web3.js.
- Dotenv.
- dRPC API raktas ir galutinis taškas.
- Jūsų paskyros privatus raktas.
- MetaMask
Išmaniosios kavos mokėjimo sutarties rašymas
- Sukurkite aplanką savo šakniniame kataloge ir pavadinkite jį
contracts
. - Sukurkite failą po
contracts
aplanką ir pavadinkite jįcoffee.sol
.
rašydami išmaniąją sutartį naudosite solidumą. Solidity failai pavadinti su
.sol
plėtinį, nes tai yra standartinis „Solidity“ šaltinio kodo failo plėtinys.
- Pridėkite šį šaltinio kodą prie
coffee.sol
:// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; contract Coffee { uint256 public constant coffeePrice = 0.0002 ether; uint256 public totalCoffeesSold; uint256 public totalEtherReceived; // Custom error definitions error QuantityMustBeGreaterThanZero(); error InsufficientEtherSent(uint256 required, uint256 sent); error DirectEtherTransferNotAllowed(); // Event to log coffee purchases event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost); // Function to buy coffee function buyCoffee(uint256 quantity) external payable { if (quantity <= 0) { revert QuantityMustBeGreaterThanZero(); } uint256 totalCost = coffeePrice * quantity; if (msg.value > totalCost) { revert InsufficientEtherSent(totalCost, msg.value); } // Update the total coffees sold and total ether received totalCoffeesSold += quantity; totalEtherReceived += totalCost; console.log("Total ether received updated:", totalEtherReceived); console.log("Total coffee sold updated:", totalCoffeesSold); // Emit the purchase event emit CoffeePurchased(msg.sender, quantity, totalCost); // Refund excess Ether sent if (msg.value > totalCost) { uint256 refundAmount = msg.value - totalCost; payable(msg.sender).transfer(refundAmount); } } // Fallback function to handle Ether sent directly to the contract receive() external payable { revert DirectEtherTransferNotAllowed(); } // Public view functions to get totals function getTotalCoffeesSold() external view returns (uint256) { console.log("getTotalCoffeesSold :", totalCoffeesSold); return totalCoffeesSold; } function getTotalEtherReceived() external view returns (uint256) { console.log("getTotalEtherReceived :", totalEtherReceived); return totalEtherReceived; } }
Pragma
pragma solidity >=0.8.0 <0.9.0;
: nurodoma, kad kodas parašytas Solidity versijoms nuo 0.8.0 (imtinai) iki 0.9.0 (išskyrus).
Būsenos kintamasis
uint256 public constant coffeePrice = 0.0002 ether;
uint256 public totalCoffeesSold;
uint256 public totalEtherReceived;
coffeePrice
: nustatyta kaip pastovi reikšmė0.0002 ether
.totalCoffeesSold
: seka parduotų kavos rūšių skaičių.totalEtherReceived
: seka bendrą eterio kiekį, gautą pagal sutartį.
Pasirinktinės klaidos
Pasirinktinės Solidity klaidos yra klaidų pranešimai, pritaikyti konkrečiam naudojimo atvejui, o ne numatytieji klaidų pranešimai, kuriuos pateikia programavimo kalba. Jie gali padėti pagerinti vartotojo patirtį, taip pat gali padėti derinti ir palaikyti išmaniąsias sutartis.
Norėdami apibrėžti tinkintą klaidą Solidity, galite naudoti šią sintaksę:
error
: šis raktinis žodis naudojamas pasirinktinei klaidai apibrėžti- Unikalus pavadinimas: klaida turi turėti unikalų pavadinimą
- Parametrai: jei norite įtraukti konkrečią informaciją ar parametrus į klaidos pranešimą, galite juos įtraukti skliausteliuose po klaidos pavadinimu.
error QuantityMustBeGreaterThanZero();
error InsufficientEtherSent(uint256 required, uint256 sent);
error DirectEtherTransferNotAllowed();
QuantityMustBeGreaterThanZero()
: Užtikrina, kad kiekis didesnis nei nulis.InsufficientEtherSent(uint256 required, uint256 sent)
: Užtikrina, kad atsiųsto eterio pakanka.DirectEtherTransferNotAllowed()
: Neleidžia tiesiogiai perduoti eterio į sutartį.
Renginiai
Įvykis yra sutarties dalis, kurioje saugomi argumentai, perduoti operacijų žurnaluose, kai jie išsiunčiami. Įvykiai paprastai naudojami informuoti skambinančią programą apie dabartinę sutarties būseną, naudojant EVM registravimo funkciją. Jie praneša programoms apie atliktus sutarčių pakeitimus, kurie vėliau gali būti naudojami susijusiai logikai vykdyti.
event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost);
CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost)
: Registruoja kavos pirkimus.
Funkcijos
Funkcijos yra savarankiški kodo moduliai, kurie atlieka konkrečią užduotį. Jie pašalina tos pačios kodo dalies perrašymo perteklių. Vietoj to, kūrėjai gali iškviesti funkciją programoje, kai tai būtina.
function buyCoffee(uint256 quantity) external payable {
if (quantity <= 0) {
revert QuantityMustBeGreaterThanZero();
}
uint256 totalCost = coffeePrice * quantity;
if (msg.value > totalCost) {
revert InsufficientEtherSent(totalCost, msg.value);
}
// Update the total coffees sold and total ether received
totalCoffeesSold += quantity;
totalEtherReceived += totalCost;
console.log("Total ether received updated:", totalEtherReceived);
console.log("Total coffee sold updated:", totalCoffeesSold);
// Emit the purchase event
emit CoffeePurchased(msg.sender, quantity, totalCost);
// Refund excess Ether sent
if (msg.value > totalCost) {
uint256 refundAmount = msg.value - totalCost;
payable(msg.sender).transfer(refundAmount);
}
}
receive() external payable {
revert DirectEtherTransferNotAllowed();
}
function getTotalCoffeesSold() external view returns (uint256) {
console.log("getTotalCoffeesSold :", totalCoffeesSold);
return totalCoffeesSold;
}
function getTotalEtherReceived() external view returns (uint256) {
console.log("getTotalEtherReceived :", totalEtherReceived);
return totalEtherReceived;
}
buyCoffee(uint256 quantity) external payable
: tvarko kavos pirkimą ir atlieka šias operacijas:- Patikrinkite, ar kiekis tinkamas.
- Apskaičiuoja bendrą kainą.
- Užtikrina, kad būtų išsiųsta pakankamai eterio.
- Atnaujina būsenos kintamuosius.
- Išleidžia pirkimo įvykį.
- Grąžina eterio perteklių.
receive() external payable
: Grąžina tiesioginius eterio pervedimus, jei kas nors siunčia lėšas tiesiogiai sutarties adresu.getTotalCoffeesSold() external view returns (uint256)
: grąžina visą parduotą kavos kiekį.getTotalEtherReceived() external view returns (uint256)
: grąžina visą gautą eterį.
Išmaniosios kavos mokėjimo sutarties sudarymas
Čia jūs naudosite „Hardhat“, kad sudarytumėte išmaniąją sutartį.
- Įdiekite „Hardhat“ naudodami šią komandų eilutę.
npm install --save-dev hardhat
Po sėkmingo įdiegimo gausite atsakymą žemiau.
- Tame pačiame kataloge, kuriame inicijuojate hardhat naudodami šią komandų eilutę:
npx hardhat init
- Pasirinkite
Create a Javascript project
naudodami rodyklės žemyn mygtuką ir paspauskite enter. - Paspauskite Enter, kad įdiegtumėte šakniniame aplanke
- Priimkite visus raginimus naudodami
y
klaviatūroje, įskaitant@nomicfoundation/hardhat-toolbox
priklausomybės - Žemiau matote šį atsakymą, rodantį, kad sėkmingai inicijavote
Pastebėsite, kad prie jūsų projekto buvo pridėta naujų aplankų ir failų. pvz.,
Lock.sol
,iginition/modules
,test/Lock.js
irhardhat.config.cjs
. Nesijaudink dėl jų.Vieninteliai naudingi yra
iginition/modules
irhardhat.config.cjs
. Vėliau sužinosite, kam jie naudojami. Nedvejodami ištrinkiteLock.sol
pagalcontracts
aplankas irLock.js
pagaliginition/modules
aplanką.
- Sudarykite sutartį naudodami šią komandų eilutę:
npx hardhat compile
- Matote papildomų aplankų ir failų, tokių kaip šis.
- Viduje
Coffee.json
failas yra ABI kodas JSON formatu, kurį iškviesite bendraudami su išmaniąja sutartimi.
{
"_format": "hh-sol-artifact-1",
"contractName": "Coffee",
"sourceName": "contracts/coffee.sol",
"abi": (
{
"inputs": (),
"name": "DirectEtherTransferNotAllowed",
"type": "error"
},
{
"inputs": (
{
"internalType": "uint256",
"name": "required",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "sent",
"type": "uint256"
}
),
"name": "InsufficientEtherSent",
"type": "error"
},
{
"inputs": (),
"name": "QuantityMustBeGreaterThanZero",
"type": "error"
},
{
"anonymous": false,
"inputs": (
{
"indexed": true,
"internalType": "address",
"name": "buyer",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "totalCost",
"type": "uint256"
}
),
"name": "CoffeePurchased",
"type": "event"
},
{
"inputs": (
{
"internalType": "uint256",
"name": "quantity",
"type": "uint256"
}
),
"name": "buyCoffee",
"outputs": (),
"stateMutability": "payable",
"type": "function"
},
{
"inputs": (),
"name": "coffeePrice",
"outputs": (
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
),
"stateMutability": "view",
"type": "function"
},
{
"inputs": (),
"name": "getTotalCoffeesSold",
"outputs": (
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
),
"stateMutability": "view",
"type": "function"
},
{
"inputs": (),
"name": "getTotalEtherReceived",
"outputs": (
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
),
"stateMutability": "view",
"type": "function"
},
{
"inputs": (),
"name": "totalCoffeesSold",
"outputs": (
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
),
"stateMutability": "view",
"type": "function"
},
{
"inputs": (),
"name": "totalEtherReceived",
"outputs": (
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
),
"stateMutability": "view",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
),
"bytecode": "0x608060405234801561001057600080fd5b506107d7806100206000396000f3fe6080604052600436106100595760003560e01c80631c8a403814610094578063657b2d89146100bf5780637ef3e741146100ea5780639fd66f9014610115578063b03b4a2914610140578063e926b8d01461015c5761008f565b3661008f576040517ebbbfa300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080fd5b3480156100a057600080fd5b506100a9610187565b6040516100b69190610537565b60405180910390f35b3480156100cb57600080fd5b506100d4610191565b6040516100e19190610537565b60405180910390f35b3480156100f657600080fd5b506100ff6101dc565b60405161010c9190610537565b60405180910390f35b34801561012157600080fd5b5061012a6101e2565b6040516101379190610537565b60405180910390f35b61015a60048036038101906101559190610583565b6101e8565b005b34801561016857600080fd5b506101716103e7565b60405161017e9190610537565b60405180910390f35b65b5e620f4800081565b60006101d46040518060400160405280601781526020017f676574546f74616c45746865725265636569766564203a000000000000000000815250600154610432565b600154905090565b60015481565b60005481565b60008111610222576040517f0cdcd02000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008165b5e620f4800061023691906105df565b90508034111561027f5780346040517f8ad0844f000000000000000000000000000000000000000000000000000000008152600401610276929190610621565b60405180910390fd5b81600080828254610290919061064a565b9250508190555080600160008282546102a9919061064a565b925050819055506102f16040518060400160405280601d81526020017f546f74616c20657468657220726563656976656420757064617465643a000000815250600154610432565b6103326040518060400160405280601a81526020017f546f74616c20636f6666656520736f6c6420757064617465643a000000000000815250600054610432565b3373ffffffffffffffffffffffffffffffffffffffff167fb706f7a46856e7a0e4f8f504c23f2ac26950209db23c2125108eed5ef9e333d3838360405161037a929190610621565b60405180910390a2803411156103e35760008134610398919061067e565b90503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156103e0573d6000803e3d6000fd5b50505b5050565b600061042a6040518060400160405280601581526020017f676574546f74616c436f6666656573536f6c64203a0000000000000000000000815250600054610432565b600054905090565b6104ca8282604051602401610448929190610742565b6040516020818303038152906040527fb60e72cc000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506104ce565b5050565b6104e5816104dd6104e8610509565b63ffffffff16565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b610514819050919050565b61051c610772565b565b6000819050919050565b6105318161051e565b82525050565b600060208201905061054c6000830184610528565b92915050565b600080fd5b6105608161051e565b811461056b57600080fd5b50565b60008135905061057d81610557565b92915050565b60006020828403121561059957610598610552565b5b60006105a78482850161056e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006105ea8261051e565b91506105f58361051e565b92508282026106038161051e565b9150828204841483151761061a576106196105b0565b5b5092915050565b60006040820190506106366000830185610528565b6106436020830184610528565b9392505050565b60006106558261051e565b91506106608361051e565b9250828201905080821115610678576106776105b0565b5b92915050565b60006106898261051e565b91506106948361051e565b92508282039050818111156106ac576106ab6105b0565b5b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156106ec5780820151818401526020810190506106d1565b60008484015250505050565b6000601f19601f8301169050919050565b6000610714826106b2565b61071e81856106bd565b935061072e8185602086016106ce565b610737816106f8565b840191505092915050565b6000604082019050818103600083015261075c8185610709565b905061076b6020830184610528565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfea264697066735822122006c7d91368c8390cb4f21f6314ccd362b6d56cb17994af7009b53e7fb92411a864736f6c63430008180033",
"deployedBytecode": "0x6080604052600436106100595760003560e01c80631c8a403814610094578063657b2d89146100bf5780637ef3e741146100ea5780639fd66f9014610115578063b03b4a2914610140578063e926b8d01461015c5761008f565b3661008f576040517ebbbfa300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080fd5b3480156100a057600080fd5b506100a9610187565b6040516100b69190610537565b60405180910390f35b3480156100cb57600080fd5b506100d4610191565b6040516100e19190610537565b60405180910390f35b3480156100f657600080fd5b506100ff6101dc565b60405161010c9190610537565b60405180910390f35b34801561012157600080fd5b5061012a6101e2565b6040516101379190610537565b60405180910390f35b61015a60048036038101906101559190610583565b6101e8565b005b34801561016857600080fd5b506101716103e7565b60405161017e9190610537565b60405180910390f35b65b5e620f4800081565b60006101d46040518060400160405280601781526020017f676574546f74616c45746865725265636569766564203a000000000000000000815250600154610432565b600154905090565b60015481565b60005481565b60008111610222576040517f0cdcd02000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008165b5e620f4800061023691906105df565b90508034111561027f5780346040517f8ad0844f000000000000000000000000000000000000000000000000000000008152600401610276929190610621565b60405180910390fd5b81600080828254610290919061064a565b9250508190555080600160008282546102a9919061064a565b925050819055506102f16040518060400160405280601d81526020017f546f74616c20657468657220726563656976656420757064617465643a000000815250600154610432565b6103326040518060400160405280601a81526020017f546f74616c20636f6666656520736f6c6420757064617465643a000000000000815250600054610432565b3373ffffffffffffffffffffffffffffffffffffffff167fb706f7a46856e7a0e4f8f504c23f2ac26950209db23c2125108eed5ef9e333d3838360405161037a929190610621565b60405180910390a2803411156103e35760008134610398919061067e565b90503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156103e0573d6000803e3d6000fd5b50505b5050565b600061042a6040518060400160405280601581526020017f676574546f74616c436f6666656573536f6c64203a0000000000000000000000815250600054610432565b600054905090565b6104ca8282604051602401610448929190610742565b6040516020818303038152906040527fb60e72cc000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506104ce565b5050565b6104e5816104dd6104e8610509565b63ffffffff16565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b610514819050919050565b61051c610772565b565b6000819050919050565b6105318161051e565b82525050565b600060208201905061054c6000830184610528565b92915050565b600080fd5b6105608161051e565b811461056b57600080fd5b50565b60008135905061057d81610557565b92915050565b60006020828403121561059957610598610552565b5b60006105a78482850161056e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006105ea8261051e565b91506105f58361051e565b92508282026106038161051e565b9150828204841483151761061a576106196105b0565b5b5092915050565b60006040820190506106366000830185610528565b6106436020830184610528565b9392505050565b60006106558261051e565b91506106608361051e565b9250828201905080821115610678576106776105b0565b5b92915050565b60006106898261051e565b91506106948361051e565b92508282039050818111156106ac576106ab6105b0565b5b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156106ec5780820151818401526020810190506106d1565b60008484015250505050565b6000601f19601f8301169050919050565b6000610714826106b2565b61071e81856106bd565b935061072e8185602086016106ce565b610737816106f8565b840191505092915050565b6000604082019050818103600083015261075c8185610709565b905061076b6020830184610528565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fdfea264697066735822122006c7d91368c8390cb4f21f6314ccd362b6d56cb17994af7009b53e7fb92411a864736f6c63430008180033",
"linkReferences": {},
"deployedLinkReferences": {}
}
Išmaniosios sutarties testavimas
Sudarant išmaniąją sutartį labai svarbu ir labai rekomenduojama parašyti automatinį bandomąjį scenarijų. Jis veikia kaip dviejų veiksnių autentifikavimas (2FA), užtikrinantis, kad jūsų išmanioji sutartis veiktų taip, kaip tikėtasi, prieš įdiegiant ją į tiesioginį tinklą.
Pagal test
aplanke sukurkite naują failą ir pavadinkite jį Coffee.
cjs. Failo viduje įklijuokite šį kodą žemiau:
const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers.js");
const { expect } = require("chai");
const pkg = require("hardhat");
const ABI = require('../artifacts/contracts/coffee.sol/Coffee.json');
const { web3 } = pkg;
describe("Coffee Contract", function () {
// Fixture to deploy the Coffee contract
async function deployCoffeeFixture() {
const coffeeContract = new web3.eth.Contract(ABI.abi);
coffeeContract.handleRevert = true;
const (deployer, buyer) = await web3.eth.getAccounts();
const rawContract = coffeeContract.deploy({
data: ABI.bytecode,
});
// Estimate gas for the deployment
const estimateGas = await rawContract.estimateGas({ from: deployer });
// Deploy the contract
const coffee = await rawContract.send({
from: deployer,
gas: estimateGas.toString(),
gasPrice: "10000000000",
});
console.log("Coffee contract deployed to: ", coffee.options.address);
return { coffee, deployer, buyer, rawContract };
}
describe("Deployment", function () {
// Test to check initial values after deployment
it("Should set the initial values correctly", async function () {
const { coffee } = await loadFixture(deployCoffeeFixture);
const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call();
const totalEtherReceived = await coffee.methods.totalEtherReceived().call();
expect(totalCoffeesSold).to.equal("0");
expect(totalEtherReceived).to.equal("0");
});
});
describe("Buying Coffee", function () {
// Test to check coffee purchase and event emission
it("Should purchase coffee and emit an event", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
const quantity = 3;
const totalCost = web3.utils.toWei("0.0006", "ether");
// Buyer purchases coffee
const receipt = await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost });
// Check event
const event = receipt.events.CoffeePurchased;
expect(event).to.exist;
expect(event.returnValues.buyer).to.equal(buyer);
expect(event.returnValues.quantity).to.equal(String(quantity));
expect(event.returnValues.totalCost).to.equal(totalCost);
});
// Test to check revert when quantity is zero
it("Should revert if the quantity is zero", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
expect(
coffee.methods.buyCoffee(0).send({ from: buyer, value: web3.utils.toWei("0.0002", "ether") })
).to.be.revertedWith("QuantityMustBeGreaterThanZero");
});
// Test to check if totalCoffeesSold and totalEtherReceived are updated correctly
it("Should update totalCoffeesSold and totalEtherReceived correctly", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
const quantity = 5;
const totalCost = web3.utils.toWei("0.001", "ether");
await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost });
const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call();
const totalEtherReceived = await coffee.methods.totalEtherReceived().call();
expect(totalCoffeesSold).to.equal(String(quantity));
expect(totalEtherReceived).to.equal(totalCost);
});
});
describe("Fallback function", function () {
// Test to check revert when ether is sent directly to the contract
it("Should revert if ether is sent directly to the contract", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
expect(
web3.eth.sendTransaction({
from: buyer,
to: coffee.options.address,
value: web3.utils.toWei("0.001", "ether"),
})
).to.be.revertedWith("DirectEtherTransferNotAllowed");
});
});
});
Šis kodas patikrina „Coffee smart contract“ funkcionalumą. Tai apima diegimo, kavos pirkimo ir tiesioginių eterio perkėlimų į sutartį tvarkymo testus.
Štai suskirstymas:
Tvirtinimo funkcija: deployCoffeeFixture
async function deployCoffeeFixture() {
const coffeeContract = new web3.eth.Contract(ABI.abi);
coffeeContract.handleRevert = true;
const (deployer, buyer) = await web3.eth.getAccounts();
const rawContract = coffeeContract.deploy({
data: ABI.bytecode,
});
const estimateGas = await rawContract.estimateGas({ from: deployer });
const coffee = await rawContract.send({
from: deployer,
gas: estimateGas.toString(),
gasPrice: "10000000000",
});
console.log("Coffee contract deployed to: ", coffee.options.address);
return { coffee, deployer, buyer, rawContract };
}
- Taiko kavos sutartį: sukuria naują sutarties egzempliorių ir diegia jį naudojant diegimo paskyrą.
- Apskaičiuoja dujas: apskaičiuoja, kiek dujų reikia diegimui.
- Grąžina: įdiegtas sutarties egzempliorius, diegimo ir pirkėjo paskyros.
Diegimo testai
describe("Deployment", function () {
it("Should set the initial values correctly", async function () {
const { coffee } = await loadFixture(deployCoffeeFixture);
const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call();
const totalEtherReceived = await coffee.methods.totalEtherReceived().call();
expect(totalCoffeesSold).to.equal("0");
expect(totalEtherReceived).to.equal("0");
});
});
- Tikrina pradines vertes: Tai užtikrina
totalCoffeesSold
irtotalEtherReceived
po įdiegimo nustatomi į nulį.
Kavos pirkimo testai
describe("Buying Coffee", function () {
it("Should purchase coffee and emit an event", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
const quantity = 3;
const totalCost = web3.utils.toWei("0.0006", "ether");
const receipt = await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost });
const event = receipt.events.CoffeePurchased;
expect(event).to.exist;
expect(event.returnValues.buyer).to.equal(buyer);
expect(event.returnValues.quantity).to.equal(String(quantity));
expect(event.returnValues.totalCost).to.equal(totalCost);
});
it("Should revert if the quantity is zero", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
expect(
coffee.methods.buyCoffee(0).send({ from: buyer, value: web3.utils.toWei("0.0002", "ether") })
).to.be.revertedWith("QuantityMustBeGreaterThanZero");
});
it("Should update totalCoffeesSold and totalEtherReceived correctly", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
const quantity = 5;
const totalCost = web3.utils.toWei("0.001", "ether");
await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost });
const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call();
const totalEtherReceived = await coffee.methods.totalEtherReceived().call();
expect(totalCoffeesSold).to.equal(String(quantity));
expect(totalEtherReceived).to.equal(totalCost);
});
});
- Kavos pirkimas ir renginio išleidimas: Tikrina, kad kavos pirkimas atnaujina būseną ir išskiria
CoffeePurchased
renginys. - Grąžinama į nulinį kiekį: Užtikrina, kad operacija būtų grąžinta, jei kiekis lygus nuliui.
- Teisingai atnaujinama būsena: Tai patvirtina
totalCoffeesSold
irtotalEtherReceived
yra tinkamai atnaujinami po pirkimo.
Atsarginės funkcijos testas
describe("Fallback function", function () {
it("Should revert if ether is sent directly to the contract", async function () {
const { coffee, buyer } = await loadFixture(deployCoffeeFixture);
expect(
web3.eth.sendTransaction({
from: buyer,
to: coffee.options.address,
value: web3.utils.toWei("0.001", "ether"),
})
).to.be.revertedWith("DirectEtherTransferNotAllowed");
});
});
- Grįžtama prie tiesioginio eterio perdavimo: užtikrina, kad eterio siuntimas tiesiai į sutartį (neiškvietęs funkcijos) grąžintų operaciją.
Išmaniosios sutarties testavimas
Parašę testo scenarijų, atliksite toliau nurodytus veiksmus.
- Vykdydami sutartis ir testuodami „Hardhat Network“, galite spausdinti registravimo pranešimus ir sutarties kintamuosius skambinant
console.log()
iš jūsų solidumo kodo. Norėdami jį naudoti, turite importuotihardhat/console.sol
savo sutarties kode taip:
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "hardhat/console.sol";
contract Coffee {
//...
}
- Norėdami patikrinti sutartį, savo terminale paleiskite šią komandą:
npx hardhat test
- Turėtumėte turėti tokią išvestį kaip žemiau:
Tai rodo, kad jūsų išmanioji sutartis veikia taip, kaip tikimasi.
Jei bėgate
npx hardhat test
ji automatiškai sukompiliuoja ir išbando išmaniąją sutartį. Galite tai išbandyti ir leiskite man sužinokite komentarų skiltyje.
Diegimas Išmanioji sutartis
Čia jūs įdiegsite savo išmaniąją sutartį su Sepolia Testnet. „Testnet“ leidžia išbandyti išmaniąją sutartį aplinkoje, kuri imituoja „Ethereum“ pagrindinį tinklą, nepatiriant didelių išlaidų. Jei gerai naudojate „dApp“ funkciją, galite perskirstyti ją į „Ethereum Mainnet“.
- Įdiekite dotenv paketą ir šias priklausomybes.
npm install dotenv npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4'
Tai pridės Web3.Js ir Dotenv prie jūsų projekto įtraukiant juos į aplanką „node_modules“.
- importuoti juos į savo
hardhat.config.cjs
failąrequire('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); module.exports = { solidity: "0.8.24", } };
- Sukurti an
.env
failą savo šakniniame aplanke. - Gaukite paskyros privatų raktą iš savo MetaMask piniginės ir dRPC API rakto.
- Laikykite juos savo
.env
failą.DRPC_API_KEY=your_drpc_api_key PRIVATE_KEY=your_wallet_private_key
- Atnaujinkite
hardhat.config.cjs
failą, kad būtų įtraukta Sepolia Testnet konfigūracija:require('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); const dRPC_API_KEY = process.env.VITE_dRPC_API_KEY; const PRIVATE_KEY = process.env.VITE_PRIVATE_KEY; module.exports = { solidity: "0.8.24", networks: { sepolia: { url: `https://lb.drpc.org/ogrpc?network=sepolia&dkey=${dRPC_API_KEY}`, accounts: (`0x${PRIVATE_KEY}`), } } };
- Sukurkite naują scenarijaus failą pagal
ignition/module
aplanką ir pavadinkite jįdeploy.cjs
. Pridėkite šį kodą, kad įdiegtumėte išmaniąją sutartį:const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); const CoffeeModule = buildModule("CoffeeModule", (m) => { const coffee = m.contract("Coffee"); return { coffee }; }); module.exports = CoffeeModule;
- Įdiekite išmaniąją sutartį vykdydami šią komandą savo terminale:
npx hardhat ignition deploy ./ignition/modules/deploy.cjs --network sepolia
Paleidus komandų eilutę, jūsų bus paprašyta
Confirm deploy to network sepolia (11155111)? (y/n)
įveskitey
. Sėkmingai įdiegę terminale turėtumėte matyti įdiegtos išmaniosios sutarties adresą.Sutarties adresą taip pat galite pasiekti
deployed_addresses.json
failą.
Išvada
Šis straipsnis išmokė jus parašyti išmaniąją mokėjimo sutartį, išbandyti, sudaryti ir įdiegti išmaniąją sutartį naudojant „hardhat CLI“.
Kitame straipsnyje sužinosite, kaip sukurti šios dApp priekinę dalį. Šią vartotojo sąsają sudarys:
- Įveskite nupirktų kavos skaičių.
- Mygtukas, kuris suaktyvina mokėjimo operaciją ir išskaito ją iš jūsų sąskaitos.
- Rodyti visą nupirktą kavą ir gautą sumą eteriu ir USD
- Pačios kavos kaina tiek eteriu, tiek USD.
Nuoroda
Be numatytųjų pranešimų: tinkintų klaidų įvaldymas solidumo srityje
Tinkintų klaidų įvaldymas solidumo srityje: padidinkite savo išmaniąsias sutartis daugiau nei numatytuosius pranešimus
Kas yra solidumo funkcijos?
Kas yra Solidity įvykiai?
← Ankstesnis straipsnis Kitas straipsnis →