Solidity nauka

Solidity po polsku – kurs programowania smart kontraktów

Aby tworzyć smart kontrakty, nie musisz ściągać w całości Ethereum Wallet z wszystkimi blokami na swój komputer.
Jeżeli już próbowałeś to zrobić, to wiesz jak długo trwa pobieranie.
Istnieje inne rozwiązanie.

Kompilator online

Możesz pisać  smart kontrakty,  kompilować je i sprawdzać czy poprawnie je napisałeś,  online na stronie : remix.ethereum.org

Definiowanie stałej – constant

string constant fName = 'Gary';

Definiowanie zmiennej

uint private age;

Prosty kontrakt z Setter i Getter

Poniższy kontrakt pozwala ustawiać wiek i imię.
Możemy też odczytać przypisane wartości.

Setter – oznacza,  że nadajesz czemuś wartość.
Getter – oznacza, że pobierasz jakąś wartość.

pragma solidity ^0.4.0;

contract MyFirstContract {
string private name;
uint private age;

function setName(string newName) {
name = newName;
}

function getName() returns (string) {
return name;
}

function setAge(uint newAge) {
age = newAge;
}

function getAge() returns (uint) {
return age;
}
}

Jak używać kompilatora?

Używamy kompilatora na sieci testowej.

  1. Wpisz lub wklej  kod smart kontraktu w sekcji do tego przeznaczonej.
  2. W zakładce Compile kliknij na Start to compile.
  3. Kliknij w sekcję Run.
  4. Wybierz JavaScript VM.
  5. Kliknij przycisk Create.
  6. Możesz teraz klikać przyciski odczytujące wiek i imię oraz ustawiające te wartości.

Poniżej przedstawiam grafikę,  na której możesz zobaczyć w których miejscach należy wykonać powyższe kroki (konfiguracja kompilatora).

setName i setAge

Klikasz setName i możesz nadać imię.
Imię wpisujesz tak: “Konrad”
Musisz otoczyć je znakami cudzysłów bo jest to string.

Klikając setAge możesz zdefinować wiek.
Wiek podajesz normalnie.

Gdy już nadasz jakiś wiek np. 35 to możesz kliknąć przycisk getAge.

Aby odczytać tę wartość przesuń się w lewo i kliknij Details.

W sekcji decoded output możesz odczytać wiek.

 

Emisja prawdziwego smart kontraktu

  1. Używaj Google Chrome
  2. Zainstaluj na Chrome wtyczkę MetaMask.
  3. Utwórz portfel na MetaMask i zaloguj się na niego.
  4. Przelej na MetaMask jakąś część Ethereum. Za emisję smart kontraktu płaci się w tej kryptowalucie.
  5. Wchodzisz na stronę remix.ethereum.org.
  6. Piszesz swój smart kontrakt, zmieniasz sieć testową  JavaScript VM na sieć Injected Web3.
  7. Klikasz Crate.
  8. Otworzy się MetaMask, gdzie wyświetli się informacja o tym, ile kosztuje emisja danego smart kontraktu.
  9. Zatwierdzasz i gotowe.


Dostęp do funkcji tworzenia nowych coinów ma tylko twórca kontraktu

To jest kontrakt który pozwala różnym adresom przypisać wartość liczbową coinów (które istnieją tylko w tym kontrakcie).
Następnie użytkownicy tych adresów mogą sobie wzajemnie lub na inne adresy wysyłać swoje coiny.
Każdy może sprawdzić ilośc coinów przypisanych do dowolnego adresu.


pragma solidity ^0.4.21;

contract Coin {
   
    address public minter;
    mapping (address => uint) public balances;

    function Coin() public {
        minter = msg.sender;
    }
    
    // Wywarzać nowe monety może tylko twórca kontaktu - minter
    // Jeżeli ktoś inny uruchomi funkcję to return natychmiast
    // przerwie funkcję
    function mint(address receiver, uint amount) public {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
    }
}

Modifier

Pozwala na uruchomienie wskazanych funkcji tylko przez właściciela. Jest to bardziej profesjonalny sposób ograniczania dostępu do funkcji.

contract Jobs {
   address public owner;

   // Poniżej jest konstruktor, który uruchamia się tylko raz podczas tworzenia projektu.
   // Konstruktor przypisuje wartości owner adres twórcy kontraktu

   function Jobs() public{
      owner = msg.sender;
   }

   // Poniżej tworzymy modifier, jeżeli przykleimiy onlyOwner() do jakiejś funkcji to tylko właściciel będzie mógł ją uruchomić
   
   modifier onlyOwner(){
      require(msg.sender == owner);
      _;
   }
   
   // Poniższa funkcję uruchomi tylko własciciel   

   function Kill_This_Contract() onlyOwner{
      selfdestruct(owner);
    }
}

Jak wyświetlić adres z którego łączę się z kontraktem

Ta funkcja przydaje się podczas testowania kontraktu na remix.ethereum.org

function MyAddress() returns (address){
   return msg.sender;
}

Jak sprawdzić balans kontraktu z wewnątrz kontraktu – ile jest na nim ETH

pragma solidity ^0.4.21;

contract testowy{
   function pokazBalance () public view returns (uint){
      return address(this).balance;
   }
}

Sprawdzenie balansu dowolnego konta z poziomu kontraktu

function balances(address _account) public view returns (uint) {
    return balances[_account];
}

Funkcja umożliwiająca wyświetlenie adresu kontraktu na którym pracuję

Ta funkcja przydaje się podczas testowania kontraktu na remix.ethereum.org

function contractAddress() returns (address){
   return address(this);
}

Struct

Dzięki struct można budować bardziej założone typy danych.

pragma solidity ^0.4.19;

contract Armia {

   struct Wojownik {
      string name;
      uint power;
   }
}

Tablice

W deklaracji tablicy możesz na wstępie określić ile ma mieć ona elementów:
uint[2] tablica1;
Możesz też nie określać ilości elementów, taka tablica będzie się powiększała dynamicznie:
uint[] tablica2;
Możesz też stworzyć tablicę przechowującą elementy struct:
Wojownik[] public oddzial;

Dodawanie wartości do tablicy

Wartość możemy dodawać na pierwszą wolną pozycję:

///Utworzenie tablicy
uint[] public tablica1;
uint zmienna = 13;
tablica1.push(zmienna);

Dodawanie elementu struct do tablicy

pragma solidity ^0.4.19;
contract Factory {

   struct Auto {
      string name;
      uint vin;
   }

   Auto[] public cars;

   function createAuto(string _name,uint _vin){
      cars.push(Auto(_name, _vin));
   }
}

Czyszczenie elementu z tablicy

Funkcja ta czyści jeden wskazany rekord z tablicy. Rekord ten jednak nadal istnieje, wielkość tablicy się nie zmienia.

function usun_temat_o_nr(uint _nrDoKosza) public {
   delete tablicaTematow[_nrDoKosza];
}

Skracanie tablicy czyli usówanie jej ostatniego elementu

array.length--;

Funkcje private i public

Funkcja public to taka, którą może uruchomić każdy także inny kontrakt.

Funkcja private to taka, którą może uruchomić tylko inna funkcja z Twojego smart kontaktu.

Przykład zdefiniowania funkcji prywatnej:

function _addToArray(uint _number) private {
   numbers.push(_number);
}

Funkcja publiczna ma zamiast słowa private – public.

Generowanie liczb pseudolosowych

 function losuj() public pure returns (uint){
    return uint(keccak256("aaaab"));
 }

Funkcja keccak256 zmienia stringa na zapis szesnastkowy.
Następnie wynik poprzedniej funkcji jest zamieniany na liczbę całkowitą dodatnią.

Losowanie liczb

Losowanie liczb nie jest takie proste w Solidity jak np. w C#.
Poniżej zamieszczam link wyjaśniający tę sprawę.

https://gist.github.com/alexvandesande/259b4ffb581493ec0a1c

Poniżej zamieszczam kod losującu od 7 do 12. Losowanie jest wykonywane w oparciu o poprzedni blok. Seed to zmienna pomocnicza umożliwiająca uzyskiwanie innych wyników.

contract losowanie{

    uint private seed=0;
    function randomGen() public returns (uint randomNumber) {
        seed++;
        return((uint(keccak256(block.blockhash(block.number-1), seed))%14)+7);
    }
}

Modyfikator view i pure

Jeżeli funkcja nic nie zmienia w danych to możesz jej nadać modyfikator view.

pragma solidity ^0.4.0;

contract Test {
string password = “Hello!”;
function sayHello() public view returns (string) {
return password;
}
}

Jeżeli funkcja nie zmnienia danych i nawet ich nie odczytuje to nadaj jej modyfikator pure.

function _multiply(uint a, uint b) private pure returns (uint) {
   return a * b;
}

 

Zdarzenia – Events

Służą do komunikacji pomiędzy blockchain’em a Twoją aplikacją np. stroną internetową.

Zdefiniowanie eventu:

event Instructor(string name, uint age);

Wygenerowanie eventu:

function setInstructor(string _fName, uint _age) public {
   fName = _fName;
   age = _age;
   emit Instructor(_fName, _age);
}

Uruchamiając funkcję setInstructor wysyłamy sygnał Event, który może być odebrany przez naszą stronę internetową.

Mapowanie

Mapowanie działa trochę jak tablica.

Przeanalizuj poniższy kod.
Aby dobrze zrozumieć poniższy skrypt, wlej go do remix.ethereum.org i przetestuj go na dwóch lub trzech adresach ETH.

pragma solidity ^0.4.0;

contract Test {
mapping (address => uint) favoriteNumber;

function setMyNumber(uint _myNumber) public {
  // Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
  favoriteNumber[msg.sender] = _myNumber;
  // ^ The syntax for storing data in a mapping is just like with arrays
}

function whatIsMyNumber() public view returns (uint) {
  // Retrieve the value stored in the sender's address
  // Will be `0` if the sender hasn't called `setMyNumber` yet
  return favoriteNumber[msg.sender];
}

}

 

Ten kontrakt pozwala przypisać ulubiony nr do Twojego adresu.

Pozwala też odczytać Twój ulubiony nr.

Licznik uruchomienia funkcji

Funkcja setLicznik zlicza ile razy ją uruchomił użytkownik o danym adresie.

pragma solidity ^0.4.0;

contract Test {
mapping (address => uint) licznikNumber;

function setLicznik() public {
 // Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
 licznikNumber[msg.sender]++;
 // ^ The syntax for storing data in a mapping is just like with arrays
}

function whatIsLicznik() public view returns (uint) {
 // Retrieve the value stored in the sender's address
 // Will be `0` if the sender hasn't called `setMyNumber` yet
 return licznikNumber[msg.sender];
}

}

Dziedziczenie – Inheritance

Jeden kontrakt może dziedziczyć po drugim.
Dzięki temu można wywoływać funkcje, które znajdują się w kontrakcie po którym dziedziczymy.

Przeanalizuj i uruchom poniższy kontrakty.

pragma solidity ^0.4.0;

contract Doge {
   function catchphrase() public returns (string) {
   return "So Wow CryptoDoge";
   }
}

contract BabyDoge is Doge {
   function anotherCatchphrase() public returns (string) {
   return "Such Moon BabyDoge";
   }
}

Import

Mamy dwa pliki a.sol i b.sol.

Plik b.sol dziedziczy po a.sol. Jego kod to:

pragma solidity ^0.4.0;

import "./a.sol";

contract Cat is Doge {
   function cat() public returns (string) {
   return "So Wow CryptoCat";
   }
}

Jeżeli mamy plik z rozszerzeniem .sol w tej samej lokalizacji co plik na którym piszemy nasz kontakt, to zostanie on zaimportowany przez kompilator.
Pamiętaj o tym, że jeden kontrakt dziedziczy po drugim. Musisz użyć słówka is.

Czas

Coś się może dziać w zależności od czasu.

Przykład smartkontraktu.:

function f(uint start, uint daysAfter) public {
    if (now >= start + daysAfter * 1 days) {
      // ...
    }
}

Możemy używać: seconds, minutes, hours and years.

Przyjęcie płatności w ETH

Poniższy kontrakt zapisuje do zmniennej lastSender adres portfela, z którego ostatnio dokonano przelewu ETH na adres kontraktu.

 

contract token {
address public lastSender ;
function () payable {
   lastSender = msg.sender;
   }
}

Wysyłanie ETH z kontraktu na dowolny adres

Tworzymy zmienną balance, dzięki której będziemy mogli w przyszłości chronić się przed błędami.
Np. próbą wysłania większej kasy niż mamy.

 

uint private balance = 0; 

function showBalance() returns (uint){
   return balance;
}

// funkcja send umożliwia wysyłanie ETH na dowolny adres
function send(address _receiver) payable {
   _receiver.call.value(msg.value).gas(20317)();
   balance -= msg.value;
}

// ta funkcja pozwala przesłać ETH na ten kontrakt.
function () payable {
   balance += msg.value;
}

Inny sposób wysłania swoich środków na zewnątrz kontraktu

function Withdraw(address _to, uint _amount) onlyOwner external payable{
   require(_amount <= totalContribution);
   totalContribution -= _amount;
   _to.transfer(_amount); } 
}

 

Zabicie kontaktu i przelanie wszystkich ETH na konto twórcy

Konstuktorem jest funkcja o nazwie kontraktu. Konstruktor uruchamia się tylko raz gdy kontrakt powstaje.

contract niszczenie {

   address private creator;

   constructor() public{
      creator = msg.sender;
   }

   function remove() {
      if(msg.sender == creator) { 
          selfdestruct(creator); 
      }
   }
}

Łączenie stringów

Łączenie stringów nie jest intuicyjne i trzeba korzystać z dodatkowej biblioteki.

import "github.com/Arachnid/solidity-stringutils/strings.sol";

contract C {
   using strings for *;
   string public s;

   function foo(string s1, string s2) {
      s = s1.toSlice().concat(s2.toSlice());
   }
}

Konwersja uint do string

Trzeba stworzyć specjalną funkcję, która będzie to robiła.

function uint2str(uint i) internal pure returns (string){
   if (i == 0) return "0";
   uint j = i;
   uint len;
   while (j != 0){
      len++;
      j /= 10;
   }
   bytes memory bstr = new bytes(len);
   uint k = len - 1;
   while (i != 0){
      bstr[k--] = byte(48 + i % 10);
      i /= 10;
   }
   return string(bstr);
}

Pisanie Smart Contract’u przy użyciu Visual Studio

Najpierw musisz pobrać paczkę z poniższego linku i ją zainstalować.

https://marketplace.visualstudio.com/items?itemName=ConsenSys.Solidity

Następnie postępuj według poniższego tutorialu

https://medium.com/@ConsenSys/solidity-integration-with-visual-studio-8bdab2ff8a74

Poniżej filmik wyjaśniający zagadnienie:

Strona do nauki podstaw Solidity

Na poniższej stronie możesz stworzyć własną prostą grę w Solidity.
W przyjemny i zabawny sposób nauczysz się podstaw języka Solidity. Polecam.

https://cryptozombies.io

Poniżej link do fajnego poradnika.

https://medium.com/@k3no/anyone-can-kill-your-contract-723c25bd273f

Nową fajną stroną do nauki języka Solidity jest:

https://learn.godapping.com/solidity

Płatny kurs online na udemy:

https://www.udemy.com/ethereum-dapp/

Darmowa strona do nauki Solidity:

https://coursetro.com/courses/20/Developing-Ethereum-Smart-Contracts-for-Beginners

Polska strona o programowaniu smartkontraktów w języku Solidity:

https://antyweb.pl/smart-contracts-tutorial/

Jeszcze jedna strona warta przeczytania i przeanalizowania:

https://blockgeeks.com/guides/solidity/

Środowisko crypto rekomensuje zapoznanie się na początku swojej przygody ze smartkontraktami, z trzema anglojęzycznymi artykułami:

https://hackernoon.com/ethereum-development-walkthrough-part-1-smart-contracts-b3979e6e573e

https://hackernoon.com/ethereum-development-walkthrough-part-2-truffle-ganache-geth-and-mist-8d6320e12269

https://hackernoon.com/ethereum-development-walkthrough-part-3-security-limitations-and-considerations-d482f05278b4

Strona do oglądania i wzorowania się na cudzych smart kontaktach

https://www.stateofthedapps.com/

Testowanie własnych projektów

Można kożystać z jednego z testnetów Ethereum np. rinkeby.
Do testów będziesz potrzebować testowego ETH, pozyskanie kilku ETH, jest możliwe stąd: https://faucet.rinkeby.io/

Strona internetową, która bezpośrednio działa na blockchainie

Możesz stworzyć stronę, która będzie bezpośrednio operowała na Twoim smart kontrakcie.
Stosuje się do takiej łączności Meta Mask.

Poniżej film wprowadzający do zagadnienia:

Crowdsale ERC20

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *