Vrhunski vodnik za zaščito pametnih pogodb EOS. Kriptoskupnost je postala skeptična, ko se je junija 2018 začela izvajati največja svetovna organizacija ICO EOS, EOS, ki je bila 2 dni zamrznjena zaradi programska napaka. Toda hitro naprej 4 mesece in EOS danes predstavlja več kot podvoji transakcije kar danes počne Ethereum. Z obljubo brezplačnih in hitrejših transakcij ima najvišji Dapp EOS-a približno 13.000 aktivnih uporabnikov na dan, v primerjavi s samo 2000 najvišjimi Dapp-i v Ethereumu.

Varnost pametne pogodbe EOS

Avtor Rohan Agarwal

Nekatere splošne ranljivosti pametnih pogodb veljajo za skoraj vse platforme. Tako kot Ethereum je treba tudi pametne pogodbe, napisane na EOS, pregledati, preden začnejo delovati v glavnem omrežju. Usodne napake v pogodbi se lahko izkoristijo, če pogodbe niso dovolj preizkušene. V tem priročniku vam bomo pomagali, da se izognete pogostim pastem na poti, da naredite naslednji morilec dApp v EOS.

Preden preberete priročnik, je pomembno vedeti nekaj predpogojnih informacij v zvezi z razvojem EOS-a, ki vam bodo prav prišle med branjem priročnika. Poznavanje jezika C ++ je nujno. Najboljši kraj za začetek razvoja pametne pogodbe je EOSIO dokumentacijo

Obravnavanje dispečerja ABI

zunanjost "C" {

Uporabi ničnost (sprejemnik uint64_t, koda uint64_t, dejanje uint64_t) {

class_name thiscontract (sprejemnik);

če ((koda == N (eosio.token)) && (dejanje == N (prenos))) {

execute_action (&to pogodbo, &ime_razreda :: prenos);

vrnitev;

}

če (koda! = sprejemnik) vrne;

stikalo (dejanje) {EOSIO_API (ime_razreda, (dejanje_1) (dejanje_n))};

eosio_exit (0);

}

}

Zgornja slika je vzorčna koda spremenjenega dispečerja ABI. Za enostavnejše ravnanje s pogodbo se uporablja enostavnejši dispečer ABI, kot je prikazano spodaj.

EOSIO_ABI (ime_razreda, (dejanje_1) (dejanje_n));

Dispečer / posrednik ABI pogodbi omogoča, da posluša dohodne dogodke prenosa eosio.token in običajne interakcije s pametno pogodbo. Pomembno je, da vsako ključno dejanje in kodo vežete tako, da ustreza zahtevam, da se izognete neobičajnim in nezakonitim klicem.

Primer bi bil kramp, ki se je zgodil dApp-u EOSBet Casino zaradi napake v njihovi izvorni kodi za posredovanje ABI.

če (koda == samo || koda == N (eosio.token)) {

TIP to pogodbo (samo);

preklop (dejanje) {

EOSIO_API (TIP, ČLANI)

}

}

Zgornje preverjanje obdelovalca dejanj uporabe izvorne kode za posredovanje ABI je napadalcu omogočilo, da v celoti zaobide funkcijo eosio.token :: transfer () in neposredno pokliče funkcijo contract :: transfer (), ne da bi EOS prenesel v pogodbo, preden je postavil stava. Za izgube mu ni nič plačal, ni pa nič izgubil. Za zmage pa mu je iz pogodbe izplačal pravi EOS.

Zgoraj so odpravili napako, tako da so pred pogodbo o dohodnem dejanju v pogodbo dodali ček dejanja prenosa pogodbe eosio.token.

če (koda == samo || koda == N (eosio.token)) {

če (dejanje == N (prenos)) {

eosio_assert (koda == N (eosio.token), "Morate prenesti EOS");

}

TIP to pogodbo (samo);

preklop (dejanje) {

EOSIO_API (TIP, ČLANI)

}

}

Pomembno je, da uporabite izjavo require_auth (račun); v dejanja, za katera želite, da se izvajajo samo pooblaščeni računi. require_auth (_self); se uporablja za pooblastilo samo lastnika pogodbe za podpis posla

Pooblastilo v akcijah

ničen žeton :: prenos (ime_računa iz, ime_računa v, količina sredstva)

{

samodejno sym = quantity.symbol.name ();

require_recipient (od);

require_recipient (do);

samodejni plačnik = has_auth (do)? za od;

sub_balance (od, količina);

add_balance (do, količina, plačnik);

}

Zgornja vzorčna koda omogoča vsakomur, da pokliče akcijo. Da bi jo rešili, uporabite require_auth (from); izjavo, da pooblasti plačnika, da sproži tožbo.

Poskusite se izogniti spreminjanju pogodbe eosio.token

Nedavnemu hekerju belega klobuka je to uspelo terjati 1 milijardo žetonov Dapp-a zaradi slabo preizkušene metode v njihovi pogodbi eosio.token. Dapp Se7ens (zdaj neaktiven) je v pogodbi eosio.token razglasil novo metodo za prenos svojih žetonov v uporabniške račune. Pogodba ni zahtevala izdaje ali dejanja prenosa pogodbe eosio.token, da bi odražala spremembe, zato so se sredstva čarobno pojavila na računih uporabnikov. Drugič, pozabili so preveriti znesek v metodi pred prenosom, ki je hekerju omogočil, da je v postopku zahteval milijardo njihovih žetonov.

Poleg spreminjanja največje ponudbe in simbola žetona je priporočljivo, da se ne spreminjate tudi za funkcije po meri, saj so napake v pogodbi eosio.token lahko usodne. Da varno olajšate zračno kapljico, prenesite žetone airdrop na ločen račun in jih od tam distribuirajte.

Sprememba lastnosti tabele z več indeksi

EOS trenutno shranjuje podatke v skupno podatkovno bazo podatkov za skupno rabo.

struct [[eosio :: table]] oseba {

ključ_ime_računa;

std :: string first_name;

std :: string priimek;

std :: string street;

std :: string city;

std :: niz stanja;

uint64_t primarni_ključ () const {ključ za vrnitev; }

};

typedef eosio :: multi_index<N (ljudje), oseba> naslov_indeks;

Zgornja vzorčna koda ustvari tabelo multi_index z imenom people, ki temelji na podatkovni strukturi ene vrstice te tabele z uporabo osebe struct. EOS trenutno ne dovoljuje sprememb lastnosti tabele, ko se uvede. Napaka trditve eosio_assert_message bo napaka, ki bo vržena. Zato je treba lastnosti pred namestitvijo tabele popolnoma premisliti. V nasprotnem primeru je treba ustvariti novo tabelo z drugačnim imenom in biti zelo previden pri selitvi s stare tabele na novo. Če tega ne storite, lahko pride do izgube podatkov.

Numerično preverjanje prelivanja

Pri izvajanju aritmetičnih operacij se lahko vrednosti prelivajo, če mejni pogoji niso dovolj odgovorno preverjeni, kar povzroči izgubo uporabniškega premoženja.

neveljaven prenos (simbol_ime_ simbol, ime_računa iz, imena računov v, stanje uint64_t) {

require_auth (od);

račun z računa;

eosio_assert (is_balance_within_range (saldo), "neveljavno stanje");

eosio_assert (ravnotežje > 0, "mora prenesti pozitivno stanje"); uint64_t znesek = stanje * 4; // Prelivanje množenja

}

V zgornji vzorčni kodi z uporabo uint64_t za označevanje uporabniškega ravnovesja lahko povzroči, da se vrednost pomnoži. Zato se izogibajte uporabi uint64_t za označevanje tehtnic in izvajanje aritmetičnih operacij na njih, kolikor je to mogoče. Za operacije uporabite strukturo sredstev, opredeljeno v eosiolibu, in ne natančno ravnotežje, ki skrbi za pogoje prelivanja.

Skrb za predpostavke v pogodbi

Obstajale bodo predpostavke, ki bodo zahtevale trditve med izvajanjem pogodbe. Uporaba eosio_assert bo predhodno poskrbela za pogoje in ustavila izvajanje določenega dejanja, če trditve ne bodo uspele. Kot primer –

void assert_roll_under (const uint8_t& roll_under) {

eosio_assert (roll_under >= 2 && roll_under <= 96,

"zvitek pod prelivom, mora biti večji od 2 in manjši od 96");

}

Zgornja izjava za trditev predvideva, da je celo število roll_under večje od 2 & manj kot 96. Če pa ne, vrzite zgornje sporočilo in ustavite izvedbo. Če ne bi odkrili vogalnih primerov, kot je zgoraj, bi lahko postalo katastrofalno za hišo, ki določa pravila.

Ustvarjanje resničnih naključnih števil

Ustvarjanje resničnih naključnih številk na bloku EOS Blockchain je še vedno tveganje, če se ne izvede natančno. Če tega ne storite pravilno, bo nasprotnik napovedal izide in pri tem igral ves sistem. Storitve, kot so Oracalize.it obstaja za zagotavljanje naključnih števil iz zunanjega vira, vendar so drage in imajo samo eno točko okvare. Ljudje so v preteklosti uporabljali kontekstne spremenljivke Blockchain (številka bloka, žig bloka itd.) Za generiranje naključnega števila v pametni pogodbi Ethereum, vendar je bilo igral prej. Za pravilno izvedbo generacije mora program zagotoviti nekakšno kombinirano naključnost, ki je nobena stranka ne more nadzorovati sama. Trenutno najboljši možni način je metoda, ki jo je predlagal Dan Larimar sam pri generiranju naključnega števila med dvema strankama.

Blog BountyOne: Varnost pametne pogodbe EOS

niz sha256_to_hex (const kontrolna vsota256& sha256) {

vrni se na_hex ((char *) sha256.hash, sizeof (sha256.hash));

}

niz sha1_to_hex (const kontrolna vsota 160& sha1) {

vrni se na_hex ((char *) sha1.hash, sizeof (sha1.hash));

}

predloga <razred T>

Vstavljena praznina hash_combine (std :: size_t& seme, const T& v) {

std :: hash<T> mešalnik;

seme ^ = hasher (v) + 0x9e3779b9 + (seme << 6) + (seme >> 2);

}

Zgornja vzorčna koda daje optimizirano generiranje naključnih števil med 1 in 100. seed1 je hišno seme, seed2 pa uporabniško seme zgoraj. Za referenco, Dappub in EOSBetCasino imajo odprte kode za svoje popolne pogodbe z generatorjem naključnih števil izvedbo poštene igre s kockami med igralcem in hišo (razvijalec).

uint8_t compute_random_roll (const kontrolna vsota256& seme1, kontrolna vsota const160& seme2) {

velikost_t hash = 0;

hash_combine (hash, sha256_to_hex (seed1));

hash_combine (hash, sha1_to_hex (seed2));

povratni hash% 100 + 1;

}

EOSBet je pred kratkim dobil spet vdrl od 65.000 EOS, ko je nasprotnik prelisičil njihovo pogodbo eosio.token, da je EOS poslal v svojo denarnico, kadar je sklepal transakcije med lastnimi denarnicami. Pogodbena koda eosio.token obvesti pošiljatelj in prejemnik žetonov EOS, da obstajajo dohodni žetoni. Posnemati vedenje & da bi olajšal vdor, je nasprotnik ustvaril dva računa, predpostavimo A & B. A je imel pametno pogodbo z dejanjem z izjavo require_recipient (N (eosbetdice11)). Ko je A z akcijskim pozivom olajšal transakcijo od A do B, je o tem obvestil prenosna funkcija v pogodbi, kot da je klic prišel iz pogodbe eosio.token. Ker v pogodbo ni prišlo do resničnega prenosa EOS-a, je heker, kadar je izgubil stavo, ni izgubil ničesar, vendar je bil nagrajen, ko je stavljen. Zato preverjanje samo imena pogodbe in imena akcije ni dovolj.

Preverja obvestila iz pogodb

Za ublažitev težave mora funkcija preveriti, ali je pogodba res prejemnik žetonov ali ne.

eosio_assert (transfer_data.from == _self || transfer_data.to == _self, "To mora biti dohodni ali odhodni prenos");

Katere so najboljše prakse, ki jih je treba upoštevati pri razvoju pametne pogodbe za EOS?

Napake so neizogiben del katere koli programske opreme. Njegove posledice se povečajo v decentraliziranem okolju, še posebej, če gre za transakcijo vrednosti. Poleg zgoraj omenjenih zaščitnih ukrepov EOS, je tu nekaj splošnih previdnostnih ukrepov in najboljših praks, ki bi jih morali upoštevati novi razvijalci pametnih pogodb –

  1. Nenehno revizija pogodbo neodvisno od tretjih družb za revizijo pametnih pogodb, preden jo objavijo na glavnem omrežju.
  2. Naredite potrebno odpravljanje napak za Caveman (edini način za odpravljanje napak v pogodbi) pogodbe, preden jo spustite v testno mrežo. Dokumentacija EOSIO ima a odličen vodnik za to.
  3. Določite mejno hitrost prenosa pri dvigih, da se izognete prekomernim izgubam v začetnih dneh zagona omrežja. Pripravite program za nagrajevanje napak za odgovorno razkritje s strani hekerjev.
  4. V primeru, da odkrijete napako, imejte killswitch, da zamrzne pogodbo.

Za njegovo izvajanje v tabeli multi_index vztrajamo z zastavico. Zastavo smo nastavili z dejanjem, ki ga lahko pokliče samo lastnik pogodbe. In nato pri vsakem javnem dejanju preverimo, ali je zastava zamrznjena ali ne. V nadaljevanju je podan vzorec izvedbe funkcije.

struct st_frozen {

uint64_t zamrznjen;

};

typedef singleton<N (zamrznitev), st_frozen> tb_frozen;

tb_frozen _frozen;

uint64_t getFreezeFlag () {

st_frozen zamrznjeno_st {.frozen = 0};

return _frozen.get_or_create (_self, frozen_st);

}

void setFreezeFlag (const uint64_t& pZmrznjeno) {

st_frozen frozen_st = getFreezeFlag ();

zamrznjeno_st.frozen = pZmrznjeno;

_frozen.set (zamrznjen_st, _sebe);

}

// javna akcija

void freeze () {

require_auth (_self);

setFreezeFlag (1);

}

// javna akcija

void unfreeze () {

require_auth (_self);

setFreezeFlag (0);

}

// kakršna koli javna akcija

nično dejanje (…) {

eosio_assert (getFreezeFlag (). zamrznjeno == 1, "Pogodba je zamrznjena!");

}

  1. Bodite na tekočem z varnostnimi izboljšavami v knjižnicah ali razkritji ranljivosti na platformi. Po potrebi takoj posodobite svoje knjižnice.
  2. Odprtokodna pogodbena koda vsaj tako, da se v igri ohrani poštenost, indie razvijalci pa lahko hitreje pomagajo pri odkrivanju napak.

Varnost pametne pogodbe EOS: sklep

Od uvedbe EOS-a je minilo le 5 mesecev, vendar je že presegel pričakovanja. Kompromis, ki ga je naredil – DPOS, spremenljive pametne pogodbe, 21 rudarskih vozlišč itd. Se je zagotovo soočilo s hudimi kritikami decentraliziranih maksimalistov. Kljub temu dApps, ki temelji na Ethereumu, ni ustavil, da bi prešel na EOS, glede na razširljivost, ki jim jo danes ponuja platforma. Ali bo EOS ali Ethereum zmagal v vojni, se še ni odločilo, vendar je EOS zagotovo zmagal v bitki. In ostalo bo enako, dokler Ethereum ne bo uspel doseči prilagodljivosti, ki jo potrebuje svet, za zagon “The World Computer”.

_________________________________________________________________________________________

Ta članek je napisal Rohan Agarwal

Bio – #Android Dev # Podjetnik # Blockchain Dev & Soustanovitelj raziskovalca @ Cypherock.com – varna denarnica za strojno opremo za pametne telefone.

Linkedin – https://www.linkedin.com/in/rohanagarwal94/

Github – https://github.com/rohanagarwal94

Twitter – https://twitter.com/rohanagarwal94

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me