Sådan bruges Solidity-programmering
Solidity bruges til at udarbejde komplekse smarte kontrakter, der er designet til at fungere på Ethereum-blockchain. Dette sprog præsenterer unikke strategier, der adskiller det fra andre programmeringssprog.
Hvad er Solidity?
Solidity er et højniveau-programmeringssprog til oprettelse af smarte kontrakter på Ethereum-blockchain. Smarte kontrakter er selvudførende kontrakter, der automatiserer udvekslingen af aktiver mellem parter. Det særlige ved dem er, at der ikke er behov for mellemled for at sikre overholdelse af den smarte kontrakt.
Solidity-kildekoden kompileres til bytecode og implementeres på Ethereum-blockchain som en smart kontrakt. Når dette er gjort, kan den smarte kontrakt udføres af enhver node på netværket, og status gemmes på blockchain. Vi viser et eksempel på en simpel kontrakt, der modellerer en NFT-automat:
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;
}
}solidityHvilke applikationer er Solidity velegnet til?
Solidity er specielt designet til at skabe distribuerede applikationer eller DApps, der kører på Ethereum Virtual Machine (EVM). Smarte kontrakter er blandt andet velegnede til at administrere digitale aktiver, skabe decentraliserede børser og implementere afstemningssystemer.
Decentraliserede finanser (DeFi)
Solidity bruges til at udvikle DeFi-applikationer såsom decentraliserede børser, kredit- og låneplatforme, forudsigelsesmarkeder og kryptovalutaer. DeFi er blevet en af de mest populære anvendelser af blockchain-teknologi. I den proces er Solidity blevet et uundværligt værktøj til at opbygge DeFi-applikationer på Ethereum-netværket.
Ikke-fungible tokens
Non-fungible token (NFT) har været meget populært siden 2020’erne. NFT’er er unikke digitale aktiver, der er gemt på blockchain. Det kan være digitale kunstværker, sportsminder eller artefakter fra spilindustrien. Solidity bruges til at oprette de smarte kontrakter, der driver NFT’er.
Leveringskædeadministration
Solidity kan bruges til at oprette smarte kontrakter til overvågning og styring af forsyningskæder. Kontrakterne bruges til at automatisere forskellige forsyningskædeprocesser. Disse omfatter sporing af varers bevægelser, verifikation af produkters ægthed og behandling af betalinger mellem parter.
Afstemningssystemer
Solidity kan bruges til at oprette smarte kontrakter, der implementerer sikre og gennemsigtige afstemningssystemer på blockchainen. Kontrakterne kan bruges til at sikre, at stemmerne tælles korrekt, og at afstemningsprocessen er fair og gennemsigtig.
Hvad er fordele og ulemper ved Solidity?
Solidity er et kraftfuldt sprog til opbygning af smarte kontrakter på Ethereum-blockchain, men det har sine specifikke fordele og ulemper, som udviklere bør tage i betragtning, når de udvikler smarte kontrakter. Ikke desto mindre kræver udarbejdelsen af sikre smarte kontrakter et bestemt niveau af færdighed og forsigtighed.
Som illustration er der nedenfor et smart kontrakt, der fungerer som et sort hul. Enhver Ether, der sendes til kontrakten, forbruges permanent, uden mulighed for at hente Ether eller foretage en udbetaling:
// 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);
}
}solidityFordele ved Solidity
- Fleksibilitet: Solidity er et alsidigt sprog. Det kan bruges til at udvikle forskellige smarte kontrakter med en række forskellige anvendelsesmuligheder.
- Sikkerhed: Solidity er udviklet med fokus på sikkerhed og indeholder funktioner som adgangskontrol, håndtering af undtagelser og fejlmekanismer, der hjælper udviklere med at udarbejde sikre kontrakter.
- Ethereum-kompatibilitet: I øjeblikket er Solidity det foretrukne sprog til at producere smarte kontrakter på Ethereum-blockchain.
- Særskilt community: Et stort community af blockchain-udviklere arbejder med Solidity, hvilket resulterer i en overflod af ressourcer til læring og problemløsning.
Ulemper ved Solidity
- Læringskurve: For udviklere, der er nye inden for blockchain og udvikling af smarte kontrakter, har Solidity en relativt stejl læringskurve.
- Uforanderlighed: Når en smart kontrakt er implementeret på blockchain, kan den ikke ændres yderligere. Det betyder, at udviklere skal være yderst forsigtige, når de skriver og tester.
- Mangel på formel verifikation: Solidity mangler indbyggede værktøjer til formel kodegennemgang. Dette kræver, at udviklere bruger eksterne værktøjer for at garantere nøjagtigheden af deres kontrakter.
- Begrænset værktøj: Soliditys værktøjsøkosystem er stadig i sin vorden, hvilket kan medføre problemer med integrerede udviklingsmiljøer (IDE’er), testrammer og andre udviklingsværktøjer.
Hvad er den grundlæggende syntaks i Solidity?
Solidity er et objektorienteret programmeringssprog designet til smarte kontrakter. Det er inspireret af JavaScript, Python og C++. Sprogets syntaks ligner JavaScript, dog med nogle interessante særheder.
Variabler i Solidity
Ved første øjekast kan Soliditys håndtering af variabler virke lig andre programmeringssprog. Der er dog en vigtig forskel, som skyldes, at Ethereum Virtual Machine (EVM) fungerer som eksekveringsmiljø. Alle operationer på EVM, herunder datalagring, medfører en vis mængde “gas”-omkostninger. Derfor skal man under programmeringen afveje en operations effektivitet og afgøre, hvordan den kan implementeres så effektivt som muligt.
Ud over almindelige variabler har Solidity konstanter, som skal defineres under kompilering. Konstanter kræver mindre gas til opbevaring:
// Regular variable can be declared without defining
int a;
// Constant needs to be defined at declaration
int constant b = 51;solidityDet samme gælder for immutable variabler, idet de kræver mindre gas og ikke kan ændres efter tildeling. I modsætning til constant variabler kan tildelingen af uforanderlige variabler foretages under kørsel.
Kontrolsætninger i Solidity
Som et imperativt programmeringssprog understøtter Solidity velkendte kontrolsætninger, såsom forgreninger og sløjfer. Vi viser koden til at vælge det største af to tal, a og b:
int largerNumber = 0;
// If-else statement
if (a > b) {
largerNumber = a;
} else {
largerNumber = b;
}solidityfor kken i Solidity svarer til den syntaks, der kendes fra JavaScript eller C++:
// Loop 10 times
for (int i = 0; i < 10; i++) {
// …
}solidity23-løkken fungerer også som normalt. Vi kombinerer en afslutningsbetingelse med en numerisk tællervariabel:
bool continueLoop = true;
int counter = 0;
// Loop at most 10 times
while (continueLoop && counter < 10) {
// …
counter++;
}solidityEnkle typer i Solidity
Solidity er et statisk typet sprog og understøtter de typer, der normalt findes i programmeringssprog. Enkle typer, der repræsenterer enkeltværdier, omfatter booleske værdier, tal og strenge.
Booleanske værdier i Solidity kortlægger værdierne true og false. De kan sammenkædes ved hjælp af de kendte booleske operatorer og bruges i if sætninger:
bool paymentReceived = true;
bool itemsStocked = true;
bool continueTransaction = paymentReceived && itemsStocked;
if (continueTransaction) {
// ...
}soliditySolidity understøtter en bred vifte af numeriske typer. Heltal kan skelnes mellem tegnede (int) og utegnede (uint) tal, hvor sidstnævnte kun kan være positive. Desuden kan et tals rækkevidde specificeres i trin på 8 bit, fra int8 via int16 op til int265:
uint8 smallNumber = 120;
int8 negativeNumber = -125;
int8 result = smallNumber + negativeNumber;
assert(result == -5)solidityStrings bruges i Solidity hovedsageligt til at generere statusmeddelelser. Sproget understøtter både enkelt og dobbelt anførselstegn samt Unicode-tegn:
string message = 'Hello World';
string success = unicode"Transfer sent";SolidityFunktioner i Solidity
Funktioner er et grundlæggende aspekt af Solidity, som i de fleste programmeringssprog. Definitionen af en funktion ligner JavaScript, hvor argumenttyperne skal angives eksplicit. Derudover bruges et returneringsnøgleord til at angive de return værdityper.
// Define a function
function addNumbers(int a, int b) returns (int) {
return a + b;
}solidityFunktionen kaldes som normalt:
// Call the function
int result = addNumbers(2, 3);solidityInteressant nok kan returværdier i Solidity, analogt med navngivne argumenter, også navngives. I denne situation er det tilstrækkeligt at tildele de tilsvarende variabler i funktionskroppen, og en eksplicit returnering via return er unødvendig:
function divideNumbers(int dividend, int divisor) returns (int quotient) {
quotient = dividend / divisor;
// No `return` necessary
}solidityLigesom constant eller immutable variabler kan funktioner i Solidity markeres som ikke-tilstandsmæssigt ændrende. Nøgleordene view og pure bruges til dette formål. En view ændrer ikke tilstanden, mens en pure desuden garanterer, at tilstandsvariabler ikke læses.
Smarte kontrakter i Solidity
Ud over standardtyperne kender Solidity en håndfuld specialiserede typer til smarte kontrakter. Den grundlæggende type er address og kortlægger Ethereum-adresser. Adresser, der er payable, kan modtage overførsler i Ether. Til dette formål leverer payable balance() og transfer().
// 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);
}solidityBaseret på typen address findes typen contract som en central sprogkonstruktion. Kontrakter svarer groft sagt til klasser i objektorienterede programmeringssprog. Kontrakter samler således tilstandsdata og funktioner og beskytter dem mod omverdenen. Kontrakter understøtter multiple arv, som det kendes fra Python eller C++.
Kontrakter begynder normalt med en linje, pragma angiver den tilladte Solidity-version, efterfulgt af den egentlige definition:
// 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;
}
}soliditySmarte kontrakter kan definere tilstandsdata og funktioner. Som kendt fra C++ og Java kan der i hvert tilfælde defineres et af tre adgangsniveauer:
public: Variablen kan tilgås ved at læse og skrive fra kontrakten. Derudover genereres der automatisk enviewsom en getter til ekstern læseadgang.internal: Variablen er beskyttet mod ekstern adgang. Læse- og skriveadgang er mulig fra kontrakten såvel som fra arvekontrakter.private: Sominternal, men der er ingen adgang fra arvekontrakter.
Funktioner kan yderligere karakteriseres som external. En external fungerer som en del af kontraktgrænsefladen og bruges til ekstern adgang. receive til modtagelse af ether er et velkendt eksempel:
// Define without `function` keyword
receive() external payable {
// Handle Ether
}solidityModifikatorer i Solidity
Solidity har en interessant sprogkonstruktion i form af modifikatorer, der ligner Pythons dekoratorer. Ligesom i Python bruges modifikatorer i Solidity til at ændre påkaldelsen af en funktion. De bruges ofte til at sikre, at en bestemt betingelse er opfyldt, før en funktion udføres:
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;
}
}solidityTransaktionsstyring med Solidity
Solidity har en indbygget transaktionsstyring. Denne kan bruges til at sikre, at en ether-overførsel enten afvikles fuldstændigt eller slet ikke afvikles. Sproget forstår nøgleordet revert, som udløser en “roll-back” af en transaktion. Med nøgleordet error kan du definere dine egne fejlkoder:
// 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
}
}solidityEt andet hyppigt forekommende mønster er brugen af funktionen require(). Denne kan bruges analogt med revert:
// Using `require()` function
if (!condition) revert("Error message");
// Equivalent to
require(condition, "Error message");solidity