===== Sažetak =====
Blockchain tehnologija omogućuje transparentnu i neporecivu komunikaciju koja ima mnoge primjene, od kojih su jedna od njih pametni ugovori. Ethereum platforma pruža fleksibilnost i jednostavnost pri pisanju pametnih ugovora, ali je zbog toga programerima teže na vrijeme uočiti potencijalne sigurnosne propuste. Zbog toga je potrebno upoznati se s čestim potencijalnim programskim greškama i alatima koji mogu pomoći kod sigurnosne analize pri pisanju pametnih ugovora.
**Ključne riječi:** Ethereum; blockchain; pametni ugovori
===== Uvod =====
Blockchain tehnologija znatno se razvila u zadnjih desetak godina. Prve primjene blockchaina su uglavnom bile decentralizirane value kao što su Bitcoin, Litecoin i mnoge druge. Naknadno su počele nastajati i druge blockchain platforme koje su počele primjenjivati tu tehnologiju za naprednije koncepte, kao što su pametni ugovori. Jedna od tih platformi je Ethereum, koja je danas uvjerljivo vodeća platforma za pametne ugovore. Iako blockchain pruža određenu razinu anonimnosti, i dalje je moguće pratiti lanac izvršavanja transakcija i pametnih ugovora. To omogućuje analizu transakcija i moguće otkrivanje pokušaja prijevara. Kod pametnih ugovora je još moguće i provjeriti sam kod ugovora kako bi se osigurali da sve radi na način kako tvrdi stranka koja je napisala ugovor. Međutim, kod pisanja pametnih ugovora lako je napraviti greške koje nisu uočljive na prvi pogled a mogu dovesti do zlouporabe pametnog ugovora i gubitka sredstava.
===== Ethereum platforma =====
Svrha Ethereum platforme jest izgraditi protokol za decentralizirane aplikacije koje mogu međusobno komunicirati na siguran način u smislu da ne postoji centrali autoritet koji garantira točnost informacija, nego se ona utvrđuje kroz konsenzus u blockchainu. Ethereum ovo postiže pomoću apstraktnog temeljnog sloja: blockchain s ugrađenim Turing-potpunim programskim jezikom koji omogućuje korisnicima da pišu pametne ugovore u kojima oni sami mogu definirati pravila vlasništva, transakcija i prijelaza stanja. Ovo svojstvo omogućuje pametne ugovore koji imaju različite primjene. Na primjer, moguće je napisati pametni ugovor koji isplaćuje zaključana sredstva na određeni račun kada se ispune neki uvjeti, kao što je istek vremena ili potpis sa strane nekog drugog računa. Također je moguće koristiti pametne ugovore kako bi se implementirale decentralizirane glasačke platforme, autonomne organizacije ili čak druge kriptovalute.
Dizajn Ethereum platforme slijedi sljedeća osnovna načela:
**Jednostavnost: **Ethereum protokol treba biti što je moguće jednostavniji, čak ako to znači manju vremensku i memorijsku efikasnost. Prosječan programer treba moći sam slijediti i implementirati cijelu specifikaciju. Ovim načelom se ispunjava vizija da je Ethereum platforma otvorena za sve korisnike.
**Univerzalnost: **osnovni dio dizajna Ethereum platforme jest to da ona nema specifične mogućnosti, već pruža Turing-potpun programski jezik pomoću kojeg programeri mogu izgraditi bilo koji pametni ugovor koji trebaju.
**Modularnost: **dijelovi Ethereum platforme moraju biti dizajnirani na tako da su što je moguće modularniji i međusobno neovisni.
**Agilnost: **detalji Ethereum protokola nisu zaključani i mogu se mijenjati kako bi se dodatno poboljšala skalabilnost i sigurnost cijelog protokola.
**Bez diskriminacije i bez cenzure: **protokol ne smije aktivno ograničavati i blokirati određene kategorije primjene. Programeru treba biti dozvoljeno da čak pokrene beskonačnu petlju unutar pametnog ugovora, dokle got je spreman plaćati za njegovo kontinuirano izvršavanje.
===== Računi i pametni ugovori =====
Svaki Ethereum račun se sastoji od 20-bitne adrese koja jednoznačno identificira račun. Svaki račun također sadrži sljedeće vrijednosti:
* Takozvani **nonce**, broj koji se povećava pri svakoj transakciji i služi kako bi se svaka transakcija mogla izvršiti točno jednom
* Trenutnu količinu **ether**-a koji se nalazi na računu
* **Programski kod pametnog ugovora, **ako on postoji za taj račun
* **Spremište vrijednosti,** koje je inicijalno prazno
Ether je naziv za kriptovalutu Ethereum platforme koja se koristi kao "gorivo" za plaćanje transakcija i izvršavanje pametnih ugovora. Načelno, postoje dva tipa računa na Ethereum platformi: **vanjski posjedovani računi,** koji su kontrolirani privatnim ključem, i **računi pametnih ugovora,** koji su kontrolirani programskim kodom pametnog ugovora. Vanjski posjedovani računi nikada nemaju kod pametnog ugovora, te vlasnici mogu nad njima izvršavati transakcija bilo kada potpisom navedene transakcije te njenim slanjem na platformu. S druge strane, računi pametnih ugovora mogu dobiti ulazne vrijednosti kroz druge transakcije te time izvršiti programski kod ugovora.
Programski kod pametnih ugovora pisan je jezikom niske razine koji je baziran na stogovnom virtualnom stroju pod nazivom "//Ethereum Virtual Machine//", skraćeno //EVM//. Kako bi se olakšao posao programerima, napravljeni su programski jezici više razine koji se prevode u jezik niže razine koji koristi //EVM//. Jedan od tih jezika jest //Solidity//. On je statički tipizirani programski jezik koji je jedan on najraširenijih jezika više razine koji se koriste na Ethereum platformi.
Primjer pametnog ugovora napisanog koristeći //Solidity://
pragma solidity>=0.5.0 <0.7.0;
contract Coin {
address public minter;
mapping (address => uint) public balances;
event Sent(address from, address to, uint amount);
constructor() public {
minter = msg.sender;
}
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount <1e60);
balances[receiver] += amount;
}
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
Navedeni primjer pametnog ugovora implementira jednostavnu kriptovalutu s centralnim izdavateljem. Korisnici mogu slati valutu samo ako posjeduju barem vrijednost koju žele poslati.
===== Česti propusti kod pisanja pametnih ugovora =====
Napadi na pametne ugovori često ciljaju određene propuste koje su programeri nenamjerno napravili pri pisanju pametnih ugovora. Pošto su sadržaji svih računa i transakcija na Ethereum platformi dostupni svima, bilo tko može analizirati programski kod ugovora koji je preveden u jezik niže razine. Neki od češćih propusta kod pisanja pametnih ugovora su sljedeći:
==== Višestruko izvlačenje sredstava ====
Pri definiciji funkcije koja izvlači sredstva iz pametnog ugovora, potrebno je provjeriti da li korisnik smije izvući tu količinu sredstava. Nakon što je količina sredstava izvučena, treba ju ukloniti iz stanja pametnog ugovora za tog korisnika. Međutim, tu je lako pogriješiti tako da se sredstva oduzmu tek nakon što se pošalju korisniku. U tom slučaju, ako korisnik pokuša izvući sredstva više puta za redom u kratkim vremenskim razmacima, moguće je da će uspjeti izvući veću količini nego što smije. Sljedeći primjer programskog koda sadrži ovaj problem:
mapping (address => uint) private userBalances;
function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
msg.sender.transfer(amountToWithdraw);
userBalances[msg.sender] = 0;
}
U ovom primjeru, ''userBalances[msg.sender]'' se postavlja na nulu tek nakon što su se sredstva poslala korisniku. Ovaj problem se lako može riješiti na tako da se sredstva oduzmu prije slanja korisniku. Tada će višestruki pozivi pametnog ugovora poslati sredstva korisniku samo jednom.
==== Preljev cijelih brojeva ====
Pri oduzimanju ili dodavanju brojeva u pametnom ugovoru, mogu se premašiti definirane granice brojevnih varijabli. To može uzrokovati neželjeno ponašanje. Na primjer, ako pri korištenju tipa ''uint256'' oduzme vrijednost veća od one koja je pohranjena u varijabli dogodit će se preljev te će vrijednost skočiti na veliki broj. Tada će korisnik koji više ne bi trebao imati nikakva sredstva odjednom imati jako veliku količinu sredstava. Primjer programskog koda s ovim problemom:
uint8 myNumber = 255;
function increment(uint _number) public returns (uint) {
_number += _number;
return _number;
}
uint newNumber = increment(myNumber);
Kada se izvrši navedeni kod, vrijednost ''newNumber'' varijable će biti 0, a ne 256. Ovaj problem se najjednostavnije može riješiti koristeći biblioteku //SafeMath//.
==== Napad uskraćivanja usluge ====
Pri pisanju pametnih ugovora treba imati na umu da adrese koje pristupaju ugovoru ne moraju nužno biti adrese vanjski posjedovanih računa - pametni ugovori mogu pozivati druge pametne ugovore. To ima posljedicu da pametni ugovori mogu uskratiti uslugu drugim ugovorima. Glavni razlog tome je taj što napadačev pametni ugovor može odbiti primanje sredstava usred izvršavanja glavnog ugovora, te se time može dogoditi beskonačna petlja koja će paralizirati pametni ugovor. Najbolji način za obranu od ovakvog tipa napada jest odvajanje poslovne logike pametnog ugovora od logike plaćanja.
==== Pozivanje vanjskih ugovora koristeći delegatecall() ====
Pametni ugovori mogu pozivati druge pametne ugovore preko poziva funkcije ''delegatecall()''.Tada će se programski kod ciljnog ugovora izvršavati u kontekstu trenutnog ugovora, tako da će ''msg.sender'' i ''msg.value'' imati iste vrijednosti kao i u pozivajućem ugovoru. Ovo znači da ugovor može dinamički učitati programski kod s druge adrese prilikom izvršavanja. Na ovaj način se mogu implementirati kompleksniji ugovori te se može ponovno iskoristiti programski kod. Međutim, tada će sve javno dostupne funkcije ugovora koji je pozvan uz pomoć ''delegatecall()'' biti dostupne svim izvršiteljima pametnog ugovora, što nije samo po sebi problem. Sigurnosni propust se može dogoditi ako ugovor koji se poziva nema dobro implementirane sigurnosne provjere jer on sada može manipulirati ugovorom koji ga je pozvao. U tom slučaju napadač može iskoristiti sigurnosne propuste u pozivajućem ugovoru i time nanijeti štetu originalnom pametnom ugovoru.
===== Sigurnosna analiza pametnih ugovora =====
Metode analize pametnih ugovora na Ethereum platformi možemo svrstati u tri kategorije: statička analiza, dinamička analiza i formalna verifikacija. Za bilo koju od navedenih metoda nam je potreban programski kod pametnog ugovora. Njega možemo pronaći koristeći //Etherscan //unosom adrese željenog pametnog ugovora. Na //Etherscan//-u također možemo pronaći potpunu povijest transakcija koje su izvršene na nekoj adresi.
**Statičkom analizom** provjeravamo sigurnost koda prije samog izvršavanja. Ova vrsta analize provjerava programski kod i pokušava naći potencijalne sigurnosne propuste provjerom svih ponašanja u programskom kodu i slabosti koje bi mogle nastati pri izvršavanju koda. Za statičku analizu postoje alati kao što su //OYENTE//, //ZEUS//, //GASPER//, //Vandal//, //Ethir, Securify i MAIAN.// Svaki od navedenih alata detektira različite sigurnosne propuste, tako da je preporučeno koristiti više njih kako bi se osigurala veća razina sigurnosti pametnog ugovora.
**Dinamička analiza** provjerava ispravnost pametnog ugovora dok se on izvršava. Time se oponaša način na koji bi napadač tražio sigurnosne propuste u pametnom ugovoru. Sigurnosni propusti koji bi se identificirali kao lažno negativni u statičkoj analizi se mogu uspješno identificirati uz pomoć dinamičke analize. Dinamička analiza se također može koristiti kao metoda validacije rezultata statičke analize.
**Formalna verifikacija** koristi dokazivače teorema ili formalne metode iz matematike kako bi se dokazala određena svojstva pametnog ugovora, kao što su funkcijska ispravnost, sigurnost pri izvođenju koda, pouzdanost, itd. Alati za formalnu verifikaciju pametnih ugovora koriste postojeće dokazivače teorema, kao što su //Coq//, //Isabelle/HOL//, //Lem// i //SMT// dokazivači. Primjeri ovakvih alata su //F* Framework// i //FEther// interpreter.
===== Zaključak =====
Zbog neporecivosti blockchain tehnologije nije moguće promijeniti programski kod postojećih pametnih ugovora, pa je zbog toga potrebni pri pisanju samih ugovora jako paziti na ispravnost i sigurnost. To se može postići upoznavanjem s čestim programskim propustima, korištenjem standardnih biblioteka, uz pomoć alata za statičku i dinamičku analizu, te formalnom verifikacijom programskog koda pametnog ugovora.
===== Izvori =====
[1] [[https://github.com/ethereum/wiki/wiki/White-Paper|Ethereum White Paper]]
[2] [[https://en.wikipedia.org/wiki/Solidity|Solidity, Wikipedia]]
[3] [[https://medium.com/coinmonks/common-attacks-in-solidity-and-how-to-defend-against-them-9bc3994c7c18|Common attacks in Solidity and how to defend against them, Joel Foster, 2017.]]
[4] [[https://ethereumdev.io/safemath-protect-overflows/|SafeMath biblioteka]]
[5] [[https://arxiv.org/pdf/1908.08605.pdf|Security Analysis Methods on Ethereum Smart Contract Vulnerabilities — A Survey, Purathani Praitheeshan, Lei Pan, Jiangshan Yu, Joseph Liu, Robin Doss, 2019.]]