Iepazīstieties ar Solidity – vadošo programmēšanas valodu viedo līgumu izstrādei Ethereum blokķēdē. Ceļvedis aptver visu no pamatkonceptiem līdz sarežģītām tehnikām.
Solidity: Visaptverošs ceļvedis viedo līgumu programmēšanā
Solidity ir augsta līmeņa, uz līgumiem orientēta programmēšanas valoda, ko izmanto viedo līgumu ieviešanai dažādās blokķēdes platformās, jo īpaši Ethereum. Tā ir spēcīgi ietekmēta no C++, Python un JavaScript, un ir izstrādāta, lai mērķētu uz Ethereum virtuālo mašīnu (EVM). Šis ceļvedis sniedz detalizētu pārskatu par Solidity, piemērots gan iesācējiem, gan pieredzējušiem programmētājiem, kuri vēlas iedziļināties blokķēdes izstrādes pasaulē.
Kas ir viedie līgumi?
Pirms iedziļināties Solidity, ir ļoti svarīgi saprast, kas ir viedie līgumi. Viedais līgums ir pašizpildošs līgums, kura vienošanās nosacījumi ir tieši ierakstīti kodā. Tas tiek glabāts blokķēdē un automātiski izpildās, kad tiek izpildīti iepriekš noteikti nosacījumi. Viedie līgumi nodrošina automatizāciju, caurspīdīgumu un drošību dažādās lietojumprogrammās, tostarp:
- Decentralizētās finanses (DeFi): Aizdošanas, aizņemšanās un tirdzniecības platformas.
- Piegādes ķēdes pārvaldība: Preču izsekošana un caurspīdīguma nodrošināšana.
- Balsošanas sistēmas: Droša un pārbaudāma elektroniskā balsošana.
- Nekustamais īpašums: Īpašuma darījumu automatizācija.
- Veselības aprūpe: Pacientu datu droša pārvaldība.
Kāpēc Solidity?
Solidity ir dominējošā valoda viedo līgumu rakstīšanai Ethereum un citās ar EVM saderīgās blokķēdēs vairāku faktoru dēļ:
- EVM saderība: Solidity ir īpaši izstrādāta, lai kompilētos baitkodā, kas var darboties Ethereum virtuālajā mašīnā.
- Kopienas atbalsts: Liela un aktīva kopiena nodrošina plašu dokumentāciju, bibliotēkas un rīkus.
- Drošības funkcijas: Solidity ietver funkcijas, lai mazinātu biežas viedo līgumu ievainojamības.
- Augsta līmeņa abstrakcija: Piedāvā augsta līmeņa konstrukcijas, kas padara līgumu izstrādi efektīvāku un pārvaldāmāku.
Izstrādes vides iestatīšana
Lai sāktu izstrādi ar Solidity, jums būs jāiestata piemērota izstrādes vide. Šeit ir dažas populāras iespējas:
Remix IDE
Remix ir tiešsaistes, pārlūkprogrammas IDE, kas ir lieliski piemērota Solidity apguvei un eksperimentēšanai. Tam nav nepieciešama lokāla instalācija un tas nodrošina tādas funkcijas kā:
- Koda redaktors ar sintakses izcelšanu un automātisko pabeigšanu.
- Kompilators Solidity koda pārveidošanai baitkodā.
- Izvietotājs līgumu izvietošanai testēšanas tīklos vai galvenajā tīklā.
- Atkļūdotājs koda izpildei pa soļiem un kļūdu identificēšanai.
Piekļūstiet Remix IDE vietnē https://remix.ethereum.org/
Truffle Suite
Truffle ir visaptverošs izstrādes ietvars, kas vienkāršo viedo līgumu būvēšanas, testēšanas un izvietošanas procesu. Tas nodrošina tādus rīkus kā:
- Truffle: Komandrindas rīks projektu izveidei, kompilācijai, izvietošanai un testēšanai.
- Ganache: Personīga blokķēde lokālai izstrādei.
- Drizzle: Priekšgala bibliotēku kolekcija, kas atvieglo viedo līgumu integrāciju ar lietotāja saskarnēm.
Lai instalētu Truffle:
npm install -g truffle
Hardhat
Hardhat ir vēl viena populāra Ethereum izstrādes vide, kas pazīstama ar savu elastību un paplašināmību. Tā ļauj jums kompilēt, izvietot, testēt un atkļūdot savu Solidity kodu. Galvenās funkcijas ietver:
- Iebūvēts lokālais Ethereum tīkls testēšanai.
- Spraudņu ekosistēma funkcionalitātes paplašināšanai.
- Console.log atkļūdošana.
Lai instalētu Hardhat:
npm install --save-dev hardhat
Solidity pamati: Sintakse un datu tipi
Aplūkosim Solidity pamat sintaksi un datu tipus.
Solidity līguma struktūra
Solidity līgums ir līdzīgs klasei objektorientētā programmēšanā. Tas sastāv no stāvokļa mainīgajiem, funkcijām un notikumiem. Šeit ir vienkāršs piemērs:
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
Paskaidrojums:
pragma solidity ^0.8.0;
: Norāda Solidity kompilatora versiju. Ir svarīgi izmantot saderīgu versiju, lai izvairītos no neparedzētas uzvedības.contract SimpleStorage { ... }
: Definē līgumu ar nosaukumuSimpleStorage
.uint256 storedData;
: Deklarē stāvokļa mainīgo ar nosaukumustoredData
, kas ir tipsuint256
(bez zīmes vesels skaitlis ar 256 bitiem).function set(uint256 x) public { ... }
: Definē funkciju ar nosaukumuset
, kas ņem bez zīmes veselu skaitli kā ievadi un atjauninastoredData
mainīgo. Atslēgvārdspublic
nozīmē, ka funkciju var izsaukt ikviens.function get() public view returns (uint256) { ... }
: Definē funkciju ar nosaukumuget
, kas atgriežstoredData
vērtību. Atslēgvārdsview
norāda, ka funkcija nemodificē līguma stāvokli.
Datu tipi
Solidity atbalsta dažādus datu tipus:
- Veselie skaitļi:
uint
(bez zīmes vesels skaitlis) unint
(ar zīmi vesels skaitlis) ar dažādiem izmēriem (piemēram,uint8
,uint256
). - Būla vērtības:
bool
(true
vaifalse
). - Adreses:
address
(apzīmē Ethereum adresi). - Baiti:
bytes
(fiksēta izmēra baitu masīvi) unstring
(dinamiska izmēra virkne). - Masīvi: Fiksēta izmēra (piemēram,
uint[5]
) un dinamiska izmēra (piemēram,uint[]
). - Kartēšana: Atslēgu-vērtību pāri (piemēram,
mapping(address => uint)
).
Piemērs:
pragma solidity ^0.8.0;
contract DataTypes {
uint256 public age = 30;
bool public isAdult = true;
address public owner = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
bytes32 public name = "JohnDoe";
uint[] public numbers = [1, 2, 3, 4, 5];
mapping(address => uint) public balances;
constructor() {
balances[msg.sender] = 100;
}
}
Stāvokļa mainīgie vs. Lokālie mainīgie
Stāvokļa mainīgie tiek deklarēti ārpus funkcijām un glabāti blokķēdē. Tie saglabājas pāri funkciju izsaukumiem un līgumu izpildēm. Iepriekš minētajā piemērā storedData
ir stāvokļa mainīgais.
Lokālie mainīgie tiek deklarēti funkciju iekšienē un eksistē tikai šīs funkcijas darbības laukā. Tie netiek glabāti blokķēdē un tiek atmesti, kad funkcija pabeidz izpildi.
Funkcijas Solidity valodā
Funkcijas ir viedo līgumu pamatelementi. Tās definē loģiku un operācijas, ko līgums var veikt. Funkcijas var:
- Mainīt līguma stāvokli.
- Lasīt datus no līguma stāvokļa.
- Mijiedarboties ar citiem līgumiem.
- Nosūtīt vai saņemt Ether.
Funkciju redzamība
Solidity funkcijām ir četri redzamības modifikatori:
- public: Var izsaukt gan iekšēji, gan ārēji.
- private: Var izsaukt tikai iekšēji no līguma.
- internal: Var izsaukt iekšēji no līguma un atvasinātajiem līgumiem.
- external: Var izsaukt tikai ārēji.
Funkciju modifikatori
Funkciju modifikatorus izmanto, lai mainītu funkcijas uzvedību. Tos bieži izmanto, lai ieviestu drošības ierobežojumus vai veiktu pārbaudes pirms funkcijas loģikas izpildes.
Piemērs:
pragma solidity ^0.8.0;
contract Ownership {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
function transferOwnership(address newOwner) public onlyOwner {
owner = newOwner;
}
}
Šajā piemērā onlyOwner
modifikators pārbauda, vai izsaucējs ir līguma īpašnieks. Ja nav, tas atceļ darījumu. Vietaizvietotājs _
apzīmē pārējo funkcijas kodu.
Funkciju stāvokļa mainīgums
Solidity funkcijām var būt arī stāvokļa mainīguma modifikatori:
- view: Norāda, ka funkcija nemodificē līguma stāvokli. Tā var lasīt stāvokļa mainīgos, bet nevar tajos rakstīt.
- pure: Norāda, ka funkcija nelasa un nemodificē līguma stāvokli. Tā ir pilnīgi autonoma un deterministiska.
- payable: Norāda, ka funkcija var saņemt Ether.
Piemērs:
pragma solidity ^0.8.0;
contract Example {
uint256 public value;
function getValue() public view returns (uint256) {
return value;
}
function add(uint256 x) public pure returns (uint256) {
return x + 5;
}
function deposit() public payable {
value += msg.value;
}
}
Kontroles struktūras
Solidity atbalsta standarta kontroles struktūras, piemēram, if
, else
, for
, while
un do-while
ciklus.
Piemērs:
pragma solidity ^0.8.0;
contract ControlStructures {
function checkValue(uint256 x) public pure returns (string memory) {
if (x > 10) {
return "Value is greater than 10";
} else if (x < 10) {
return "Value is less than 10";
} else {
return "Value is equal to 10";
}
}
function sumArray(uint[] memory arr) public pure returns (uint256) {
uint256 sum = 0;
for (uint256 i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
}
Notikumi un žurnālēšana
Notikumi ļauj viedajiem līgumiem sazināties ar ārpasauli. Kad notikums tiek emitēts, tas tiek saglabāts blokķēdes darījumu žurnālos. Šos žurnālus var uzraudzīt ārējās lietojumprogrammas, lai izsekotu līguma darbību.
Piemērs:
pragma solidity ^0.8.0;
contract EventExample {
event ValueChanged(address indexed caller, uint256 newValue);
uint256 public value;
function setValue(uint256 newValue) public {
value = newValue;
emit ValueChanged(msg.sender, newValue);
}
}
Šajā piemērā notikums ValueChanged
tiek emitēts ikreiz, kad tiek izsaukta funkcija setValue
. Atslēgvārds indexed
uz parametra caller
ļauj ārējām lietojumprogramām filtrēt notikumus, pamatojoties uz izsaucēja adresi.
Pārmantošana
Solidity atbalsta pārmantošanu, ļaujot jums izveidot jaunus līgumus, pamatojoties uz esošajiem. Tas veicina koda atkārtotu izmantošanu un modularitāti.
Piemērs:
pragma solidity ^0.8.0;
contract BaseContract {
uint256 public value;
function setValue(uint256 newValue) public {
value = newValue;
}
}
contract DerivedContract is BaseContract {
function incrementValue() public {
value++;
}
}
Šajā piemērā DerivedContract
pārmanto no BaseContract
. Tas pārmanto stāvokļa mainīgo value
un funkciju setValue
. Tas arī definē savu funkciju incrementValue
.
Bibliotēkas
Bibliotēkas ir līdzīgas līgumiem, taču tās nevar glabāt datus. Tās tiek izmantotas atkārtoti izmantojama koda izvietošanai, ko var izsaukt vairāki līgumi. Bibliotēkas tiek izvietotas tikai vienu reizi, kas samazina gāzes izmaksas.
Piemērs:
pragma solidity ^0.8.0;
library Math {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
}
contract Example {
using Math for uint256;
uint256 public result;
function calculateSum(uint256 x, uint256 y) public {
result = x.add(y);
}
}
Šajā piemērā bibliotēka Math
definē funkciju add
. Paziņojums using Math for uint256;
ļauj izsaukt funkciju add
uz uint256
mainīgajiem, izmantojot punktu notāciju.
Bieži sastopamās viedo līgumu ievainojamības
Viedie līgumi ir pakļauti dažādām ievainojamībām, kas var novest pie līdzekļu zaudēšanas vai neparedzētas uzvedības. Ir ļoti svarīgi apzināties šīs ievainojamības un veikt pasākumus to mazināšanai.
Atkārtota ievadīšana (Reentrancy)
Atkārtota ievadīšana notiek, kad līgums izsauc ārēju līgumu, un ārējais līgums atkal izsauc sākotnējo līgumu pirms sākotnējā līguma izpildes pabeigšanas. Tas var novest pie neparedzētām stāvokļa izmaiņām.
Mazina: Izmantojiet Checks-Effects-Interactions (Pārbaudes-Ietekmes-Mijiedarbības) modeli un apsveriet iespēju izmantot funkcijas transfer
vai send
, lai ierobežotu pieejamo gāzi ārējam izsaukumam.
Pārpilde un nepietiekamība (Overflow un Underflow)
Pārpilde notiek, kad aritmētiskā operācija pārsniedz datu tipa maksimālo vērtību. Nepietiekamība notiek, kad aritmētiskā operācija rada vērtību, kas ir mazāka par datu tipa minimālo vērtību.
Mazina: Izmantojiet SafeMath bibliotēkas (lai gan ar Solidity 0.8.0 un jaunākām versijām pārpildes un nepietiekamības pārbaudes ir iebūvētas pēc noklusējuma), lai novērstu šīs problēmas.
Atkarība no laika zīmoga (Timestamp Dependence)
Paļaušanās uz bloka laika zīmogu (block.timestamp
) var padarīt jūsu līgumu ievainojamu pret manipulācijām no kalnraču puses, jo viņiem ir zināma kontrole pār laika zīmogu.
Mazina: Izvairieties no block.timestamp
izmantošanas kritiskā loģikā. Apsveriet iespēju izmantot orākulus vai citus uzticamākus laika avotus.
Pakalpojuma atteikums (Denial of Service - DoS)
DoS uzbrukumu mērķis ir padarīt līgumu nelietojamu likumīgiem lietotājiem. To var panākt, patērējot visu pieejamo gāzi vai izmantojot ievainojamības, kas izraisa līguma atjaunošanu.
Mazina: Ieviesiet gāzes ierobežojumus, izvairieties no cikliem ar neierobežotām iterācijām un rūpīgi validējiet lietotāja ievadi.
Priekšizpilde (Front Running)
Priekšizpilde notiek, kad kāds novēro gaidošu darījumu un iesniedz savu darījumu ar augstāku gāzes cenu, lai tas tiktu izpildīts pirms sākotnējā darījuma.
Mazina: Izmantojiet "commit-reveal" shēmas vai citas metodes, lai paslēptu darījumu detaļas, līdz tās ir izpildītas.
Labākās prakses drošu viedo līgumu rakstīšanā
- Vienkāršība: Rakstiet kodolīgu un viegli saprotamu kodu.
- Ievērojiet Checks-Effects-Interactions (Pārbaudes-Ietekmes-Mijiedarbības) modeli: Pārliecinieties, ka pārbaudes tiek veiktas pirms jebkādām stāvokļa izmaiņām, un mijiedarbība ar citiem līgumiem tiek veikta pēdējā.
- Izmantojiet drošības rīkus: Izmantojiet statiskās analīzes rīkus, piemēram, Slither un Mythril, lai identificētu iespējamās ievainojamības.
- Rakstiet vienības testus: Rūpīgi pārbaudiet savus viedos līgumus, lai pārliecinātos, ka tie darbojas, kā paredzēts.
- Veiciet auditu: Pirms viedo līgumu izvietošanas galvenajā tīklā veiciet to auditu cienījamās drošības firmās.
- Esiet informēts: Sekojiet jaunākajām drošības ievainojamībām un labākajām praksēm Solidity kopienā.
Uzlaboti Solidity koncepti
Kad esat labi sapratis pamatus, varat pētīt sarežģītākus konceptus:
Assembler (Mašīnkods)
Solidity ļauj rakstīt inline mašīnkoda kodu, kas dod jums lielāku kontroli pār EVM. Tomēr tas arī palielina kļūdu un ievainojamību ieviešanas risku.
Proksi
Proksi ļauj jums jaunināt viedos līgumus, nemigrējot datus. Tas ietver proksi līguma izvietošanu, kas pārsūta izsaukumus uz implementācijas līgumu. Kad vēlaties jaunināt līgumu, jūs vienkārši izvietojat jaunu implementācijas līgumu un atjaunojat proksi, lai tas norādītu uz jauno implementāciju.
Meta-darījumi
Meta-darījumi ļauj lietotājiem mijiedarboties ar jūsu viedo līgumu, tieši nemaksājot par gāzes maksām. Tā vietā relejs maksā gāzes maksas viņu vārdā. Tas var uzlabot lietotāja pieredzi, īpaši lietotājiem, kuri ir jauni blokķēdē.
EIP-721 un EIP-1155 (NFT)
Solidity parasti izmanto, lai izveidotu neaizvietojamos marķierus (NFT), izmantojot tādus standartus kā EIP-721 un EIP-1155. Šo standartu izpratne ir ļoti svarīga NFT balstītu lietojumprogrammu veidošanai.
Solidity un blokķēdes nākotne
Solidity ir kritiska loma strauji augošajā blokķēdes tehnoloģiju ainavā. Tā kā blokķēdes pielietojums turpina pieaugt, Solidity izstrādātāji būs ļoti pieprasīti, lai veidotu inovatīvas un drošas decentralizētas lietojumprogrammas. Valoda tiek pastāvīgi atjaunināta un uzlabota, tāpēc, lai gūtu panākumus šajā jomā, ir svarīgi sekot līdzi jaunākajām izstrādēm.
Secinājums
Solidity ir jaudīga un daudzpusīga valoda viedo līgumu veidošanai Ethereum blokķēdē. Šis ceļvedis ir sniedzis visaptverošu pārskatu par Solidity, sākot no pamatkonceptiem līdz sarežģītām metodēm. Apgūstot Solidity un ievērojot labākās prakses drošai izstrādei, jūs varat sniegt ieguldījumu aizraujošajā decentralizēto lietojumprogrammu pasaulē un palīdzēt veidot blokķēdes tehnoloģijas nākotni. Vienmēr atcerieties prioritizēt drošību, rūpīgi pārbaudīt savu kodu un sekot līdzi jaunākajām izstrādēm Solidity ekosistēmā. Viedo līgumu potenciāls ir milzīgs, un ar Solidity jūs varat īstenot savas inovatīvās idejas.