Хотите всегда оставаться в курсе событий? Подписывайтесь на @cryptochan и получайте новости в нашем Telegram канале.
×
Анатомия ERC721
Давайте попробуем разобраться в устройстве невзаимозаменяемых токенов на Эфириуме. Многие слышали об игре на блокчейне Ethereum CryptoKitties. Игра наделала шума в криптовалютном сообществе из-за своей чрезвычайно уникальной идеи и влияния на сеть Эфириума. CryptoKitties – игра, где можно покупать, продавать, обменивать и разводить цифровых котят. Их можно представить как «игрушки Beanie Babies, которые могут размножаться», в том смысле что каждый котик так или иначе уникален. Данная уникальность делает криптокотят востребованными коллекционными объектами, так как кого-то могут заинтересовать характеристики тех или иных котят и он может захотеть иметь их много. Но коллекционирование не ограничивается цифровыми товарами. Люди всегда что-то коллекционировали; это не новость. От монет до карточек с покемонами – люди любят коллекционировать. Это хобби, формирующееся в результате уникального интереса к редким предметам. Подобно тому как стоимость товара связана с его редкостью, стоимость коллекционного предмета для коллекционера связана с его редкостью среди других предметов. Редкие коллекционные предметы можно сымитировать с помощью токенов на Эфириуме, придерживающихся нового стандарта ERC721. Рабочее предложение Эфириума 721 (Ethereum Request for Comments 721, или ERC721) – это предложение об улучшении Эфириума, представленное Дитером Ширли в конце 2017 г. Это предложенный стандарт, который позволяет смарт-контрактам функционировать как торгуемые токены, подобно ERC20. Токены ERC721 уникальны тем, что они невзаимозаменяемы. Нечто (например, деньги или товар) считается взаимозаменяемым, если одну его часть или количество можно заменить другой равной частью или количеством при расчёте или погашении долга. Взаимозаменяемость – это, по сути, характеристика актива, или в данном случае токена, определяющая, могут ли объекты или количества того же или похожего типа полностью заменять друг друга в процессе обмена или использования. Например, за пятидолларовую купюру можно купить газировку в магазине.Она обладает стоимостью и может использоваться для покупки товаров, имеющих такую же или меньшую стоимость. Но если кто-то захочет купить газировку за бейсбольную карточку, владелец магазина её не примет. Почему владелец магазина не примет показанную выше карточку с Карлосом Сантаной, если она стоит $5, как и купюра? Потому что бейсбольная карточка и долларовая купюра обладают разными характеристиками, определяющими их стоимость для разных людей. Семилетний ребёнок может быть готов отдать за бейсбольную карточку $7, потому что ему нравится разноцветная картинка. Но владелец магазина не оценит её даже в $5, просто потому, что она не выпущена Федеральной резервной системой, как доллар. Уникальные свойства бейсбольной карточки и долларовой купюры лишают их взаимозаменяемости, потому что они по-разному оцениваются в зависимости от обмена и не всегда могут использоваться друг вместо друга. Если говорить о коллекционных предметах, то два предмета в коллекции не взаимозаменяемы, если они обладают разными характеристиками. Золотая монета не взаимозаменяема с медной монетой, потому что из-за разных характеристик они имеют разную ценность для коллекционеров. Токены ERC721 могут использоваться в любом обмене, но их стоимость – результат уникальности и редкости каждого токена. Стандарт определяет функции name, symbol, totalSupply, balanceOf, ownerOf, approve, takeOwnership, transfer, tokenOfOwnerByIndex и tokenMetadata. Он также определяет два события: Transfer и Approval. Примечание: Вот краткий пример объявления контракта ERC721: contract ERC721 { // ERC20 compatible functions function name() constant returns (string name); function symbol() constant returns (string symbol); function totalSupply() constant returns (uint256 totalSupply); function balanceOf(address _owner) constant returns (uint balance); // Functions that define ownership function ownerOf(uint256 _tokenId) constant returns (address owner); function approve(address _to, uint256 _tokenId); function takeOwnership(uint256 _tokenId); function transfer(address _to, uint256 _tokenId); function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId); // Token metadata function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl); // Events event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); } Ниже приведён обзор каждого поля контракта. ВНИМАНИЕ: Приведённый здесь код имеет исключительно образовательное предназначение и не был протестирован. Пожалуйста, не используйте его в реальных приложениях! ERC20-совместимые функции ERC721 определяет несколько функций, дающих ему некоторую совместимость со стандартом токенов ERC20. Это нужно, чтобы существующим кошелькам было проще отображать базовую информацию о токене. Эти функции позволяют смарт-контракту, соответствующему данному стандарту, функционировать как обычная криптовалюта вроде биткойна или эфира. Для этого определяются функции, позволяющие пользователям выполнять такие действия, как пересылка токенов и проверка баланса счёта. name Данная функция используется для сообщения внешним контрактам и приложениям названия токена. Например, функция может быть реализована следующим образом: contract MyNFT { function name() constant returns (string name){ return "My Non-Fungible Token"; } } symbol Эта функция также обеспечивает совместимость со стандартом токенов ERC20. Она сообщает внешним программам краткое название, или символ, токена. contract MyNFT { function symbol() constant returns (string symbol){ return "MNFT"; } } totalSupply Данная функция задаёт общее количество монет, доступных в блокчейне. Предложение не обязательно должно быть константой. contract MyNFT { // Это число может быть произвольным uint256 private totalSupply = 1000000000; function totalSupply() constant returns (uint256 supply){ return totalSupply; } } balanceOf Эта функция используется, чтобы найти количество токенов, принадлежащих конкретному адресу. contract MyNFT { mapping(address => uint) private balances; function balanceOf(address _owner) constant returns (uint balance) { return balances[_owner]; } } Функции владения Данные функции определяют, как контракт будет рассматривать права собственности на токены и как эти права могут передаваться. Наиболее значимые среди этих функций – takeOwnership и transfer, действующие соответственно как функции снятия и пересылки и являющиеся важными для возможности перевода токенов между пользователями. ownerOf Эта функция определяет адрес владельца токена. Поскольку токены ERC721 невзаимозаменяемые и, следовательно, уникальные, в блокчейне им присвоены уникальные идентификаторы. Определить владельца токена можно с помощью его ID. contract MyNFT { mapping(uint256 => address) private tokenOwners; mapping(uint256 => bool) private tokenExists; function ownerOf(uint256 _tokenId) constant returns (address owner) { require(tokenExists[_tokenId]); return tokenOwners[_tokenId]; } } approve Эта функция одобряет разрешение другому субъекту переводить токен от имени владельца. Например, если Алиса владеет 1 MyNFT, она может вызвать функцию approve для своего друга Боба. После успешного вызова Боб может позже распоряжаться токеном от имени Алисы или стать его владельцем. Больше о передаче прав собственности можно узнать из описания функций takeOwnership и transfer. contract MyNFT { mapping(address => mapping (address => uint256)) allowed; function approve(address _to, uint256 _tokenId){ require(msg.sender == ownerOf(_tokenId)); require(msg.sender != _to); allowed[msg.sender][_to] = _tokenId; Approval(msg.sender, _to, _tokenId); } } takeOwnership Эта функция действует как функция снятия, поскольку другая сторона может вызвать её, чтобы снять токены со счёта пользователя. Таким образом, takeOwnership может использоваться, когда пользователь получил одобрение (approve) на владение определённым количеством токенов и желает снять эти токены со счёта другого пользователя. contract MyNFT { function takeOwnership(uint256 _tokenId){ require(tokenExists[_tokenId]); address oldOwner = ownerOf(_tokenId); address newOwner = msg.sender; require(newOwner != oldOwner); require(allowed[oldOwner][newOwner] == _tokenId); balances[oldOwner] -= 1; tokenOwners[_tokenId] = newOwner; balances[newOwner] += 1; Transfer(oldOwner, newOwner, _tokenId); } } transfer Данная функция – ещё один способ передачи токенов. transfer позволяет владельцу токена переслать его другому пользователю, подобно обычной криптовалюте. Однако перевод может быть инициирован, только если принимающий счёт раньше получил от отправляющего счёта одобрение на владение токеном. contract MyNFT { mapping(address => mapping(uint256 => uint256)) private ownerTokens; function removeFromTokenList(address owner, uint256 _tokenId) private { for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ ownerTokens[owner][i] = 0; } } function transfer(address _to, uint256 _tokenId){ address currentOwner = msg.sender; address newOwner = _to; require(tokenExists[_tokenId]); require(currentOwner == ownerOf(_tokenId)); require(currentOwner != newOwner); require(newOwner != address(0)); removeFromTokenList(_tokenId); balances[oldOwner] -= 1; tokenOwners[_tokenId] = newOwner; balances[newOwner] += 1; Transfer(oldOwner, newOwner, _tokenId); } } tokenOfOwnerByIndex (опционально – рекомендуется) Каждый владелец невзаимозаменяемых токенов может одновременно владеть более чем одним токеном. Но так как каждому токену присвоен уникальный идентификатор, может быть сложно отслеживать отдельные токены, принадлежащие пользователю. Поэтому контракт ведёт учёт идентификаторов всех токенов, принадлежащих каждому пользователю. Следовательно, каждый отдельный токен можно найти по его индексу в списке (массиве) токенов, принадлежащих пользователю. tokenOfOwnerByIndex позволяет найти токен данным методом. contract MyNFT { mapping(address => mapping(uint256 => uint256)) private ownerTokens; function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId){ return ownerTokens[_owner][_index]; } } Функция метаданных Как уже говорилось, невзаимозаменяемые объекты являются таковыми благодаря своей уникальной комбинации свойств. Доллар и бейсбольная карточка не взаимозаменяемые, потому что они обладают разными характеристиками. Но хранить в блокчейне данные, описывающие определяющие характеристики каждого токена, чрезвычайно дорого и не рекомендуется. Вместо этого можно хранить в блокчейне ссылки на каждый атрибут токена, такие как IPFS-хеш или HTTP(S)-адрес, чтобы внешняя программа могла найти больше информации о токене с помощью логических операций. Такие ссылки – это данные о данных, или метаданные. tokenMetadata (опционально – рекомендуется) Эта функция позволяет обнаружить метаданные токена, или ссылку на его данные. contract MyNFT { mapping(uint256 => string) tokenLinks; function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl) { return tokenLinks[_tokenId]; } } События События запускаются, когда контракт их вызывает, и после запуска транслируются любым отслеживающим программам. Внешние программы отслеживают события блокчейна, чтобы после запуска события выполнить логические операции, используя предоставляемую событием информацию. Стандарт ERC721 определяет два следующих события. Transfer Это событие срабатывает, когда токен меняет владельца. Оно транслируется, когда право собственности на токен переходит от одного пользователя другому. Оно описывает, какой счёт отправил токен, какой счёт его получил и какой токен (по ID) был передан. contract MyNFT { event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); } Approval Это событие запускается, когда один пользователь одобряет передачу прав на токен другому пользователю (т. е. когда выполняется approve). Оно описывает, какому счёту сейчас принадлежит токен, какому счёту разрешено заполучить токен в будущем и для какого токена (по ID) одобрена передача права собственности. contract MyNFT { event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); } Исходный код моей реализации стандарта ERC721 можно найти здесь. Подобно ERC20, предложение стандарта ERC721 открыло возможности использовать смарт-контракты как невзаимозаменяемые объекты. Как можно увидеть на примере таких приложений, как CryptoKitties, Decentraland, CryptoPunks и многие другие, невзаимозаменяемые токены оказались очень востребованными продуктами. Даже WikiLeaks владеет несколькими высоко ценящимися криптокотятами! Но главное, этот стандарт ещё больше расширит криптовалютную экономику и будет способствовать её дальнейшему развитию. Источник Поделиться ссылкой:Нажмите, чтобы поделиться в vkontakte (Открывается в новом окне)Нажмите, чтобы поделиться в Telegram (Открывается в новом окне)Нажмите, чтобы поделиться в Instagram (Открывается в новом окне)Нажмите, чтобы поделиться на Twitter (Открывается в новом окне)Нажмите здесь, чтобы поделиться контентом на Facebook. (Открывается в новом окне)Нажмите, чтобы поделиться на LinkedIn (Открывается в новом окне)Нажмите, чтобы поделиться на Reddit (Открывается в новом окне)ЕщёНажмите, чтобы поделиться записями на Tumblr (Открывается в новом окне)Послать это другу (Открывается в новом окне)Нажмите для печати (Открывается в новом окне)Нажмите, чтобы поделиться в Google+ (Открывается в новом окне)Нажмите, чтобы поделиться записями на Pinterest (Открывается в новом окне)Нажмите, чтобы поделиться записями на Pocket (Открывается в новом окне) Related