Ukratko

Najvažnije iz članka

  • Smart Contracts su samoispunjavajući ugovori na blockchainu, a Ethereum je dominantna platforma za njihovu implementaciju pomoću Solidityja.
  • Postavljanje razvojnog okruženja uključuje Node.js, npm, Truffle Suite i Ganache za lokalnu simulaciju Ethereum mreže.
  • Napisani Solidity ugovor se kompilira u bytecode, a zatim deploya na blockchain putem migracijskih skripti u Truffleu.
  • Interakcija s deployed ugovorom moguća je putem Truffle Console-a, a automatizirani testovi osiguravaju ispravnost i sigurnost koda.
Sadržaj članka
  1. Uvod u Smart Contracts i Ethereum
  2. Zašto baš Ethereum i Solidity?
  3. Postavljanje razvojnog okruženja
  4. Instalacija preduvjeta
  5. Kreiranje i konfiguracija Truffle projekta
  6. Konfiguracija Truffle-a za Ganache
  7. Pisanje prvog Smart Contracta (Solidity)
  8. Objašnjenje koda:
  9. Kompilacija i Deployanje ugovora
  10. 1. Kompilacija
  11. 2. Kreiranje migracijske skripte
  12. 3. Deployanje na Ganache
  13. Interakcija s deployed ugovorom
  14. Čitanje vrijednosti (get)
  15. Postavljanje nove vrijednosti (set)
  16. Provjera ažurirane vrijednosti
  17. Testiranje Smart Contracta
  18. Objašnjenje testa:
  19. Pokretanje testova
  20. Zaključak i sljedeći koraci

Uvod u Smart Contracts i Ethereum

Blockchain tehnologija, a posebno Ethereum platforma, donijela je revoluciju u načinu na koji percipiramo i provodimo transakcije, ugovore i digitalnu imovinu. Centralni stup te revolucije su "pametni ugovori" (Smart Contracts) – samoispunjavajući ugovori kodirani na blockchainu. Za razliku od tradicionalnih ugovora, pametni ugovori izvršavaju se automatski i samostalno kada su ispunjeni unaprijed definirani uvjeti, bez potrebe za posrednicima. Njihova nepromjenjivost (immutability), transparentnost i otpornost na cenzuru čine ih idealnim za širok spektar primjena, od financijskih sustava (DeFi) do upravljanja lancem opskrbe i digitalnog identiteta.

Ethereum je prva blockchain platforma koja je popularizirala koncept pametnih ugovora, omogućujući developerima da pišu decentralizirane aplikacije (DApps) koristeći Turing-kompletan programski jezik Solidity. U ovom opsežnom vodiču, proći ćemo kroz cijeli proces – od postavljanja razvojnog okruženja, pisanja i testiranja jednostavnog Smart Contracta, pa sve do njegovog deployanja na lokalnu testnu mrežu i interakcije s njim. Cilj je pružiti praktično znanje koje će vam omogućiti da samostalno počnete istraživati svijet decentraliziranog programiranja.

Zašto baš Ethereum i Solidity?

Ethereum je i dalje dominantna platforma za pametne ugovore, s najvećom developerskom zajednicom, najviše alata i najširim ekosustavom. Unatoč pojavljivanju brojnih "Ethereum killera", njegova infrastruktura, sigurnost i mreža efekata ostaju neusporedivi.

Solidity je programski jezik specifično dizajniran za pisanje pametnih ugovora na Ethereum Virtual Machineu (EVM). Iako ima svoje specifičnosti i krivulju učenja, njegova sintaksa podsjeća na JavaScript, što ga čini relativno pristupačnim za developere s iskustvom u web programiranju. Razumijevanje Solidityja ključno je za svakoga tko želi aktivno sudjelovati u razvoju decentraliziranih aplikacija.

Postavljanje razvojnog okruženja

Prije nego što zaronimo u kod, moramo postaviti odgovarajuće razvojno okruženje. Koristit ćemo kombinaciju popularnih alata koji su postali de facto standard u Ethereum developerskoj zajednici:

  • Node.js i npm (ili yarn): Potrebni za instalaciju i upravljanje JavaScript paketima.
  • Truffle Suite: Kompletan razvojni okvir za Ethereum, uključujući alate za kompilaciju, deployanje, testiranje i otklanjanje pogrešaka pametnih ugovora.
  • Ganache: Osobni Ethereum blockchain za lokalni razvoj. Omogućuje vam deployanje ugovora i testiranje transakcija bez potrebe za stvarnim Ethereumom ili spajanjem na javnu testnu mrežu.
  • Visual Studio Code (VS Code): Preporučeni uređivač koda s ekstenzijama za Solidity.

Instalacija preduvjeta

  1. Node.js i npm: Posjetite službenu stranicu Node.js-a i preuzmite stabilnu verziju. Nakon instalacije, provjerite verzije:

    node -v
    npm -v
    
  2. Truffle Suite i Ganache: Otvorite terminal i instalirajte Truffle globalno, a Ganache možete preuzeti kao desktop aplikaciju ili instalirati CLI verziju (preporučamo desktop za početak).

    npm install -g truffle
    npm install -g ganache-cli # (opcionalno, ako preferirate CLI verziju)
    

    Preuzmite desktop verziju Ganachea s trufflesuite.com/ganache.

  3. Visual Studio Code: Preuzmite s code.visualstudio.com. Nakon instalacije, preporučujemo instalaciju ekstenzije "Solidity" (autora Juan Blanco) za syntax highlighting, linting i automatsko formatiranje.

Kreiranje i konfiguracija Truffle projekta

Kreirajmo novi Truffle projekt. Otvorite terminal u mapi gdje želite smjestiti svoj projekt i izvršite sljedeće naredbe:

mkdir moj_smart_ugovor
cd moj_smart_ugovor
truffle init

Ovo će stvoriti osnovnu strukturu Truffle projekta:

  • contracts/: Mapa za vaše Solidity pametne ugovore (datoteke s .sol ekstenzijom).
  • migrations/: Mapa za skripte koje deployaju vaše ugovore na blockchain.
  • test/: Mapa za JavaScript ili Solidity testove vaših ugovora.
  • truffle-config.js: Glavna konfiguracijska datoteka Truffle projekta.

Konfiguracija Truffle-a za Ganache

Otvorite datoteku truffle-config.js u vašem VS Codeu. Pronađite sekciju networks i dekomentirajte (ili dodajte) konfiguraciju za Ganache. Obično Ganache radi na portu 7545.

// truffle-config.js

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 7545,            // Standard Ganache port
      network_id: "*",       // Any network (default: none)
    },
  },

  // Configure your compilers
  compilers: {
    solc: {
      version: "0.8.0",    // Fetch exact version from solc-bin (ili željena verzija)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      settings: {          // See the solidity docs for advice about optimization and evmVersion
        optimizer: {
          enabled: false,
          runs: 200
        },
        evmVersion: "byzantium"
      }
    }
  },
};

Važno: Pokrenite Ganache desktop aplikaciju prije nego što nastavite. Trebali biste vidjeti listu generiranih računa i privatnih ključeva.

Pisanje prvog Smart Contracta (Solidity)

Kreirajmo jednostavan pametni ugovor za spremanje i dohvaćanje jedne vrijednosti. U folderu contracts/ kreirajte novu datoteku SimpleStorage.sol.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 public storedData; // Varijabla za pohranu broja

    // Konstruktor se izvršava samo jednom pri deployanju ugovora
    constructor() {
        storedData = 0;
    }

    // Funkcija za postavljanje nove vrijednosti
    function set(uint256 x) public {
        storedData = x;
    }

    // Funkcija za dohvaćanje trenutne vrijednosti
    function get() public view returns (uint256) {
        return storedData;
    }
}

Objašnjenje koda:

  • // SPDX-License-Identifier: MIT: Standardna licenca za Solidity datoteke. Dobra praksa je uključiti je.
  • pragma solidity ^0.8.0;: Definira verziju Solidity kompilatora koju koristimo. ^ znači "kompatibilna verzija, minimalno 0.8.0".
  • contract SimpleStorage { ... }: Definira naš pametni ugovor. Sve unutar vitičastih zagrada pripada ugovoru.
  • uint256 public storedData;: Deklarira stanje varijable storedData tipa uint256 (neoznačeni cijeli broj od 256 bitova). Ključna riječ public automatski generira funkciju za dohvaćanje ove varijable (getter).
  • constructor() { storedData = 0; }: Konstruktor. Izvršava se samo jednom, prilikom deployanja ugovora. Ovdje inicijaliziramo storedData na 0.
  • function set(uint256 x) public { ... }: Funkcija set prima jedan argument x tipa uint256. Ključna riječ public znači da se funkcija može pozvati izvan ugovora. Unutar funkcije, vrijednost storedData se ažurira na x. Ova operacija mijenja stanje blockchaina i zahtijeva transakciju (plaćanje gasa).
  • function get() public view returns (uint256) { ... }: Funkcija get ne prima argumente i vraća uint256. Ključna riječ public slično kao i kod set. view modificator označava da ova funkcija samo čita stanje blockchaina i ne modificira ga. Funkcije s view ili pure modifikatorima ne koštaju gas kada se pozivaju izvan ugovora (iz nekog vanjskog klijenta), ali koštaju ako se pozovu iz drugog ugovora.

Kompilacija i Deployanje ugovora

1. Kompilacija

Prije nego što možemo deployati ugovor, moramo ga kompajlirati u bytecode koji Ethereum Virtual Machine (EVM) može razumjeti. U terminalu, unutar korijenskog foldera projekta, pokrenite:

truffle compile

Ako sve prođe u redu, vidjet ćete uspješnu poruku i nova datoteka SimpleStorage.json bit će stvorena u build/contracts/ folderu. Ova JSON datoteka sadrži bytecode, Application Binary Interface (ABI) i ostale metapodatke o vašem ugovoru.

2. Kreiranje migracijske skripte

Mreže Ethereum koriste koncept "migracija" za deployanje ugovora. U folderu migrations/ kreirajte novu datoteku nazvanu 2_deploy_simplestorage.js (broj na početku je važan za redoslijed izvršavanja migracija).

// migrations/2_deploy_simplestorage.js

const SimpleStorage = artifacts.require("SimpleStorage");

module.exports = function (deployer) {
  deployer.deploy(SimpleStorage);
};
  • artifacts.require("SimpleStorage"): Govorimo Truffleu da učita definiciju našeg SimpleStorage ugovora.
  • module.exports = function (deployer) { ... }: Standardna Node.js sintaksa za izvoz funkcije. Truffle će pozvati ovu funkciju proslijedivši joj deployer objekt, koji nam omogućuje interakciju s blockchainom.
  • deployer.deploy(SimpleStorage): Naredba za deployanje našeg SimpleStorage ugovora na mrežu.

3. Deployanje na Ganache

Provjerite je li vaša Ganache desktop aplikacija pokrenuta. U terminalu, unutar korijenskog foldera projekta, izvršite naredbu za migraciju:

truffle migrate --network development

--network development govori Truffleu da koristi konfiguraciju za development mrežu koju smo definirali u truffle-config.js. Trebali biste vidjeti detaljan ispis koji prikazuje transakcije deployanja, potrošnju gasa i adrese ugovora. Adresa ugovora je ključna – zapišite je, trebat će nam za interakciju.

U Ganache desktop aplikaciji, vidjet ćete zabilježene transakcije, što potvrđuje uspješno deployanje.

Interakcija s deployed ugovorom

Sada kada je naš ugovor deployan na Ganache, možemo s njim komunicirati koristeći Truffle Console. Truffle Console je interaktivna JavaScript okolina koja se spaja na vašu blockchain mrežu i omogućuje vam jednostavnu interakciju s ugovorima.

U terminalu pokrenite:

truffle console --network development

Unutar konzole, prvo ćemo dobiti instancu našeg deployed ugovora:

// Unutar Truffle Console-a
const simpleStorage = await SimpleStorage.deployed();

Sada kada imamo instancu simpleStorage, možemo pozivati njegove funkcije.

Čitanje vrijednosti (get)

Prvo ćemo pročitati početnu vrijednost storedData (koja bi trebala biti 0, jer smo je tako inicijalizirali u konstruktoru):

const value = await simpleStorage.get();
console.log(value.toString()); // Ili samo value ako je Number

Izlaz bi trebao biti 0.

Možemo također direktno pristupiti public varijabli storedData jer je Solidity za nju automatski generirao getter funkciju:

const directValue = await simpleStorage.storedData();
console.log(directValue.toString());

Postavljanje nove vrijednosti (set)

Sada ćemo postaviti novu vrijednost, npr. 42:

await simpleStorage.set(42);

Ova transakcija će promijeniti stanje blockchaina. Vidjet ćete izlaz koji prikazuje detalje transakcije (hash, potrošnju gasa itd.). Provjerite Ganache – vidjet ćete novu transakciju.

Provjera ažurirane vrijednosti

Ponovno pročitajte vrijednost da biste potvrdili promjenu:

const newValue = await simpleStorage.get();
console.log(newValue.toString());

Izlaz bi sada trebao biti 42.

Čestitamo! Uspješno ste napisali, deployali i interagirali s vašim prvim pametnim ugovorom na Ethereum blockchainu.

Testiranje Smart Contracta

Testiranje je ključni dio razvoja pametnih ugovora jer greške u kodu mogu imati ozbiljne financijske posljedice. Truffle nam omogućuje pisanje testova u JavaScriptu (koristeći Mocha i Chai) ili čak u samom Solidityju.

Kreirajmo jednostavan JavaScript test. U folderu test/ kreirajte novu datoteku simple_storage_test.js.

// test/simple_storage_test.js

const SimpleStorage = artifacts.require("SimpleStorage");

contract('SimpleStorage', (accounts) => {
  let simpleStorage; // Deklariramo varijablu za instancu ugovora

  // Prije svakog testa, deployat ćemo svježu instancu ugovora
  beforeEach(async () => {
    simpleStorage = await SimpleStorage.new(); 
  });

  it('should set the value of storedData', async () => {
    await simpleStorage.set(100, { from: accounts[0] });
    const storedValue = await simpleStorage.get();
    assert.equal(storedValue.toNumber(), 100, 'The value should be 100');
  });

  it('should return the correct initial value', async () => {
    const storedValue = await simpleStorage.get();
    assert.equal(storedValue.toNumber(), 0, 'The initial value should be 0');
  });

  it('should allow multiple updates', async () => {
    await simpleStorage.set(50, { from: accounts[0] });
    let storedValue = await simpleStorage.get();
    assert.equal(storedValue.toNumber(), 50, 'First update failed');

    await simpleStorage.set(200, { from: accounts[0] });
    storedValue = await simpleStorage.get();
    assert.equal(storedValue.toNumber(), 200, 'Second update failed');
  });
});

Objašnjenje testa:

  • contract('SimpleStorage', (accounts) => { ... }): Definira test blok za naš ugovor. accounts je niz Ethereum adresa koje Ganache generira, a koje možemo koristiti za simulaciju transakcija.
  • beforeEach(async () => { simpleStorage = await SimpleStorage.new(); });: beforeEach kuka osigurava da se prije svakog testa deploya nova instanca SimpleStorage ugovora. Ovo osigurava da svaki test kreće od "čistog" stanja i da se testovi međusobno ne ometaju.
  • it('should set the value of storedData', async () => { ... });: Definira pojedinačni test slučaj. it blok sadrži asinkroni kod za interakciju s ugovorom i provjeru rezultata.
  • await simpleStorage.set(100, { from: accounts[0] });: Pozivamo funkciju set s vrijednošću 100. { from: accounts[0] } specificira s kojeg računa se šalje transakcija. Ovo je važno jer se transakcije moraju slati s nekog računa.
  • const storedValue = await simpleStorage.get();: Dohvaćamo postavljenu vrijednost.
  • assert.equal(storedValue.toNumber(), 100, 'The value should be 100');: Koristimo Chai-jev assert objekt (koji je dostupan u Truffle testovima) za provjeru je li dohvaćena vrijednost jednaka očekivanoj. toNumber() je potreban jer su vrijednosti iz Solidityja objekti tipa BN (BigNumber) u JavaScriptu.

Pokretanje testova

U terminalu, unutar korijenskog foldera projekta, pokrenite:

truffle test

Truffle će pokrenuti Ganache instancu (ako već nije pokrenuta), deployati vaše ugovore na nju, izvršiti testove i prikazati rezultate. Trebali biste vidjeti poruku o uspješnom prolasku svih testova.

Zaključak i sljedeći koraci

Čestitamo! Uspješno ste prošli kroz cijeli ciklus razvoja pametnog ugovora na Ethereum mreži. Od postavljanja razvojnog okruženja, pisanja jednostavnog Solidity ugovora, preko njegove kompilacije i deployanja na lokalnu testnu mrežu Ganache, do interakcije s njim putem Truffle Console-a i pisanja automatiziranih testova – stekli ste solidnu osnovu za daljnje učenje.

Ovo je, naravno, tek vrh ledenog brijega. Svijet decentraliziranog programiranja je ogroman i stalno se razvija. Evo nekoliko smjernica za vaše sljedeće korake:

  • Složeniji Smart Contracts: Istražite naprednije značajke Solidityja, kao što su nasljeđivanje, implementacija ERC standarda (npr. ERC-20 za tokene, ERC-721 za NFT-ove), rukovanje pogreškama (require, revert), mapiranja i složenije strukture podataka.
  • Sigurnost Smart Contracts: Proučite uobičajene ranjivosti pametnih ugovora (reentrancy, integer overflow/underflow, timestamp dependence, itd.) i najbolje prakse za njihovo izbjegavanje. Alati poput Slither i Mythril mogu pomoći u analizi sigurnosti.
  • Front-end integracija: Naučite kako izgraditi web sučelje (front-end) koje komunicira s vašim Smart Contractom. Popularne biblioteke za to su Web3.js i Ethers.js. Ovo vam omogućuje stvaranje potpunih decentraliziranih aplikacija (DApps).
  • Deployanje na javne testne mreže: Kada ste sigurni u svoj ugovor, pokušajte ga deployati na javnu testnu mrežu poput Sepolia ili Goerli. Za to će vam trebati pravi Ether (testnet Ether, koji se može dobiti putem "faucet-a").
  • Razumijevanje Gas-a: Dublje proučite kako funkcionira Ethereumov sustav gas-a, kako optimizirati potrošnju gasa u svojim ugovorima i kako izračunati troškove transakcija.
  • Decentralizirani Razvojni Okviri (Frameworks): Istražite druge okvire kao što je Hardhat, koji nudi snažne alate za testiranje i otklanjanje pogrešaka.

Blockchain tehnologija i pametni ugovori otvaraju vrata nevjerojatnim inovacijama. Uz strpljenje i kontinuirano učenje, možete postati ključni igrač u izgradnji budućnosti decentraliziranog interneta. Sretno s kodiranjem!

Izvori i dodatno čitanje

  1. Truffle Suite Dokumentacija
  2. Solidity Dokumentacija
  3. Ethereum.org (Smart Contracts)
  4. OpenZeppelin Contracts
B
Uredništvo portala

BAJT

Službeni autorski profil redakcije portala BAJT. Sadržaj priprema i provjerava uredništvo portala.