Jak stworzyć prosty smart kontrat do obsługi aukcji ?

Jak stworzyć prosty smart kontrat do obsługi aukcji ?

7 grudnia

/

Smart contracts

W poprzednim tutorialu dowiedziałeś się, jak stworzyć smart contract, który jest walletem. W tym tutorialu postaramy się utrwalić wiedzę z poprzedniego poradnika oraz poszerzyć ją o nową. 

Przejdźmy więc do dalej. Wszystkie rzeczy, których możesz nie rozumieć wyjaśnimy Ci w dalszej części tekstu.

Zdefiniowanie zmiennych 

Zacznijmy od zdefiniowania zmiennych, które będą nam potrzebne do funkcjonowania smart kontraktu. Na pewno potrzebujemy :

  • adres osoby do której zostanie przesłana najwyższa oferta,
  • czas, kiedy dana aukcja się zakończy,
  • adres osoby, która wystawiła najwyższą ofertę,
  • ile wei to najwyższa oferta,
  • tablicę adresów i ilość pieniędzy jaką przelali do smart kontraktu, aby osoby, które nie wygrały aukcji, mogły wypłacić swoje pieniądze,
  • zmienną czy aukcja jest zakończona lub nie.
pragma solidity 0.8.11;

contract Auction {

    address payable public beneficiary;

    uint public auctionEndTime;

    address public highestBidder;

    uint public highestBid;

    mapping(address => uint) pendingReturns;

    bool ended;

}

Czego możesz nie zrozumieć z powyższego kodu?

Mapping w solidity to tablica klucz-wartość, odpowiednik dictionary w innych językach.

Jeśli nie wiesz czemu zmienna auctionEndTime jest podana w zwykłym uintcie, to jest to z tego powodu, że czas kiedy aukcja się zakończy będzie podany w czasie unixowym.

Stwórzmy sobie constructor, który będzie przyjmował adres do którego zostanie przesłana najwyższa oferta oraz ile czasu będzie trwała aukcja.

constructor(

        uint biddingTime,

        address payable beneficiaryAddress

    ) {

        beneficiary = beneficiaryAddress;

        auctionEndTime = block.timestamp + biddingTime;

    }

Na co warto zwrócić uwagę ?

  • block.timestamp to zmienna, która oznacza po prostu jaki jest teraz czas podany oczywiście jako czas unixowy.

Funkcja do składania ofert

Teraz stwórzmy sobie funkcję, która będzie służyła do składania swojej oferty. Funkcja ma zwracać błąd jeśli :

  • aukcja się zakończyła,
  • nasza oferta będzie niższa niż najwyższa oferta.

Na zakończenie wykonywania funkcji, funkcja wyemituje event, mówiący o tym że najwyższa oferta się zmienia. Aplikacja frontendowa może nasłuchiwać emitowanych eventów na smart contracie, dzięki czemu, gdy tylko najwyższa oferta się zmieni, może ona ją zaktualizować w interfejsie użytkownika.

event HighestBidIncreased(address bidder, uint amount);

    event AuctionEnded(address winner, uint amount);

    error AuctionAlreadyEnded();

    error BidNotHighEnough(uint highestBid);

    error AuctionNotYetEnded();

    error AuctionEndAlreadyCalled();

    function bid() external payable {

        if (block.timestamp > auctionEndTime)

            revert AuctionAlreadyEnded();

        if (msg.value <= highestBid)

            revert BidNotHighEnough(highestBid);

        if (highestBid != 0) {

            pendingReturns[highestBidder] += highestBid;

        }

        highestBidder = msg.sender;

        highestBid = msg.value;

        emit HighestBidIncreased(msg.sender, msg.value);

    }

Jak widzisz w powyższym kodzie definiowane są eventy z parametrami, które możemy wyemitować na blockchainie. Aby wyemitować event w solidity wpisujemy 

emit  + nazwa eventu i parametry

Zdefiniowaliśmy sobie swoje własne errory, które jeśli chcemy wywołać wpisujemy

revert + nazwa naszego erroru i parametry.

Zapewne domyśliłeś się już, że zamiast ifów i custom errorów mogliśmy użyć requiera.

Ta funkcja sprawdza czy aukcja się już nie zakończyła, czy msg.value jest wyższy niż najwyższa oferta, jeśli tak aktualizujemy mapping pendingReturns, żeby osoba, która złożyła wcześniej najwyższą ofertę mogła dostać z powrotem swoje pieniądze. Przypisujemy najwyższą ofertę do msg.value oraz highestBidder do msg.sender, na końcu wykonywania funkcji emitujemy event, który informuje, że najwyższa oferta została zwiększona.

Funkcja do zakończenia aukcji, oraz przelania najwyższej oferty do beneficiera

Teraz stwórzmy funkcję dzięki, której po zakończonej aukcji adres beneficiary, będzie mógł przesłać do swojego portfela pieniądze.

Ta funkcja powinna:

  • zwracać błąd jeśli aukcja się jeszcze nie skończyła,
  • zwracać błąd jeśli ta funkcja została już wywołana,
  • zmieniać zmienna ended na true,
  • wyemitować event świadczący o tym, że aukcja się zakończyła,
  • przesłać ilość Ethereum równoważną do najwyższej oferty do beneficiera.

  

function auctionEnd() external {

        if (block.timestamp < auctionEndTime)

            revert AuctionNotYetEnded();

        if (ended)

            revert AuctionEndAlreadyCalled();

        ended = true;

        emit AuctionEnded(highestBidder, highestBid);

        beneficiary.transfer(highestBid);

    }

Funkcja dla osób, które nie wygrały aukcji i chcą odzyskać swoje pieniądze

Teraz, ostatnia funkcja, której potrzebujemy, aby nasz kontrakt był gotowy! Będzie ona dla adresów, które nie wygrały aukcji, a chcą odzyskać swoje pieniądze. Zastanówmy się co powinna mieć w sobie taka funkcja :

  • powinna sprawdzać ile należy ci się ethereum w mappingu pendingReturns oraz przypisać tą wartość do zmiennej,
  • powinna zmienić ile ci się należy na 0,
  • powinna przesłać tyle Ethereum ile zapisaliśmy w zmiennej.

No to do dzieła !

  function withdraw() external{

        uint amount = pendingReturns[msg.sender];

        pendingReturns[msg.sender] = 0;

        payable(msg.sender).transfer(amount);

    }

To już koniec dzisiejszego tutorialu ! Nasz smart contract jest gotowy. W celu poćwiczenia oraz utrwalenia sobie wiedzy, jako zadanie możesz spróbować zamienić custom errory na requiry. Jeśli to jednak dla ciebie za mało możesz również ulepszyć ten kontrakt, aby dało się w nim prowadzić kilka aukcji na raz.

Never miss a story

Stay updated about Nextrope news as it happens.

You are subscribed

More of our Blog

See the latest collection of articles produced by our seasoned professionals

Zakres projektu

API/Backend
Development

Strony Internetowe
Development

Aplikacje Mobilne
Development

Projektowanie
Design

Blockchain
Solutions

Usługi Internetowe
Services

Next Enterprises zapewniło bankowi usługę technologiczną potrzebną do wprowadzenia projektu opartego na blockchainie. W ramach współpracy firma zaprojektowała usługę w modelu SaaS. Rozwiązanie przechowuje na swoich serwerach, udostępniając je bankowi i jednocześnie gwarantując jakość zgodną ze standardami zawartymi w umowie.

Tomasz Sienicki

Tomasz Sienicki

Blockchain Strategy Manager, Alior Bank

Współpraca z zespołem Nextrope wyznacza zupełnie nowy poziom jakości, innowacyjnych rozwiązań i profesjonalnych usług. Jeśli potrzebujesz wsparcia przy technologii blockchain, trafiłeś na profesjonalistów. Zdecydowanie polecam!

Kajetan Komar-Komarowski

Kajetan Komar-Komarowski

Współzałożyciel i prawnik Lex Secure

W listopadzie 2017 r. opublikowaliśmy grę wykorzystującą inteligentne kontrakty jako mechanizm dystrybucji i transakcji. Zespół Nextrope wspierał nas w najważniejszej części projektu - tworzeniu i testowaniu bezpieczeństwa inteligentnych kontraktów blockchain w sieci Ethereum. Mogę gorąco polecić Mateusza i jego zespół - to prawdziwi eksperci w dziedzinie blockchaina.

Maciej Skrzypczak

Maciej Skrzypczak

CEO Gameset