Susipažinkite su „Solidity“ – pirmaujančia programavimo kalba, skirta išmaniosioms sutartims „Ethereum“ blokų grandinėje kurti. Šis išsamus vadovas apima viską nuo pagrindinių koncepcijų iki pažangių metodų.
Solidity: Išsamus išmaniųjų sutarčių programavimo vadovas
„Solidity“ yra aukšto lygio, į sutartis orientuota programavimo kalba, naudojama išmaniosioms sutartims diegti įvairiose blokų grandinės platformose, ypač „Ethereum“. Ji stipriai paveikta C++, Python ir JavaScript kalbų ir sukurta veikti su „Ethereum“ virtualia mašina (EVM). Šis vadovas pateikia išsamią „Solidity“ apžvalgą, tinkančią tiek pradedantiesiems, tiek patyrusiems programuotojams, norintiems pasinerti į blokų grandinės kūrimo pasaulį.
Kas yra išmaniosios sutartys?
Prieš pradedant gilintis į „Solidity“, labai svarbu suprasti, kas yra išmaniosios sutartys. Išmanioji sutartis yra save vykdanti sutartis, kurios susitarimo sąlygos yra tiesiogiai įrašytos į kodą. Ji saugoma blokų grandinėje ir automatiškai įvykdoma, kai įvykdomos iš anksto nustatytos sąlygos. Išmaniosios sutartys leidžia automatizuoti, užtikrinti skaidrumą ir saugumą įvairiose srityse, įskaitant:
- Decentralizuoti finansai (DeFi): Skolinimo, skolinimosi ir prekybos platformos.
- Tiekimo grandinės valdymas: Prekių sekimas ir skaidrumo užtikrinimas.
- Balsavimo sistemos: Saugus ir patikrinamas elektroninis balsavimas.
- Nekilnojamasis turtas: Nuosavybės sandorių automatizavimas.
- Sveikatos apsauga: Saugus pacientų duomenų valdymas.
Kodėl „Solidity“?
„Solidity“ yra dominuojanti kalba rašant išmaniąsias sutartis „Ethereum“ ir kitose su EVM suderinamose blokų grandinėse dėl kelių veiksnių:
- Suderinamumas su EVM: „Solidity“ yra specialiai sukurta kompiliuoti į baitkodą, kuris gali veikti „Ethereum“ virtualioje mašinoje.
- Bendruomenės palaikymas: Didelė ir aktyvi bendruomenė teikia išsamią dokumentaciją, bibliotekas ir įrankius.
- Saugumo funkcijos: „Solidity“ apima funkcijas, skirtas sumažinti įprastus išmaniųjų sutarčių pažeidžiamumus.
- Aukšto lygio abstrakcija: Siūlo aukšto lygio konstrukcijas, kurios daro sutarčių kūrimą efektyvesnį ir lengviau valdomą.
Kūrimo aplinkos nustatymas
Norėdami pradėti kurti su „Solidity“, turėsite nustatyti tinkamą kūrimo aplinką. Štai keletas populiarių parinkčių:
Remix IDE
Remix yra internetinė, naršyklės pagrindu veikianti IDE, kuri puikiai tinka mokytis ir eksperimentuoti su „Solidity“. Jai nereikia vietinės instaliacijos ir ji teikia tokias funkcijas kaip:
- Kodo redaktorius su sintaksės paryškinimu ir autoužbaigimu.
- Kompiliatorius, skirtas „Solidity“ kodui konvertuoti į baitkodą.
- Diegėjas, skirtas sutartims diegti į testavimo tinklus arba pagrindinį tinklą.
- Derintuvas, skirtas žingsniuoti per kodą ir identifikuoti klaidas.
Pasiekite Remix IDE adresu https://remix.ethereum.org/
Truffle Suite
Truffle yra išsami kūrimo sistema, kuri supaprastina išmaniųjų sutarčių kūrimo, testavimo ir diegimo procesą. Ji teikia tokius įrankius kaip:
- Truffle: Komandinės eilutės įrankis projekto karkaso kūrimui, kompiliavimui, diegimui ir testavimui.
- Ganache: Asmeninė blokų grandinė vietiniam kūrimui.
- Drizzle: Front-end bibliotekų rinkinys, palengvinantis jūsų išmaniųjų sutarčių integravimą su vartotojo sąsajomis.
Norėdami įdiegti Truffle:
npm install -g truffle
Hardhat
Hardhat yra dar viena populiari „Ethereum“ kūrimo aplinka, žinoma dėl savo lankstumo ir išplečiamumo. Ji leidžia kompiliuoti, diegti, testuoti ir derinti jūsų „Solidity“ kodą. Pagrindinės funkcijos apima:
- Integruotas vietinis „Ethereum“ tinklas testavimui.
- Papildinių ekosistema funkcionalumui išplėsti.
- Console.log derinimas.
Norėdami įdiegti Hardhat:
npm install --save-dev hardhat
„Solidity“ pagrindai: sintaksė ir duomenų tipai
Panagrinėkime pagrindinę „Solidity“ sintaksę ir duomenų tipus.
„Solidity“ sutarties struktūra
„Solidity“ sutartis yra panaši į klasę objektiniame programavime. Ją sudaro būsenos kintamieji, funkcijos ir įvykiai. Štai paprastas pavyzdys:
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
Paaiškinimas:
pragma solidity ^0.8.0;
: Nurodo „Solidity“ kompiliatoriaus versiją. Labai svarbu naudoti suderinamą versiją, kad išvengtumėte netikėto elgesio.contract SimpleStorage { ... }
: Apibrėžia sutartį pavadinimuSimpleStorage
.uint256 storedData;
: Deklaruoja būsenos kintamąjį pavadinimustoredData
, kurio tipas yrauint256
(256 bitų sveikasis skaičius be ženklo).function set(uint256 x) public { ... }
: Apibrėžia funkciją pavadinimuset
, kuri priima sveikąjį skaičių be ženklo kaip įvestį ir atnaujinastoredData
kintamąjį. Raktinis žodispublic
reiškia, kad funkciją gali iškviesti bet kas.function get() public view returns (uint256) { ... }
: Apibrėžia funkciją pavadinimuget
, kuri grąžinastoredData
vertę. Raktinis žodisview
nurodo, kad funkcija nekeičia sutarties būsenos.
Duomenų tipai
„Solidity“ palaiko įvairius duomenų tipus:
- Sveikieji skaičiai:
uint
(sveikasis skaičius be ženklo) irint
(sveikasis skaičius su ženklu) su įvairiais dydžiais (pvz.,uint8
,uint256
). - Loginės reikšmės:
bool
(true
arbafalse
). - Adresai:
address
(atstovauja „Ethereum“ adresą). - Baitai:
bytes
(fiksuoto dydžio baitų masyvai) irstring
(dinaminio dydžio eilutė). - Masyvai: Fiksuoto dydžio (pvz.,
uint[5]
) ir dinaminio dydžio (pvz.,uint[]
). - Atvaizdžiai (Mappings): Raktų-verčių poros (pvz.,
mapping(address => uint)
).
Pavyzdys:
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;
}
}
Būsenos kintamieji ir vietiniai kintamieji
Būsenos kintamieji yra deklaruojami už funkcijų ribų ir saugomi blokų grandinėje. Jie išlieka tarp funkcijų iškvietimų ir sutarčių vykdymų. Aukščiau pateiktame pavyzdyje storedData
yra būsenos kintamasis.
Vietiniai kintamieji yra deklaruojami funkcijų viduje ir egzistuoja tik tos funkcijos apimtyje. Jie nėra saugomi blokų grandinėje ir yra sunaikinami, kai funkcija baigia darbą.
Funkcijos „Solidity“ kalboje
Funkcijos yra išmaniųjų sutarčių statybiniai blokai. Jos apibrėžia logiką ir operacijas, kurias sutartis gali atlikti. Funkcijos gali:
- Keisti sutarties būseną.
- Skaityti duomenis iš sutarties būsenos.
- Sąveikauti su kitomis sutartimis.
- Siųsti arba gauti Ether.
Funkcijų matomumas
„Solidity“ funkcijos turi keturis matomumo modifikatorius:
- public: Gali būti iškviesta viduje ir išorėje.
- private: Gali būti iškviesta tik viduje, iš pačios sutarties.
- internal: Gali būti iškviesta viduje, iš pačios sutarties ir išvestinių sutarčių.
- external: Gali būti iškviesta tik išorėje.
Funkcijų modifikatoriai
Funkcijų modifikatoriai naudojami funkcijos elgesiui keisti. Jie dažnai naudojami saugumo apribojimams įgyvendinti arba patikrinimams atlikti prieš vykdant funkcijos logiką.
Pavyzdys:
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;
}
}
Šiame pavyzdyje onlyOwner
modifikatorius patikrina, ar iškviečiantysis yra sutarties savininkas. Jei ne, jis atšaukia transakciją. Simbolis _
atstoja likusį funkcijos kodą.
Funkcijos būsenos kintamumas
„Solidity“ funkcijos taip pat gali turėti būsenos kintamumo modifikatorius:
- view: Nurodo, kad funkcija nekeičia sutarties būsenos. Ji gali skaityti būsenos kintamuosius, bet negali į juos rašyti.
- pure: Nurodo, kad funkcija neskaito ir nekeičia sutarties būsenos. Ji yra visiškai autonomiška ir deterministinė.
- payable: Nurodo, kad funkcija gali priimti Ether.
Pavyzdys:
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;
}
}
Valdymo struktūros
„Solidity“ palaiko standartines valdymo struktūras, tokias kaip if
, else
, for
, while
ir do-while
ciklai.
Pavyzdys:
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;
}
}
Įvykiai ir registravimas
Įvykiai leidžia išmaniosioms sutartims bendrauti su išoriniu pasauliu. Kai įvykis yra išsiunčiamas, jis saugomas blokų grandinės transakcijų žurnaluose. Šiuos žurnalus gali stebėti išorinės programos, kad sektų sutarties veiklą.
Pavyzdys:
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);
}
}
Šiame pavyzdyje ValueChanged
įvykis išsiunčiamas kiekvieną kartą, kai iškviečiama setValue
funkcija. Raktinis žodis indexed
prie caller
parametro leidžia išorinėms programoms filtruoti įvykius pagal iškviečiančiojo adresą.
Paveldėjimas
„Solidity“ palaiko paveldėjimą, leidžiantį kurti naujas sutartis remiantis esamomis. Tai skatina kodo pakartotinį naudojimą ir moduliškumą.
Pavyzdys:
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++;
}
}
Šiame pavyzdyje DerivedContract
paveldi iš BaseContract
. Ji paveldi value
būsenos kintamąjį ir setValue
funkciją. Ji taip pat apibrėžia savo funkciją incrementValue
.
Bibliotekos
Bibliotekos yra panašios į sutartis, bet jos negali saugoti duomenų. Jos naudojamos diegti pakartotinai naudojamą kodą, kurį gali iškviesti kelios sutartys. Bibliotekos diegiamos tik vieną kartą, o tai sumažina dujų (gas) sąnaudas.
Pavyzdys:
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);
}
}
Šiame pavyzdyje Math
biblioteka apibrėžia add
funkciją. Sakinys using Math for uint256;
leidžia jums iškviesti add
funkciją uint256
kintamiesiems naudojant taško notaciją.
Dažniausi išmaniųjų sutarčių pažeidžiamumai
Išmaniosios sutartys yra jautrios įvairiems pažeidžiamumams, kurie gali lemti lėšų praradimą ar netikėtą elgesį. Labai svarbu žinoti apie šiuos pažeidžiamumus ir imtis priemonių jiems sušvelninti.
Pakartotinis įėjimas (Reentrancy)
Pakartotinis įėjimas įvyksta, kai sutartis iškviečia išorinę sutartį, o išorinė sutartis atgal iškviečia pradinę sutartį, kol pradinės sutarties vykdymas dar nebaigtas. Tai gali sukelti netikėtus būsenos pokyčius.
Mažinimas: Naudokite „Checks-Effects-Interactions“ modelį ir apsvarstykite galimybę naudoti transfer
ar send
funkcijas, kad apribotumėte dujų kiekį, prieinamą išoriniam iškvietimui.
Perpildymas ir nepakankamumas (Overflow and Underflow)
Perpildymas įvyksta, kai aritmetinė operacija viršija maksimalią duomenų tipo vertę. Nepakankamumas įvyksta, kai aritmetinės operacijos rezultatas yra mažesnis už minimalią duomenų tipo vertę.
Mažinimas: Naudokite SafeMath bibliotekas (nors nuo „Solidity“ 0.8.0 versijos perpildymo ir nepakankamumo patikrinimai yra integruoti pagal nutylėjimą), kad išvengtumėte šių problemų.
Priklausomybė nuo laiko žymės (Timestamp Dependence)
Pasikliavimas bloko laiko žyme (block.timestamp
) gali padaryti jūsų sutartį pažeidžiamą manipuliacijoms iš kasėjų pusės, nes jie turi tam tikrą kontrolę ties laiko žyme.
Mažinimas: Venkite naudoti block.timestamp
kritinei logikai. Apsvarstykite galimybę naudoti orakulus ar kitus patikimesnius laiko šaltinius.
Paslaugos trikdymas (Denial of Service - DoS)
DoS atakos siekia padaryti sutartį neprieinamą teisėtiems vartotojams. Tai galima pasiekti sunaudojant visas turimas dujas arba išnaudojant pažeidžiamumus, dėl kurių sutartis atšaukiama.
Mažinimas: Įgyvendinkite dujų limitus, venkite ciklų su neapibrėžtu iteracijų skaičiumi ir atidžiai tikrinkite vartotojų įvestis.
Aplenkimas (Front Running)
Aplenkimas įvyksta, kai kas nors pastebi laukiančią transakciją ir pateikia savo transakciją su didesne dujų kaina, kad ji būtų įvykdyta anksčiau nei pradinė transakcija.
Mažinimas: Naudokite „commit-reveal“ schemas ar kitas technikas, kad paslėptumėte transakcijos detales, kol jos nebus įvykdytos.
Geriausios praktikos rašant saugias išmaniąsias sutartis
- Paprastumas: Rašykite glaustą ir lengvai suprantamą kodą.
- Laikykitės „Checks-Effects-Interactions“ modelio: Užtikrinkite, kad patikrinimai būtų atlikti prieš atliekant bet kokius būsenos pakeitimus, o sąveika su kitomis sutartimis būtų atliekama paskutinė.
- Naudokite saugumo įrankius: Pasinaudokite statinės analizės įrankiais, tokiais kaip Slither ir Mythril, kad nustatytumėte galimus pažeidžiamumus.
- Rašykite vienetinius testus (Unit Tests): Kruopščiai testuokite savo išmaniąsias sutartis, kad užtikrintumėte, jog jos veikia kaip tikėtasi.
- Atlikite auditą: Prieš diegdami į pagrindinį tinklą, patikėkite savo išmaniųjų sutarčių auditą patikimoms saugumo firmoms.
- Būkite atnaujinę: Sekite naujausius saugumo pažeidžiamumus ir geriausias praktikas „Solidity“ bendruomenėje.
Pažangios „Solidity“ koncepcijos
Kai tvirtai suprasite pagrindus, galėsite tyrinėti pažangesnes koncepcijas:
Asembleris (Assembly)
„Solidity“ leidžia rašyti įterptinį asemblerio kodą, kuris suteikia daugiau kontrolės ties EVM. Tačiau tai taip pat padidina klaidų ir pažeidžiamumų riziką.
Tarpinės sutartys (Proxies)
Tarpinės sutartys leidžia atnaujinti jūsų išmaniąsias sutartis neperkeliant duomenų. Tai apima tarpinės sutarties diegimą, kuri persiunčia iškvietimus į įgyvendinimo sutartį. Kai norite atnaujinti sutartį, tiesiog diegiate naują įgyvendinimo sutartį ir atnaujinate tarpinę sutartį, kad ji nurodytų į naują įgyvendinimą.
Meta-transakcijos
Meta-transakcijos leidžia vartotojams sąveikauti su jūsų išmaniąja sutartimi nemokant dujų mokesčių tiesiogiai. Vietoj to, retransliuotojas (relayer) sumoka dujų mokesčius jų vardu. Tai gali pagerinti vartotojo patirtį, ypač vartotojams, kurie yra nauji blokų grandinėje.
EIP-721 ir EIP-1155 (NFT)
„Solidity“ dažnai naudojama kuriant nepakeičiamus žetonus (NFT), naudojant standartus, tokius kaip EIP-721 ir EIP-1155. Šių standartų supratimas yra labai svarbus kuriant NFT pagrįstas programas.
„Solidity“ ir blokų grandinės ateitis
„Solidity“ vaidina lemiamą vaidmenį sparčiai besivystančiame blokų grandinės technologijos kraštovaizdyje. Kadangi blokų grandinės pritaikymas toliau auga, „Solidity“ kūrėjai bus labai paklausūs, kad kurtų inovatyvias ir saugias decentralizuotas programas. Kalba nuolat atnaujinama ir tobulinama, todėl norint sėkmingai dirbti šioje srityje, būtina sekti naujausius pokyčius.
Išvada
„Solidity“ yra galinga ir universali kalba, skirta kurti išmaniąsias sutartis „Ethereum“ blokų grandinėje. Šiame vadove pateikta išsami „Solidity“ apžvalga, nuo pagrindinių koncepcijų iki pažangių metodų. Įvaldę „Solidity“ ir laikydamiesi saugaus kūrimo geriausių praktikų, galite prisidėti prie jaudinančio decentralizuotų programų pasaulio ir padėti formuoti blokų grandinės technologijos ateitį. Nepamirškite visada teikti pirmenybę saugumui, kruopščiai testuoti savo kodą ir būti informuotiems apie naujausius pokyčius „Solidity“ ekosistemoje. Išmaniųjų sutarčių potencialas yra didžiulis, o su „Solidity“ galite paversti savo inovatyvias idėjas realybe.