Hlavní navigace

Ethereová síť už živí první blockchainová tamagotchi

15. 9. 2021
Doba čtení: 7 minut

Sdílet

 Autor: wagmigotchi.pet
Pokud máte pocit, že vás po NFT létu na ethereové síti nemůže nic překvapit, sledujte projekty vývojáře a podnikatele Dominika Hofmanna. Spoluzakladatel Vine a autor aplikací Peach a Byte totiž poslední měsíc testuje, co uživatelé Etherea ještě skousnou.

Hofmann, zdá se, konečně zanevřel na pokusy prorazit ve světě sociálních sítí a zaměřil svoji pozornost raději na blockchainové projekty. Prvním nesmělým pokusem byl projekt Blitmap, ze kterého se vyklubalo testovací území pro divoký experiment jménem Loot.

Projekt Loot se trefil do druhé vlny NFT horečky a zaznamenal velký úspěch. Když na sebe Hofmann konečně strhl pozornost kryptokomunity, mohl se se smyslem pro absurdno sobě vlastním pustit ještě do divočejšího testování toho, co uživatelé smart kontraktů ještě zbaští.

Cesta přes Loot k Wagmigotchi

27. srpna oznámil Hofmann přes svůj Twitter neobvyklý experiment. Programátor v jeho rámci zveřejnil odkaz na ethereový chytrý kontrakt, pomocí něhož mohli uživatelé automaticky vygenerovat osm tisíc virtuálních batohů do ještě neexistující blockchainové hry (vznik navázaných herních projektů nechal autor zcela na bedrech komunity), provázaných s NFT tokenem. 

Každý token odkazoval na obrázek s textovým výpisem osmi položek, které mají být v batozích obsaženy. Uživatelé si následně mohli na svoji ethereovou peněženku nechat NFT token poslat, a to pouze za cenu transakčního poplatku (v době uvedení experimentu dělalo průměrné gas fee okolo sedmi dolarů za transakci).

Přestože batohy neměly žádné praktické využití a jejich grafická reprezentace byla maximálně minimalistická, byly (zřejmě pod vidinou v budoucnu cenného digitálního sběratelského předmětu) rozebrány za necelé čtyři hodiny a během následujících pěti dnů na OpenSea přeprodány za zhruba 46 milionů dolarů. Během uplynulého víkendu překročil sekundární prodej tokenů Lootu magický milník 200 milionů dolarů. Projekt také vyvolal masivní vlnu napodobitelů a projektů, které se snaží majitele Loot tokenů a jejich následovníků shromažďovat.

Těžko říci, jestli Loot tokeny splnily Hofmannův plán, nebo se jen staly manifestací toho, do jakých krajností až může současná hysterie okolo NFT tokenů zajít. Povedlo se mu tím ale každopádně strhnout na sebe pozornost kryptoměnové komunity a otevřít si tak dveře pro další projekty. Druhý sociální experiment se smart kontraktem na sebe nenechal dlouho čekat. Hofmann stvořil pomocí poměrně jednoduchého smart kontraktu blockchainové tamagotchi, respektive Wagmigotchi.

Na rozdíl od Loot tokenů nepředstavuje Wagmigotchi ani latentně způsob, jak spekulativně zbohatnout. Dalo by se spíš říci, že je pravdou pravý opak, protože abyste udrželi blockchainové Wagmigotchi spokojené a živé, musíte pálit poměrně drahý gas a jedinou odměnou vám za to bude dobrý pocit, respektive zpětná vazba ze smart kontraktu, který na začátku ani neměl grafickou reprezentaci. 

Jak říká sám Hofmann k druhému pokusu o udržení kontraktu aktivního: „Přátelé, z tohohle opravdu nijak profitovat nebudete. Je to experiment. Nedělejte to, pokud se nechcete o mazlíčka starat, aniž byste dostávali něco na oplátku.“

Jak 73 transakcí umořilo první Wagmigotchi

Jak Hofmann vysvětlil na svém Twitteru při spouštění první verze kontraktu, interakcí s kontraktem nevzniká na virtuálního blockchainové mazlíka žádný nárok a jediný smysl celé interakce je potěšení z toho, že naplňujete jeho potřeby, za což se vám dostává zpětná vazba v podobě jeho (simulované) spokojenosti.   

První pokus přinesl rozporuplné výsledky. Wagmigotchi číslo 1 zemřelo po 73 transakcích. Nepošlo ovšem na nezájem uživatelů, ale naopak na zaspamování kontraktu jedním typem interakce. 

Popsáno slovy herní logiky, virtuální tvoreček zemřel na vyčerpání poté, co si s ním hrálo příliš mnoho uživatelů. „Hrálo si v krátkém čase příliš často a v důsledku toho pošlo na vyčerpání,“ komentoval neslavný konec prvního Wagmigotchi Hofmann. Dalo by se říci, že šlo o technickou chybu a špatné pochopení mechaniky hry ze strany uživatelů, kteří s kontraktem interagovali.

Druhá generace

Po lehkém tuningu kódu kontraktu spatřilo 10. září světlo světa Wagmigotchi číslo 2. To zatím přežívá a vesele polyká transakční poplatky, kterých již kontrakt spálil za několik desítek tisíc dolarů. 

Druhá generace digitálního mazlíka byla naprogramována odolnější. Pouhá únava z příliš dlouhého hraní jej již nezabíjí, to nyní dokáže jen uživatelský nezájem, tedy nedostatek interakce se smart kontraktem a nenaplňování potřeb mazlíka. Wagmigotchi číslo dva má čtyři atributy, které jsou aktualizovány každý padesátý blok.

Atributy zahrnují nudu, nečistotu, hlad a ospalost. Pokud jeden z parametrů přesáhne pevně daný práh, blockchainový tvoreček „umírá“ a s kontraktem již není možné dále interagovat. 

Jednotlivé akce mají vedle naplnění potřeby virtuálního tvorečka občas za následek také nárůst nespokojenosti v jiné oblasti. Krmení například snižuje hlad, ale zvyšuje nudu nebo nečistotu. Potřeby navíc sice pomalu, ale za to neúprosně postupně narůstají. Jedna interakce s kontraktem, tedy naplnění některé z potřeb virtuálního zvířátka, vyjde uživatele na 0,002 až 0,006 ETH, tedy převedeno na české koruny na něco mezi 128 až 430 Kč.


Autor: Sam Mason de Caires

Protože původní projekt představuje skutečně jen holý smart kontrakt bez grafické reprezentace, vytvořil pro něj UX inženýr Sam Mason de Caires (Senior Design Engineer ve společnosti Cloudflare) uživatelsky mnohem přívětivější webový frontend, který je k nahlédnutí na adrese wagmigotchi.pet

Celý kontrakt vypadá následovně:

contract Wagmipet {
    address _owner;
    bool _birthed;
    
    event CaretakerLoved(address indexed caretaker, uint256 indexed amount);
    
    uint256 lastFeedBlock;
    uint256 lastCleanBlock;
    uint256 lastPlayBlock;
    uint256 lastSleepBlock;
    
    uint8 internal hunger;
    uint8 internal uncleanliness;
    uint8 internal boredom;
    uint8 internal sleepiness;
    
    mapping (address => uint256) public love;
    
    modifier onlyOwner() {
        require(msg.sender == _owner);
        _;
    }
    
    constructor() {
        _owner = msg.sender;
        lastFeedBlock = block.number;
        lastCleanBlock = block.number;
        lastPlayBlock = block.number;
        lastSleepBlock = block.number;
        
        hunger = 0;
        uncleanliness = 0;
        boredom = 0;
        sleepiness = 0;
    }
    
    function addLove(address caretaker, uint256 amount) internal {
        love[caretaker] += amount;
        emit CaretakerLoved(caretaker, amount);
    }
    
    function feed() public {
        require(getAlive(), "no longer with us");
        require(getBoredom() < 80, "im too tired to eat");
        require(getUncleanliness() < 80, "im feeling too gross to eat");
        // require(getHunger() > 0, "i dont need to eat");
        
        lastFeedBlock = block.number;
        
        hunger = 0;
        boredom += 10;
        uncleanliness += 3;

        addLove(msg.sender, 1);
    }
    
    function clean() public {
        require(getAlive(), "no longer with us");
        require(getUncleanliness() > 0, "i dont need a bath");
        lastCleanBlock = block.number;
        
        uncleanliness = 0;
        
        addLove(msg.sender, 1);
    }
    
    function play() public {
        require(getAlive(), "no longer with us");
        require(getHunger() < 80, "im too hungry to play");
        require(getSleepiness() < 80, "im too sleepy to play");
        require(getUncleanliness() < 80, "im feeling too gross to play");
        // require(getBoredom() > 0, "i dont wanna play");
        
        lastPlayBlock = block.number;
        
        boredom = 0;
        hunger += 10;
        sleepiness += 10;
        uncleanliness += 5;
        
        addLove(msg.sender, 1);
    }
    
    function sleep() public {
        require(getAlive(), "no longer with us");
        require(getUncleanliness() < 80, "im feeling too gross to sleep");
        require(getSleepiness() > 0, "im not feeling sleepy");
        
        lastSleepBlock = block.number;
        
        sleepiness = 0;
        uncleanliness += 5;
        
        addLove(msg.sender, 1);
    }
    
    function getStatus() public view returns (string memory) {
        uint256 mostNeeded = 0;
        
        string[4] memory goodStatus = [
            "gm",
            "im feeling great",
            "all good",
            "i love u"
        ];
        
        string memory status = goodStatus[block.number % 4];
        
        uint256 _hunger = getHunger();
        uint256 _uncleanliness = getUncleanliness();
        uint256 _boredom = getBoredom();
        uint256 _sleepiness = getSleepiness();
        
        if (getAlive() == false) {
            return "no longer with us";
        }
        
        if (_hunger > 50 && _hunger > mostNeeded) {
            mostNeeded = _hunger;
            status = "im hungry";
        }
        
        if (_uncleanliness > 50 && _uncleanliness > mostNeeded) {
            mostNeeded = _uncleanliness;
            status = "i need a bath";
        }
        
        if (_boredom > 50 && _boredom > mostNeeded) {
            mostNeeded = _boredom;
            status = "im bored";
        }
        
        if (_sleepiness > 50 && _sleepiness > mostNeeded) {
            mostNeeded = _sleepiness;
            status = "im sleepy";
        }
        
        return status;
    }
    
    function getAlive() public view returns (bool) {
        return getHunger() < 101 && getUncleanliness() < 101 &&
            getBoredom() < 101 && getSleepiness() < 101;
    }
    
    function getHunger() public view returns (uint256) {
        return hunger + ((block.number - lastFeedBlock) / 50);
    }
    
    function getUncleanliness() public view returns (uint256) {
        return uncleanliness + ((block.number - lastCleanBlock) / 50);
    }
    
    function getBoredom() public view returns (uint256) {
        return boredom + ((block.number - lastPlayBlock) / 50);
    }
    
    function getSleepiness() public view returns (uint256) {
        return sleepiness + ((block.number - lastSleepBlock) / 50);
    }

Je na Ethereu prostor i pro nevýdělečné projekty?

Otázka do pranice zní, zda může kolektivně sdílený blockchainový virtuální tvor, který nepřináší nic jiného než výdaje a mikrodávku virtuální náklonnosti, dlouhodobě přežívat. A má takový projekt vůbec nějaký praktický smysl? 

Odpověď je jednoduchá: pokud jsou uživatelé ochotní nechat svým etherovým peněženkám pouštět žilou pro trochu virtuální satisfakce neexistujího tvora, pak evidentně ano. Když nic jiného, Hofmann zde podobně jako v případě Lootu posouvá hranice směrem, kterým zatím ostatní nenapadlo uvažovat. Projekt již teď inspiruje první následovníky na dalších smart kontrakt platformách, sám autor publikoval ještě WagmiPet kontrakt na blockchainu Polygon. 

Wagmigotchi samotné navíc není prvním pokusem o blockchainové tamagotchi. V březnu 2021 vydalo herní studio Pixelcraft DeFi hru Aavegotchi, která hráčům umožňuje starat se (přejmenovat, nakrmit, hladit nebo je dovybavit) o virtuální duchy „Aavegotchi“.  

KL22 hlasovani

Ty jsou ale koncipovány jako klasické NFT tokeny, a smyslem je tedy primárně sběratelství. V tom se hra nijak neliší od armády dalších NFT her. Hofmannův přístup je rozhodně originálnější a svou absencí důrazu na snahu vydělat na svých experimentech také sympatičtější. 

Otázkou tedy zůstává hlavně to, zda je Hofmann pionýr objevující nová dosud netušená území, nebo naopak někdo, kdo nám ukazuje slepé cesty vývoje.

Autor článku

Externí spolupracovník serveru Lupa.cz a expert na blockchain a kryptoměny. Jako šéfredaktor v minulosti vedl ADASTRA Business Intelligence Magazine a server ITbiz.cz. Dnes pracuje jako redaktor časopisu Forbes.