Разбор контракта Kongz

Это первая часть серии статей о разборе контракта Cyberkongz NFT.

Cyberkongz — это генеративный НФТ, который имеет коллекцию из 1000 уникальных и случайно генерируемых 2D пиксельных горилл (известных как kongz), торгуемых на открытом морском рынке. Эти первые 1000 отчеканенных конгзов известны как genesis kongz, которые имеют возможность размножаться друг с другом, чтобы расширить новый набор конгзов, известный как baby kongz.

Эти пикселированные конгзы размером 34×34 не просто потрясающе подходят для использования в качестве фотографии профиля на любой социальной платформе, но также имеют огромное сообщество и много полезного вокруг них!

При размножении двух генезисных конгов рождается детеныш конга, а также 3D воксельный конг, который может быть использован в качестве социального аватара в метавселенной.

На странице «О сайте cyberkongz» дается подробное объяснение всей экосистемы токенов и токеномики.

Мне просто нравится, как им удается изысканно сочетать свои NFT с DeFi и metaverse.

Контракт Kongz

Важно отметить, что все функции, описанные здесь, относятся к контракту kongz. Любое упоминание функции, которая не входит в контракт, будет отмечено.

Каждый конг проходит через 2 основные фазы роста

Инкубация: Есть два основных места, где конг проходит инкубацию в контракте. Первое — во время начальной чеканки генезисных конгов в конструкторе, второе — после выведения нового конга.

Эволюция: Это часть, в которой конг развивается; это означает, что конгу присваивается новый ген, который имеет другое значение.

Контракт kongz в основном содержит 5 ключевых функций

  • Возможность чеканить новых конгов.
  • Разведение между генезисными конгзами
  • Восхождение конгов
  • Возможность эволюции конгза
  • Изменение имени и биографии конгза

Конструктор

В начале контракта владелец контракта начинает с того, что добывает для себя 3 токена генезиса, как показано на фрагменте ниже

contract Kongz {
... 

// data structure representing each kong
struct Kong {
        uint256 genes; // the value 0 implies that it's a genesis kong
        uint256 bornAt; // when the kong got minted
    }

constructor (
string memory _name, 
string memory _symbol, 
string[] memory _names, 
uint256[] memory _ids
) public ERC721Namable(_name, _symbol, _names, _ids) {
        // cyberkongz uses heroku to host their metadata
        _setBaseURI("https://kongz.herokuapp.com/api/metadata/");
        // owner minting 3 kongz for themselves.
        _mint(msg.sender, 1001);
        _mint(msg.sender, 1002);
        _mint(msg.sender, 1003);
        // saving state of newly minted kongz
        kongz[1001] = Kong(0, block.timestamp);
        kongz[1002] = Kong(0, block.timestamp);
        kongz[1003] = Kong(0, block.timestamp);
        // emiting events for newly minted kongz.
        emit KongIncubated(1001, 0, 0);
        emit KongIncubated(1002, 0, 0);
        emit KongIncubated(1003, 0, 0);
        // handling the total supply of kongz.
        bebeCount = 3;
    }

...
}
Вход в полноэкранный режим Выход из полноэкранного режима

Выращивание конгза

Эта функция отвечает за создание и вынашивание детенышей конгза при условии, что у владельца есть два генезисных конгза, которые будут служить в качестве отца и матери.

Более подробное описание добавлено в комментариях.

function breed(
uint256 _sire, 
uint256 _matron
) external {

        // confirm that msg.sender owns both NFT's serving as sire and matron
        require(ownerOf(_sire) == msg.sender && ownerOf(_matron) == msg.sender);

        // classified breedManager attempts to breed kongz if breed is successful 
        // then function continues execution else it terminates.
        require(breedManager.tryBreed(_sire, _matron));

        // the equavalent amount (600 BANANA) required for breeding gets burned from
        // msg.sender balance.
        yieldToken.burn(msg.sender, BREED_PRICE);

        // update token supply after birth of baby kong
        bebeCount++;

        // create ID for new baby kong
        uint256 id = 1000 + bebeCount; // 1004

        // nice! Baby kong is also from gen 0
        kongz[id] = Kong(0, block.timestamp); // should confirm this from team.

        // msg.sender is a proud owner of a baby kong
        _mint(msg.sender, id);

        // msg.sender announces to the world his new baby kongz alongside the parents.
        emit KongIncubated(id, _matron, _sire);
    }
Войти в полноэкранный режим Выход из полноэкранного режима

Заметные изменения

  • Было сожжено 600 БАНАНОВ для того, чтобы произошел процесс размножения.
  • Обновлен запас жетонов
  • Малыш Конг добавлен в реестр kongz с новым сгенерированным идентификатором.
  • Малыш-конг наконец-то отчеканен и назначен своим новым владельцем (msg.sender)
  • Малыш-конг инкубируется

Эволюция kongz

После инкубации детеныша конга остается последнее, что необходимо сделать для его полного перехода — это эволюционировать. Эта функция обрабатывает процесс эволюции малыша конга, передавая его ID в качестве параметра методу tryEvolve внутри breedManager (который держится в секрете от всего мира), который возвращает новый ген для конга.

// @param _tokenId uint256 is the Id of kong to evolve
function evolve(
uint256 _tokenId
) external {
        require(ownerOf(_tokenId) == msg.sender);
        Kong storage kong = kongz[_tokenId];

        // kong must have a gene of 0 before it can be evolved.
        require(kong.genes == 0);

        // breedmanger tries to evolve the kong at the given tokenId.
        uint256 genes = breedManager.tryEvolve(_tokenId);

        kong.genes = genes;

        emit KongBorn(_tokenId, genes);
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Предположения: Поскольку у меня нет возможности увидеть, что именно происходит внутри метода breedManager.tryEvolve, я предполагаю, что метод использует tokenId для создания нового гена, который будет переназначен развивающемуся конгу.

То, в чем я все еще не уверен: Я все еще не до конца понимаю, что происходит после изменения гена конга после его эволюции. Получает ли он какую-то особую полезность или что-то еще? Пожалуйста, дайте мне знать, если у вас есть лучшее понимание этой функции.

Восходящий конгз

Поскольку первое поколение kongz было создано и хранилось непосредственно на Opensea, команда cyberkongz решила перевести все свои токены с Opensea на собственные смарт-контракты. Миграция токенов, созданных и хранящихся непосредственно на Opensea, на смарт-контракт известна как — восходящая миграция

function ascend(
uint256 _tokenId,
uint256 _genes, 
bytes calldata _sig
) external {

        // confirms that the tokenId conforms to Opensea's ID format (REF 1)
        // Opensea ID format -> 73424079983647210902572285069973579475843508985221180214989722260978404425729
        require(isValidKong(_tokenId), "Not valid Kong");

        // extracts currentId format from opensea tokenFormat (REF 2)
        uint256 id = returnCorrectId(_tokenId);

        require(keccak256(abi.encodePacked(id, _genes)).toEthSignedMessageHash().recover(_sig) == SIGNER, "Sig not valid");

        kongz[id] = Kong(_genes, block.timestamp);
        _mint(msg.sender, id);
        OPENSEA_STORE.safeTransferFrom(msg.sender, burn, _tokenId, 1, "");
        yieldToken.updateRewardOnMint(msg.sender, 1);
        balanceOG[msg.sender]++;
        emit KongAscended(id, _genes);
    }
Войти в полноэкранный режим Выход из полноэкранного режима

REF1 — isValidKong: isValidKong — это служебная функция, используемая для проверки соответствия идентификатора токена kong формату идентификатора Opeansea. Поскольку объяснение этого формата выходит за рамки данной статьи, я оставлю здесь пост, который объясняет его правильно.

function isValidKong(uint256 _id) pure internal returns(bool) {
        // making sure the ID fits the opensea format:
        // first 20 bytes are the maker address
        // next 7 bytes are the nft ID
        // last 5 bytes the value associated to the ID, here will always be equal to 1
        // There will only be 1000 kongz, we can fix boundaries and remove 5 ids that dont match kongz
        if (_id >> 96 != 0x000000000000000000000000a2548e7ad6cee01eeb19d49bedb359aea3d8ad1d)
            return false;
        if (_id & 0x000000000000000000000000000000000000000000000000000000ffffffffff != 1)
            return false;
        uint256 id = (_id & 0x0000000000000000000000000000000000000000ffffffffffffff0000000000) >> 40;
        if (id > 1005 || id == 262 || id == 197 || id == 75 || id == 34 || id == 18 || id == 0)
            return false;
        return true;
    }
Вход в полноэкранный режим Выход из полноэкранного режима

REF2 — returnCorrectId: Эта функция отвечает за получение tokenId в формате Id от Opensea и извлечение из него только tokenId. Если эта функция вас смущает, ознакомьтесь с этим постом на Medium, где прекрасно объясняется формат ID Opensea.

function returnCorrectId(uint256 _id) pure internal returns(uint256) {
        _id = (_id & 0x0000000000000000000000000000000000000000ffffffffffffff0000000000) >> 40;
        if (_id > 262)
            return _id - 5;
        else if (_id > 197)
            return _id - 4;
        else if (_id > 75)
            return _id - 3;
        else if (_id > 34)
            return _id - 2;
        else if (_id > 18)
            return _id - 1;
        else
            return _id;
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Изменение имени и биографии kongz

Cyberkongz — это действительно первый проект NFT, который я лично видел и который позволяет владельцам изменять имя и биографию NFT, давая им свою собственную уникальную историю. Тем не менее, эти возможности также приходят ценой нескольких БАНАНОВ, как мы скоро увидим.

Фактическая реализация контрактов changeName и changeBio находится в другом контракте под названием ERC721Namable, который был унаследован от контракта kongz.

function changeName(uint256 tokenId, string memory newName) public override {
        // msg.sender pays the cost of changing the name by burning the equivalent
      // amount of BANANAS required (300 BANANAS)
        yieldToken.burn(msg.sender, nameChangePrice);
        super.changeName(tokenId, newName);
    }

    function changeBio(uint256 tokenId, string memory _bio) public override {
        // msg.sender pays the cost of changing the bio by burning the equivalent
      // amount of BANANAS required (100 BANANAS)
        yieldToken.burn(msg.sender, BIO_CHANGE_PRICE);
        super.changeBio(tokenId, _bio);
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Дополнительная информация

Контракт ERC721Namable довольно прост для понимания, потому что он существует только для того, чтобы решать функциональные задачи по изменению имен и биографии ваших токенов Kongz NFT.

Вы можете ознакомиться с контрактом здесь, который начинается со строк 1872 — 1920

Далее

В следующей части серии мы собираемся изучить контракт YieldToken (BANANA), который является токеном ERC20 в качестве газа для расширения функциональных возможностей и вознаграждения держателей токенов.

Этот контракт показывает, как Cyberkongz внедрила DEFi в свои NFT.

Заключительные мысли

Изначально я писал этот разбор для себя, поэтому, пожалуйста, дайте мне знать, что вы думаете об этом стиле разбора. Какие вещи я упустил и как их можно улучшить?

Несмотря на то, что это мой первый пост, пожалуйста, не сдерживайте себя. Спасибо

Оцените статью
devanswers.ru
Добавить комментарий