W poprzednim tutorialu dowiedziałeś się, jak stworzyć swój pierwszy smart contract, w tym poście dowiesz się jak stworzyć "Wallet" smart contract, do którego będziesz mógł wysyłać oraz wypłacać Ethereum, oczywiście kontrakt będzie tak napisany, że tylko właściciel kontraktu będzie mógł wypłacić środki.
Czym są keywordy public, external, internal, private ?
Słowo kluczowe public poznałeś już w poprzednim tutorialu “Hello World”, oznacza ono, że funkcja jest publiczna, czyli może zostać wywołana zarówno “na zewnątrz kontraktu” jak i "wewnątrz". Kontrakty, dziedziczące nasz kontrakt bedą miały dostęp do takiej funkcji.
Przykład:
uint counter = 0;
function externalFunction() external {
counter++;
publicFunction();
}
function publicFunction() public {
counter++;
}
Jak widzisz funkcję public można nie tylko wywołać “na zewnątrz smart kontraktu”, ale również w jego środku, tak jak w funkcji externalFunction. A właśnie, co oznacza właściwie ten external?
Jeśli funkcja jest external, oznacza to po prostu, że można ją wywołać tylko “na zewnątrz smart kontraktu” , tak jak wywoływaliśmy naszą funkcje sayHelloWorld w poprzednim tutorialu. Kontrakty, dziedziczące nasz kontrakt, bedą również miały dostęp do funkcji external.
Pozostały jeszcze dwa kluczowe słowa: internal i private.
function returnTwoPlusTwo() internal pure returns (uint256) {
return 2 + 2;
}
function returnMsgSender() private view returns (address) {
return msg.sender;
}
Internal to dokładnie odwrotność external, takiej funkcji nie będzie można wywołać “na zewnątrz smart kontraktu”, tylko w jego środku. Tak samo jak w przypadku external i public, kontrakty, które bedą dziedziczyć taką funkcję, bedą miały do niej dostęp.
Ostatnia do omówienia została funkcja private. Główną jej cechą jest fakt, że będzie ona widoczna tylko w kontrakcie, w którym została zdefiniowana. Natomiast kontrakty, które dziedziczą nasz smart kontrakt, nie będą mogły jej wywołać.
Pure vs View
Po przeanalizowaniu funkcji internal oraz private, można zauważyć, że występują przy nich słowa 'pure' oraz 'view'. Co one oznaczają ?
Gdy funkcja jest pure, oznacza to, że nie modyfikuje ani nie zczytuje żadnych danych z blockchaina, tak jak funkcja returnTwoPlusTwo - zwraca ona tylko wynik 2+2, nie wczytuje ani nie modyfikuje żadnej zmiennej w smart kontrakie ani blockchainie.
Funkcje z dopiskiem view, oznaczają, że nie modyfikują danych z blockchaina, ale za to je wczytują. Na przykład funkcja returnMsgSender zczytuje wartość zmiennej msg.sender, reprezentującą adres, który wywołał daną funkcje.
Dobrze, wystarczy już tej teorii, zabierzmy się w końcu do pracy i stwórzmy wallet smart kontrakt!
Jak stworzyć “Wallet” smart kontrakt
Najpierw, jak zawsze, należy zdefiniować wersję solidity, którą chcemy używać. My będziemy używać wersji 0.8.12, a zatem na górze pliku wpisuje:
pragma solidity 0.8.12;
Tworzę kontrakt o nazwie Wallet :
contract Wallet {
}
Każdy portfel ma swojego właściciela, więc zdefiniuje address na ethereum, który będzie właścicielem smart kontraktu. Ownerem kontraktu nazwiemy osobę, która zrobi deploy naszego smart kontraktu.
Warto zaznaczyć, że powinniśmy mieć zmienną dzięki, której będziemy mogli monitorować balans smart kontraktu.
contract Wallet {
address public owner;
uint public balance;
constructor() {
owner = msg.sender;
}
Stwórzmy funkcję, dzięki której będziemy mogli przesyłać środki do smart kontraktu.
function depositEther() external payable{
balance += msg.value;
}
W tej funkcji pojawiły się dwa nowe słowa : 'payable' oraz 'msg.value'.
Jeśli funkcja jest payable oznacza to, że wraz z wywołaniem funkcji możemy przesyłać ethereum do smart kontraktu, a msg.value to po prostu ilość przesłanych wei wraz z wywołaniem funkcji.
Teraz stwórzmy funkcje, dzięki której będziemy mogli wypłacać przesłane ethereum, oczywiście tylko właściciel smart kontraktu powinien mieć taką możliwość.
function withdrawEther(uint amount) external{
require(msg.sender == owner, "Only owner can call this function");
require(amount <= balance, "Amount exceeds balance");
balance -= amount;
payable(owner).transfer(amount);
}
Require sprawia, że gdy podany w nim warunek się nie spełni funkcja zwraca bład z wiadomością jaką podaliśmy.
W funkcji musieliśmy zkonwertować zmienną owner z addressu na address payable, ponieważ ethereum można przesyłać tylko do adressów ze słowem kluczowym payable.
Podsumowanie
To już koniec! Smart kontrakt jest gotowy! Śmiało, spróbuj się nim pobawić, a jeśli Ci się uda to nawet go ulepszyć.
W następnym tutorialu z serii Nextrope Academy pokażemy jak napisać prosty aukcyjny smart kontrakt.