Tutvu Solidityga, juhtiva programmeerimiskeelega Ethereumi plokiahelas nutilepingute loomiseks. See juhend katab kõik alates põhikontseptsioonidest kuni edasijõudnud tehnikateni.
Solidity: Põhjalik juhend nutilepingute programmeerimiseks
Solidity on kõrgetasemeline, lepingupõhine programmeerimiskeel, mida kasutatakse nutilepingute rakendamiseks erinevatel plokiahelaplatvormidel, eelkõige Ethereumis. See on tugevalt mõjutatud C++, Pythonist ja JavaScriptist ning on loodud Ethereumi virtuaalmasina (EVM) sihtimiseks. See juhend annab üksikasjaliku ülevaate Solidityst, mis sobib nii algajatele kui ka kogenud programmeerijatele, kes soovivad sukelduda plokiahela arenduse maailma.
Mis on nutilepingud?
Enne Solidity sisse sukeldumist on oluline mõista, mis on nutilepingud. Nutileping on enesetäituv leping, mille tingimused on otse koodi kirjutatud. See salvestatakse plokiahelasse ja täidetakse automaatselt, kui eelnevalt kindlaksmääratud tingimused on täidetud. Nutilepingud võimaldavad automatiseerimist, läbipaistvust ja turvalisust erinevates rakendustes, sealhulgas:
- Detsentraliseeritud rahastus (DeFi): Laenu-, laenamis- ja kauplemisplatvormid.
- Tarneahela haldamine: Kaupade jälgimine ja läbipaistvuse tagamine.
- Valimissüsteemid: Turvaline ja kontrollitav elektrooniline hääletamine.
- Kinnisvara: Kinnisvaratehingute automatiseerimine.
- Tervishoid: Patsiendiandmete turvaline haldamine.
Miks Solidity?
Solidity on Ethereumi ja teiste EVM-ühilduvate plokiahelate nutilepingute kirjutamiseks domineeriv keel mitmel põhjusel:
- EVM-ühilduvus: Solidity on spetsiaalselt loodud kompileerimiseks baitkoodiks, mis töötab Ethereumi virtuaalmasinas.
- Kogukonna tugi: Suur ja aktiivne kogukond pakub ulatuslikku dokumentatsiooni, teeke ja tööriistu.
- Turvaelemendid: Solidity sisaldab funktsioone tavaliste nutilepingute haavatavuste leevendamiseks.
- Kõrgetasemeline abstraheerimine: Pakub kõrgetasemelisi konstruktsioone, mis muudavad lepingu arendamise tõhusamaks ja hallatavamaks.
Arengukeskkonna seadistamine
Solidityga arendamise alustamiseks peate seadistama sobiva arenduskeskkonna. Siin on mõned populaarsed valikud:
Remix IDE
Remix on veebipõhine, brauseripõhine IDE, mis sobib suurepäraselt Solidityga õppimiseks ja katsetamiseks. See ei vaja kohalikku installimist ja pakub funktsioone nagu:
- Koodiredaktor süntaksi esiletõstmise ja automaatse täiendamisega.
- Kompilaator Solidity koodi baitkoodiks teisendamiseks.
- Lepe testivõrkudesse või mainneti juurutamiseks.
- Silur koodis samm-sammult liikumiseks ja vigade tuvastamiseks.
Remix IDE-le pääseb juurde aadressil https://remix.ethereum.org/
Truffle Suite
Truffle on terviklik arendusraamistik, mis lihtsustab nutilepingute loomise, testimise ja juurutamise protsessi. See pakub tööriistu nagu:
- Truffle: Käsureatööriist projektide loomiseks, kompileerimiseks, juurutamiseks ja testimiseks.
- Ganache: Isiklik plokiahel kohalikuks arenduseks.
- Drizzle: Esiotsa teekide kogumik, mis lihtsustab teie nutilepingute integreerimist kasutajaliideste kaudu.
Truffle'i installimiseks:
npm install -g truffle
Hardhat
Hardhat on veel üks populaarne Ethereumi arenduskeskkond, mis on tuntud oma paindlikkuse ja laiendatavuse poolest. See võimaldab teil kompileerida, juurutada, testida ja siluda oma Solidity koodi. Peamised funktsioonid on:
- Sisseehitatud kohalik Ethereum võrk testimiseks.
- Plugin-süsteem funktsionaalsuse laiendamiseks.
- Console.log silumine.
Hardhat'i installimiseks:
npm install --save-dev hardhat
Solidity põhitõed: Süntaks ja andmetüübid
Uurime Solidity põhilist süntaksit ja andmetüüpe.
Solidity lepingu struktuur
Solidity leping on sarnane objektorienteeritud programmeerimise klassiga. See koosneb olekumuutujatest, funktsioonidest ja sündmustest. Siin on lihtne näide:
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
Selgitus:
pragma solidity ^0.8.0;
: Määrab Solidity kompilaatori versiooni. Ootamatu käitumise vältimiseks on oluline kasutada ühilduvat versiooni.contract SimpleStorage { ... }
: Määratleb lepingu nimegaSimpleStorage
.uint256 storedData;
: Deklareerib olekumutri nimegastoredData
tüübigauint256
(märgita täisarv 256 bitiga).function set(uint256 x) public { ... }
: Määratleb funktsiooni nimegaset
, mis võtab sisendina märgita täisarvu ja värskendab muutujatstoredData
.public
võtmesõna tähendab, et funktsiooni võivad kutsuda kõik.function get() public view returns (uint256) { ... }
: Määratleb funktsiooni nimegaget
, mis tagastabstoredData
väärtuse.view
võtmesõna näitab, et funktsioon ei muuda lepingu olekut.
Andmetüübid
Solidity toetab mitmesuguseid andmetüüpe:
- Täisarvud:
uint
(märgita täisarv) jaint
(märgiga täisarv) erinevate suurustega (ntuint8
,uint256
). - Boolsid:
bool
(true
võifalse
). - Aadressid:
address
(tähistab Ethereumi aadressi). - Byted:
bytes
(fikseeritud suurusega byted massiivid) jastring
(muutuva suurusega string). - Massiivid: Fikseeritud suurusega (nt
uint[5]
) ja muutuvsuurusega (ntuint[]
). - Kaardid: Võtme-väärtuse paarid (nt
mapping(address => uint)
).
Näide:
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;
}
}
Olekumuutujad vs. lokaalsed muutujad
Olekumuutujad deklareeritakse funktsioonide väljaspool ja salvestatakse plokiahelasse. Need säilivad funktsioonikõnede ja lepingu täitmise ajal. Ülaltoodud näites on storedData
olekumutri.
Lokaalsed muutujad deklareeritakse funktsioonide sees ja eksisteerivad ainult selle funktsiooni ulatuses. Neid ei salvestata plokiahelasse ja need visatakse ära, kui funktsioon on lõpetatud.
Funktsioonid Soliditys
Funktsioonid on nutilepingute ehitusplokid. Nad määratlevad loogika ja toimingud, mida leping saab sooritada. Funktsioonid võivad:
- Muuta lepingu olekut.
- Lugeda andmeid lepingu olekust.
- Suhelda teiste lepingutega.
- Saata või vastu võtta Ethereumi.
Funktsiooni nähtavus
Solidity funktsioonidel on neli nähtavuse modifikaatorit:
- public: Saab kutsuda nii seest- kui väljastpoolt.
- private: Saab kutsuda ainult lepingu seestpoolt.
- internal: Saab kutsuda nii lepingu seestpoolt kui ka tuletatud lepingutest.
- external: Saab kutsuda ainult väljastpoolt.
Funktsioonimodifikaatorid
Funktsioonimodifikaatoreid kasutatakse funktsiooni käitumise muutmiseks. Neid kasutatakse sageli turvapiirangute jõustamiseks või funktsiooni loogika täitmiseelse kontrollide sooritamiseks.
Näide:
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;
}
}
Selles näites kontrollib onlyOwner
modifikaator, kas kutsuja on lepingu omanik. Kui ei, siis taastatakse tehing. _
kohthoidja tähistab ülejäänud funktsiooni koodi.
Funktsiooni oleku muutuvus
Solidity funktsioonid võivad samuti omada oleku muutuvuse modifikaatoreid:
- view: Näitab, et funktsioon ei muuda lepingu olekut. See võib lugeda olekumutreid, kuid ei saa neisse kirjutada.
- pure: Näitab, et funktsioon ei loe ega muuda lepingu olekut. See on täielikult iseseisev ja deterministlik.
- payable: Näitab, et funktsioon võib vastu võtta Ethereumi.
Näide:
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;
}
}
Kontrollstruktuurid
Solidity toetab standardseid kontrollstruktuuriga nagu if
, else
, for
, while
ja do-while
tsüklid.
Näide:
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;
}
}
Sündmused ja logimine
Sündmused võimaldavad nutilepingutel suhelda välismaailmaga. Kui sündmus on välja antud, salvestatakse see plokiahela tehingulogidesse. Neid logisid saavad jälgida välised rakendused, et jälgida lepingu tegevust.
Näide:
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);
}
}
Selles näites antakse setValue
funktsiooni väljakutsumisel välja ValueChanged
sündmus. caller
parameetri indexed
võtmesõna võimaldab välistel rakendustel filtreerida sündmusi kutsuja aadressi alusel.
Päritus
Solidity toetab päritust, võimaldades teil luua uusi lepinguid olemasolevate põhjal. See soodustab koodi taasühiskasutamist ja modulaarsust.
Näide:
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++;
}
}
Selles näites pärib DerivedContract
BaseContract
-ilt. See pärib value
olekumutri ja setValue
funktsiooni. See määratleb ka oma funktsiooni incrementValue
.
Teegid
Teegid sarnanevad lepingutega, kuid need ei saa andmeid salvestada. Neid kasutatakse korduvkasutatava koodi juurutamiseks, mida mitmed lepingud võivad kutsuda. Teegid juurutatakse ainult üks kord, mis vähendab gaasikulusid.
Näide:
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);
}
}
Selles näites määratleb Math
teek add
funktsiooni. using Math for uint256;
lause võimaldab teil kutsuda add
funktsiooni uint256
muutujatele punktinotatsiooni abil.
Levinumad nutilepingute haavatavused
Nutilepingud on vastuvõtlikud erinevatele haavatavustele, mis võivad põhjustada raha kaotamist või ootamatut käitumist. On oluline olla teadlik nende haavatavuste suhtes ja võtta meetmeid nende leevendamiseks.
Taaskasutamine (Reentrancy)
Taaskasutamine tekib siis, kui leping kutsub välislepingut ja väline leping kutsub tagasi algsesse lepingusse enne, kui algse lepingu täitmine on lõppenud. See võib põhjustada ootamatuid oleku muutusi.
Leevendus: Kasutage Checks-Effects-Interactions (kontroll-toimingud-interaktsioonid) mustrit ja kaaluge transfer
või send
funktsioonide kasutamist, et piirata väliskutse jaoks saadaolevat gaasi.
Ületäitumine ja alitäitumine
Ületäitumine tekib, kui aritmeetiline operatsioon ületab andmetüübi maksimaalse väärtuse. Alitäitumine tekib, kui aritmeetiline operatsioon annab tulemuseks väärtuse, mis on väiksem kui andmetüübi miinimumväärtus.
Leevendus: Kasutage SafeMath teeke (kuigi Solidity 0.8.0 ja hilisemates versioonides on ületäitumise ja alitäitumise kontrollid vaikimisi sisse ehitatud), et neid probleeme vältida.
Ajatemplist sõltuvus
Ploki ajatemplile (block.timestamp
) tuginemine võib muuta teie lepingu kaevurite manipulatsioonile vastuvõtlikuks, kuna neil on ajatempli üle teatav kontroll.
Leevendus: Vältige block.timestamp
kasutamist kriitilise loogika jaoks. Kaaluge ajatempli või muude usaldusväärsemate allikate kasutamist.
Teenuse keelamine (DoS)
DoS-ründed on suunatud lepingu kasutuskõlbmatuks muutmisele seaduslike kasutajate jaoks. Seda saab saavutada kogu saadaoleva gaasi tarbimise või haavatavuste ärakasutamise kaudu, mis põhjustavad lepingu tagasivõtmist.
Leevendus: Rakendage gaasipiiranguid, vältige piiramatu arvuga tsükleid ja valideerige hoolikalt kasutaja sisendeid.
Eesjärjekorras käimine (Front Running)
Eesjärjekorras käimine toimub siis, kui keegi märkab ootel olevat tehingut ja esitab oma tehingu kõrgema gaasihinnaga, et see täidetaks enne originaaltehingut.
Leevendus: Kasutage tehingu üksikasjade varjamiseks kuni nende täitmiseni kombineerimis-avastus skeeme või muid tehnikaid.
Parimad praktikad turvaliste nutilepingute kirjutamiseks
- Hoidke see lihtsana: Kirjutage lühike ja kergesti mõistetav kood.
- Järgige Checks-Effects-Interactions mustrit: Veenduge, et kontrollid viiakse läbi enne mis tahes oleku muutuste tegemist ja interaktsioonid teiste lepingutega viiakse lõpule.
- Kasutage turvatööriistu: Potentsiaalsete haavatavuste tuvastamiseks kasutage staatilise analüüsi tööriistu nagu Slither ja Mythril.
- Kirjutage ühiktestid: Testige oma nutilepinguid põhjalikult, et tagada nende ootuspärane käitumine.
- Saage auditeeritud: Enne oma nutilepingute peavõrku juurutamist laske need auditeerida mainekatel turvaettevõtetel.
- Püsige kursis: Hoidke end kursis Solidity kogukonna uusimate turvahäkkimiste ja parimate praktikatega.
Edasijõudnud Solidity kontseptsioonid
Kui teil on põhitõdedest kindel arusaam, saate uurida edasijõudnumaid kontseptsioone:
Koostamine (Assembly)
Solidity võimaldab teil kirjutada sisseehitatud koostekoodi, mis annab teile rohkem kontrolli EVM-i üle. Siiski suurendab see ka vigade ja haavatavuste sisseviimise riski.
Proksiid
Proksiid võimaldavad teil oma nutilepinguid uuendada ilma andmeid migreerimata. See hõlmab proksilepingu juurutamist, mis suunab kõned implementatsioonilepingusse. Kui soovite lepingut uuendada, juurdate lihtsalt uue implementatsioonilepingu ja värskendate proksit, et see uuele implementatsioonile osutaks.
Metatehingud
Metatehingud võimaldavad kasutajatel oma nutilepingutega suhelda ilma otse gaasitasusid maksmata. Selle asemel maksab vahendaja nende eest gaasitasud. See võib parandada kasutajakogemust, eriti uutele plokiahelaga kasutajatele.
EIP-721 ja EIP-1155 (NFT-d)
Solidityt kasutatakse tavaliselt mitteasendatavate žetoonide (NFT-d) loomiseks, kasutades standardeid nagu EIP-721 ja EIP-1155. Nende standardite mõistmine on NFT-põhiste rakenduste loomisel ülioluline.
Solidity ja plokiahela tulevik
Solidity mängib kriitilist rolli kiiresti arenevas plokiahela tehnoloogia maastikus. Kuna plokiahela kasutuselevõtt jätkuvalt kasvab, on Solidity arendajatele suur nõudlus uuenduslike ja turvaliste detsentraliseeritud rakenduste loomiseks. Keelt täiendatakse ja täiustatakse pidevalt, seega on selle valdkonna edu saavutamiseks oluline olla kursis viimaste arengutega.
Kokkuvõte
Solidity on võimas ja mitmekülgne keel nutilepingute loomiseks Ethereumi plokiahelas. See juhend on andnud põhjaliku ülevaate Solidityst, alates põhikontseptsioonidest kuni edasijõudnud tehnikateni. Solidity meisterdamise ja turvalise arenduse parimate tavade järgimisega saate panustada detsentraliseeritud rakenduste põnevasse maailma ja aidata kujundada plokiahela tehnoloogia tulevikku. Pidage meeles alati turvalisust prioriteediks seada, oma koodi põhjalikult testida ja olla kursis Solidity ökosüsteemi viimaste arengutega. Nutilepingute potentsiaal on tohutu ja Solidityga saate oma uuenduslikud ideed ellu viia.