Solidity naudojama sudėtingų išmaniųjų sutarčių, skirtų veikti Ethereum blokų gran­di­nė­je, kūrimui. Ši kalba pasižymi uni­ka­lio­mis stra­te­gi­jo­mis, kurios ją išskiria iš kitų prog­ra­ma­vi­mo kalbų.

Kas yra Solidity?

Solidity yra aukšto lygio prog­ra­ma­vi­mo kalba, skirta kurti protingus kont­rak­tus Ethereum blokų gran­di­nė­je. Protingi kont­rak­tai yra savaime vykdomi kont­rak­tai, kurie au­to­ma­ti­zuo­ja turto mainus tarp šalių. Jų ypatumas yra tai, kad nereikia jokių tar­pi­nin­kų, siekiant už­tik­rin­ti protingo kontrakto laikymąsi.

Solidity šaltinio kodas yra kom­pi­liuo­ja­mas į baitkodą ir diegiamas Ethereum blokų gran­di­nė­je kaip išmanusis kont­rak­tas. Tai atlikus, išmanusis kont­rak­tas gali būti vykdomas bet kuriame tinklo mazge, o jo būsena saugoma blokų gran­di­nė­je. Pa­tei­kia­me paprasto kontrakto, mo­de­liuo­jan­čio NFT pardavimo automatą, pavyzdį:

pragma Solidity 0.8.7;
contract NFTVendingMachine {
    // Declare state variables
    address public owner;
    mapping (address => uint) public nftBalance;
    // Run on deployment
    constructor() {
        owner = msg.sender;
        nftBalance[address(this)] = 100;
    }
    // Allow the owner to restock the NFT balance
    function restock(uint amount) public {
        require(msg.sender == owner, "Only the owner can restock.");
        nftBalance[address(this)] += amount;
    }
    // Allow anyone to purchase NFTs
    function purchase(uint amount) public payable {
        require(msg.value >= amount * 1 ether, "You must pay at least 1 ETH per NFT");
        require(nftBalance[address(this)] >= amount, "Not enough NFTs in stock to complete this purchase");
        nftBalance[address(this)] -= amount;
        nftBalance[msg.sender] += amount;
    }
}
solidity

Kokioms prog­ra­moms tinka „Solidity“?

Solidity yra spe­cia­liai sukurta pa­skirs­ty­toms prog­ra­moms arba DApps, vei­kian­čioms Ethereum Virtual Machine (EVM) plat­for­mo­je, kurti. Pažangios sutartys tinka skait­me­ni­nių išteklių valdymui, de­cent­ra­li­zuo­tų biržų kūrimui, balsavimo sistemų diegimui ir kt.

De­cent­ra­li­zuo­tos fi­nan­si­nės paslaugos (DeFi)

Solidity naudojama kuriant DeFi programas, pa­vyz­džiui, de­cent­ra­li­zuo­tas biržas, kredito ir skolinimo plat­for­mas, prog­no­za­vi­mo rinkas ir krip­to­va­liu­tas. DeFi tapo viena iš po­pu­lia­riau­sių blokų grandinės tech­no­lo­gi­jos naudojimo sričių. Šiame procese Solidity tapo ne­pa­kei­čia­mu įrankiu kuriant DeFi programas Ethereum tinkle.

Ne­pa­kei­čia­mi žetonai

Ne­at­sie­ja­mas žetonas (NFT) nuo 2020-ųjų metų sulaukė didelio po­pu­lia­ru­mo. NFT yra unikalūs skait­me­ni­niai turtai, saugomi blokų gran­di­nė­je. Tai gali būti skait­me­ni­niai meno kūriniai, sporto suvenyrai ar žaidimų pramonės ar­te­fak­tai. Solidity naudojama kuriant protingus kont­rak­tus, kurie valdo NFT.

Pri­sta­ty­mo grandinės valdymas

Solidity gali būti naudojama kuriant iš­ma­niuo­sius kont­rak­tus tiekimo grandinių ste­bė­ji­mui ir valdymui. Kont­rak­tai naudojami įvairių tiekimo grandinės procesų au­to­ma­ti­za­vi­mui. Tai apima prekių judėjimo stebėjimą, produktų au­ten­tiš­ku­mo tikrinimą ir mokėjimų tarp šalių ap­do­ro­ji­mą.

Su­tik­ri­ni­mo sistemos

Solidity gali būti naudojama kuriant protingus kont­rak­tus, kurie įgy­ven­di­na saugias ir skaidrias balsavimo sistemas blokų gran­di­nė­je. Kont­rak­tai gali būti naudojami siekiant už­tik­rin­ti, kad balsai būtų skai­čiuo­ja­mi teisingai ir kad balsavimo procesas būtų są­ži­nin­gas ir skaidrus.

Kokie yra „Solidity“ pri­va­lu­mai ir trūkumai?

Nors „Solidity“ yra galinga kalba, skirta kurti iš­ma­niuo­sius kont­rak­tus „Ethereum“ blokų gran­di­nė­je, ji turi spe­ci­fi­nių privalumų ir trūkumų, kuriuos kūrėjai turėtų at­si­žvelg­ti kurdami iš­ma­niuo­sius kont­rak­tus. Nepaisant to, saugių išmaniųjų kontraktų kūrimas rei­ka­lau­ja tam tikro lygio kom­pe­ten­ci­jos ir atsargumo.

Pa­vyz­džiui, žemiau pa­tei­kia­mas protingas kont­rak­tas, kuris veikia kaip juodoji skylė. Bet koks į kontraktą siun­čia­mas eteris yra ne­grįž­ta­mai su­nau­do­ja­mas, be galimybės atgauti eterį ar atlikti iš­mo­kė­ji­mą:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.9.0;
// This contract swallows all Ether sent to it
contract Blackhole {
    event Received(address, uint);
    receive() external payable {
            emit Received(msg.sender, msg.value);
    }
}
solidity

Solidity pri­va­lu­mai

  • Lanks­tu­mas: Solidity yra uni­ver­sa­li kalba. Ji gali būti naudojama įvairių protingų sutarčių, skirtų įvairiems naudojimo atvejams, kūrimui.
  • Saugumas: „Solidity“ buvo sukurta at­si­žvel­giant į saugumą, įtrau­kiant tokias savybes kaip prieigos kontrolė, išimčių tvarkymas ir gedimų me­cha­niz­mai, siekiant padėti kūrėjams kurti saugias sutartis.
  • Su­de­ri­na­mu­mas su Ethereum: šiuo metu Solidity yra pa­gei­dau­ja­ma kalba protingų sutarčių kūrimui Ethereum blokų gran­di­nė­je.
  • Iš­skir­ti­nė bend­ruo­me­nė: didelė blokų grandinės kūrėjų bend­ruo­me­nė dirba su Solidity, todėl yra gausu išteklių mokymuisi ir problemų spren­di­mui.

Solidity trūkumai

  • Mokymosi kreivė: Kūrėjams, kurie dar nėra su­si­pa­ži­nę su blokų grandine ir protingų sutarčių kūrimu, „Solidity“ yra gana sudėtinga išmokti.
  • Ne­kin­ta­mu­mas: Kai protingas kont­rak­tas yra įdiegtas blokų gran­di­nė­je, jo negalima toliau keisti. Todėl kūrėjai turi būti ypač atsargūs rašydami ir te­stuo­da­mi.
  • Formalios patikros trūkumas: „Solidity“ neturi įdiegtų įrankių formaliam kodo per­žiū­rė­ji­mui. Dėl to kūrėjai turi naudoti išorinius įrankius, kad už­tik­rin­tų savo sutarčių tikslumą.
  • Ribotos priemonės: „Solidity“ priemonių eko­sis­te­ma dar tik for­muo­ja­si, todėl gali kilti problemų su in­te­gruo­to­mis prog­ra­ma­vi­mo ap­lin­ko­mis (IDE), testavimo sis­te­mo­mis ir kitomis prog­ra­ma­vi­mo prie­mo­nė­mis.

Kokia yra pag­rin­di­nė Solidity sintaksė?

Solidity yra ob­jek­ti­nis prog­ra­ma­vi­mo kalba, sukurta pro­tin­giems kont­rak­tams. Ji yra įkvėpta Ja­vaSc­ript, Python ir C++ kalbų. Kalbos sintaksė yra panaši į Ja­vaSc­ript, nors turi keletą įdomių ypatumų.

Kin­ta­mie­ji Solidity kalboje

Iš pirmo žvilgsnio „Solidity“ kintamųjų tvarkymas gali atrodyti panašus į kitų prog­ra­ma­vi­mo kalbų. Tačiau esminis skirtumas kyla iš to, kad „Ethereum Virtual Machine“ (EVM) veikia kaip vykdymo aplinka. Visos ope­ra­ci­jos EVM, įskaitant duomenų saugojimą, rei­ka­lau­ja tam tikrų „dujų“ sąnaudų. Todėl prog­ra­ma­vi­mo metu reikia įvertinti ope­ra­ci­jos efek­ty­vu­mą ir nuspręsti, kaip ją galima įgy­ven­din­ti kuo efek­ty­viau.

Be įprastų kintamųjų, Solidity turi kons­tan­tas, kurios turi būti api­brėž­tos kom­pi­lia­vi­mo metu. Kons­tan­tos rei­ka­lau­ja mažiau dujų sau­go­ji­mui:

// Regular variable can be declared without defining
int a;
// Constant needs to be defined at declaration
int constant b = 51;
solidity

Tas pats taikoma immutable kin­ta­mie­siems, nes jie rei­ka­lau­ja mažiau dujų ir negali būti keičiami po pri­sky­ri­mo. Skir­tin­gai nei constant kin­ta­mie­ji, ne­kin­ta­mų­jų kintamųjų pri­sky­ri­mas gali būti at­lie­ka­mas vykdymo metu.

Kontrolės teiginiai Solidity kalboje

Kaip im­pe­ra­ty­vi­nė prog­ra­ma­vi­mo kalba, Solidity palaiko įprastas valdymo inst­ruk­ci­jas, pa­vyz­džiui, šakeles ir ciklus. Pa­tei­kia­me kodą, skirtą pa­si­rink­ti didesnį iš dviejų skaičių, a ir b:

int largerNumber = 0;
// If-else statement
if (a > b) {
    largerNumber = a;
} else {
        largerNumber = b;
}
solidity

for kilpa Solidity atitinka sintaksę, žinomą iš Ja­vaSc­ript arba C++:

// Loop 10 times
for (int i = 0; i < 10; i++) {
    // …
}
solidity

while kilpa taip pat veikia kaip įprasta. Mes su­jun­gia­me nu­trau­ki­mo sąlygą su skait­me­ni­niu skai­tik­lio kin­ta­muo­ju:

bool continueLoop = true;
int counter = 0;
// Loop at most 10 times
while (continueLoop && counter < 10) {
    // …
    counter++;
}
solidity

Paprasti tipai Solidity kalboje

Solidity yra statinio tipavimo kalba, pa­lai­kan­ti tipus, paprastai nau­do­ja­mus prog­ra­ma­vi­mo kalbose. Paprasti tipai, at­spin­din­tys vieną reikšmę, apima boolinius tipus, skaičius ir eilutes.

Booleans Solidity at­vaiz­duo­ja vertes true ir false. Jos gali būti susietos naudojant žinomus Boolean ope­ra­to­rius ir nau­do­ja­mos if tei­gi­niuo­se:

bool paymentReceived = true;
bool itemsStocked = true;
bool continueTransaction = paymentReceived && itemsStocked;
if (continueTransaction) {
    // ...
}
solidity

Solidity palaiko platų skait­me­ni­nių tipų spektrą. Sveikieji skaičiai gali būti skirstomi į žen­kli­nius (int) ir be­žen­kli­nius (uint) skaičius, kur pa­sta­rie­ji gali būti tik teigiami. Be to, skaičiaus dia­pa­zo­nas gali būti nurodytas 8 bitų žings­niais, nuo int8 per int16 iki int265:

uint8 smallNumber = 120;
int8 negativeNumber = -125;
int8 result = smallNumber + negativeNumber;
assert(result == -5)
solidity

Stringai Solidity kalboje naudojami dau­giau­sia būsenos pra­ne­ši­mams generuoti. Kalba palaiko viengubas ir dvigubas kabutes, taip pat Unicode simbolius:

string message = 'Hello World';
string success = unicode"Transfer sent";
Solidity

Funkcijos Solidity

Funkcijos yra pag­rin­di­nis Solidityaspektas, kaip ir daugumoje prog­ra­ma­vi­mo kalbų. Funkcijos api­brė­ži­mas yra panašus į Ja­vaSc­ript, kur argumentų tipai turi būti aiškiai nurodyti. Be to, raktinis žodis „returns“ nau­do­ja­mas return vertės tipams nurodyti.

// Define a function
function addNumbers(int a, int b) returns (int) {
    return a + b;
}
solidity

Funkcijos iš­kvie­ti­mas at­lie­ka­mas kaip įprasta:

// Call the function
int result = addNumbers(2, 3);
solidity

Įdomu tai, kad ana­lo­giš­kai kaip ir pavadinti ar­gu­men­tai, Solidity grą­ži­na­mo­sios reikšmės taip pat gali būti pa­va­din­tos. Tokiu atveju pakanka priskirti ati­tin­ka­mas kin­ta­muo­sius funkcijos kūne, o aiškus grą­ži­ni­mas per return nėra būtinas:

function divideNumbers(int dividend, int divisor) returns (int quotient) {
    quotient = dividend / divisor;
    // No `return` necessary
}
solidity

Panašiai kaip constant ar immutable kin­ta­mie­ji, Solidity funkcijos gali būti pažymėtos kaip ne­kei­čian­čios būsenos. Šiam tikslui naudojami raktiniai žodžiai view ir pure. view funkcija nekeičia būsenos, o pure funkcija pa­pil­do­mai ga­ran­tuo­ja, kad nebūtų skaitomi būsenos kin­ta­mie­ji.

Išmanieji kont­rak­tai „Solidity“ kalba

Be stan­dar­ti­nių tipų, Solidity žino keletą spe­cia­li­zuo­tų išmaniųjų sutarčių tipų. Pag­rin­di­nis tipas yra address ir atitinka Ethereum adresus. Adresai, kurių tipas yra payable, gali priimti per­ve­di­mus Ether. Šiam tikslui payable adresai teikia balance() ir transfer() metodus.

// Get address of this contract
address mine = address(this);
// Get payable external address
address payable other = payable(0x123);
// Transfer if balances fulfill conditions
if (other.balance < 10 && mine.balance >= 100) {
    other.transfer(10);
}
solidity

Remiantis address tipu, contract tipas eg­zis­tuo­ja kaip centrinė kalbos konst­ruk­ci­ja. Sutartys atitinka objektų ori­en­tuo­tų prog­ra­ma­vi­mo kalbų klases. Taigi, sutartys apjungia būsenos duomenis ir funkcijas bei apsaugo juos nuo išorinio pasaulio. Sutartys palaiko daug­kar­ti­nį pa­vel­dė­ji­mą, kaip žinoma iš Python ar C++.

Sutartys paprastai prasideda pragma eilute, kurioje nurodyta leidžiama „Solidity“ versija, po kurios eina tikrasis api­brė­ži­mas:

// Make sure Solidity version matches
pragma Solidity >=0.7.1 <0.9.0;
// Contract definition
contract Purchase {
    // Public state variables
    address seller;
    address buyer;
    
    // View-function
    function getSeller() external view returns (address) {
        return seller;
    }
}
solidity

Išmanieji kont­rak­tai gali apibrėžti būsenos duomenis ir funkcijas. Kaip žinoma iš C++ ir Java, kiekvienu atveju galima apibrėžti vieną iš trijų prieigos lygių:

  • public: Prie kintamojo galima prieiti skaitant ir rašant iš sutarties. Be to, view funkcija au­to­ma­tiš­kai ge­ne­ruo­ja­ma kaip gavimo funkcija išorinei skaitymo prieigai.
  • internal: Kin­ta­ma­sis yra ap­sau­go­tas nuo išorinės prieigos. Skaityti ir rašyti galima iš sutarties vidaus, taip pat iš paveldėtų sutarčių.
  • private: kaip internal, bet nėra prieigos iš paveldėtų sutarčių

Funkcijos taip pat gali būti api­bū­di­na­mos kaip external. external funkcija veikia kaip sutarties sąsajos dalis ir yra naudojama išorinei prieigai. receive funkcija, skirta eteriui priimti, yra gerai žinomas pavyzdys:

// Define without `function` keyword
receive() external payable {
    // Handle Ether
}
solidity

Mo­di­fi­ka­to­riai Solidity kalboje

Solidity turi įdomią kalbos konst­ruk­ci­ją mo­di­fi­ka­to­rių forma, kurie primena Python deko­ra­to­rius. Panašiai kaip Python, Solidity mo­di­fi­ka­to­riai naudojami funkcijos iš­kvie­ti­mui pakeisti. Jie dažnai naudojami siekiant už­tik­rin­ti, kad prieš vykdant funkciją būtų įvykdyta tam tikra sąlyga:

contract Sale {
    uint price;
    address payable owner;
    modifier onlyOwner {
        // Will throw error if called by anyone other than the owner
        require(
            msg.sender == owner,
            "Only owner can call this function."
        );
        // The wrapped function's body is inserted here
        _;
    }
    
    // `onlyOwner` wraps `changePrice`
    function changePrice(uint newPrice) public onlyOwner {
        // We'll only get here if the owner called this function
        price = newPrice;
    }
}
solidity

Sandorių valdymas naudojant „Solidity“

Solidity turi in­te­gruo­tą sandorių valdymą. Tai gali būti naudojama siekiant už­tik­rin­ti, kad eterio per­ve­di­mas būtų visiškai įvykdytas arba visiškai ne­įvyk­dy­tas. Kalba supranta revert raktinį žodį, kuris sukelia sandorio „atšaukimą“. Naudodami error raktinį žodį galite apibrėžti savo klaidų kodus:

// Custom error definition
error InsufficientPayment(uint256 paid, uint256 required);
// Contract representing a sale
contract Sale {
    uint price;
    // Purchase if enough ether transferred
    function purchase() public payable {
        if (msg.value < price) {
            revert InsufficientPayment(msg.value, price);
        }
        // Complete purchase
    }
}
solidity

Kitas dažnai pa­si­tai­kan­tis modelis yra require() funkcijos nau­do­ji­mas. Ji gali būti naudojama ana­lo­giš­kai kaip revert:

// Using `require()` function
if (!condition) revert("Error message");
// Equivalent to
require(condition, "Error message");
solidity
Go to Main Menu