Norme de jeton non fongible ERC-721
Introduction
Qu'est-ce qu'un jeton non fongible (NFT) ?
Un NFT est utilisé pour identifier quelque chose ou quelqu'un d'une façon unique. Ce type de jeton est parfait pour une utilisation sur les plateformes proposant des objets de collection, clés d'accès, billets de loterie, sièges numérotés pour concerts et matchs sportifs, etc. Ce type spécial de jeton ayant des possibilités incroyables, il mérite donc une norme adéquate, comme l'ERC-721.
Qu'est-ce que l'ERC-721 ?
L'ERC-721 introduit une norme pour les NFT. En d'autres termes, ce type de jeton est unique et peut avoir une valeur différente de celle d'un autre jeton du même contrat intelligent, peut-être en raison de son âge, de sa rareté ou du visuel qui lui est associé. Visuel ? Vous avez dit visuel ?
Oui ! Tous les NFT ont une variable uint256
appelée tokenId
. Pour tout contrat ERC-721, la paire address, uint256 tokenId
du contrat doit être globalement unique. Une DApp peut avoir un "convertisseur" qui utilise le tokenId
comme entrée et affiche une image de quelque chose de cool, comme des zombies, des armes, des compétences ou de superbes chats !
Prérequis
Présentation
La demande de commentaires ERC-721, proposée par William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs en janvier 2018, est une norme de jeton non fongible qui implémente une API pour les jetons des contrats intelligents.
Elle fournit des fonctionnalités permettant de transférer des jetons d'un compte à un autre, ou d'obtenir le solde actuel d'un compte en jetons, le nom du propriétaire d'un jeton spécifique et le nombre total de jetons disponibles sur le réseau. En plus de celles-ci, il en existe d'autres pour, par exemple, approuver que des jetons provenant d'un compte soient déplacés par un compte tiers.
Si un contrat intelligent implémente les méthodes et les événements suivants, il peut être nommé Contrat de jeton non fongible ERC-721 et, une fois déployé, sera responsable d'effectuer un suivi des jetons créés sur Ethereum.
De EIP-721 :
Méthodes
1 function balanceOf(address _owner) external view returns (uint256);2 function ownerOf(uint256 _tokenId) external view returns (address);3 function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;4 function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;5 function transferFrom(address _from, address _to, uint256 _tokenId) external payable;6 function approve(address _approved, uint256 _tokenId) external payable;7 function setApprovalForAll(address _operator, bool _approved) external;8 function getApproved(uint256 _tokenId) external view returns (address);9 function isApprovedForAll(address _owner, address _operator) external view returns (bool);10Afficher toutCopier
Événements
1 event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);2 event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);3 event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);4Copier
Exemples
Voyons comment une norme peut être si importante pour nous faciliter le contrôle de tout contrat de jeton ERC-721 sur Ethereum. Nous avons juste besoin de l'interface binaire-programme (ABI) du contrat pour créer une interface à n'importe quel jeton ERC-721. Comme vous pouvez le voir ci-dessous, nous utiliserons une ABI simplifiée, pour en faire un exemple de faible friction.
Exemple Web3.py
Pour commencer, assurez-vous d'avoir installé la bibliothèque Python Web3.py:
1$ pip install web32
1from web3 import Web32from web3.utils.events import get_event_data345w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))67ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # CryptoKitties Contract89acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # CryptoKitties Sales Auction1011# This is a simplified Contract Application Binary Interface (ABI) of an ERC-721 NFT Contract.12# It will expose only the methods: balanceOf(address), name(), ownerOf(tokenId), symbol(), totalSupply()13simplified_abi = [14 {15 'inputs': [{'internalType': 'address', 'name': 'owner', 'type': 'address'}],16 'name': 'balanceOf',17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],18 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True19 },20 {21 'inputs': [],22 'name': 'name',23 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],24 'stateMutability': 'view', 'type': 'function', 'constant': True25 },26 {27 'inputs': [{'internalType': 'uint256', 'name': 'tokenId', 'type': 'uint256'}],28 'name': 'ownerOf',29 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}],30 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True31 },32 {33 'inputs': [],34 'name': 'symbol',35 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],36 'stateMutability': 'view', 'type': 'function', 'constant': True37 },38 {39 'inputs': [],40 'name': 'totalSupply',41 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],42 'stateMutability': 'view', 'type': 'function', 'constant': True43 },44]4546ck_extra_abi = [47 {48 'inputs': [],49 'name': 'pregnantKitties',50 'outputs': [{'name': '', 'type': 'uint256'}],51 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True52 },53 {54 'inputs': [{'name': '_kittyId', 'type': 'uint256'}],55 'name': 'isPregnant',56 'outputs': [{'name': '', 'type': 'bool'}],57 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True58 }59]6061ck_contract = w3.eth.contract(address=w3.toChecksumAddress(ck_token_addr), abi=simplified_abi+ck_extra_abi)62name = ck_contract.functions.name().call()63symbol = ck_contract.functions.symbol().call()64kitties_auctions = ck_contract.functions.balanceOf(acc_address).call()65print(f"{name} [{symbol}] NFTs in Auctions: {kitties_auctions}")6667pregnant_kitties = ck_contract.functions.pregnantKitties().call()68print(f"{name} [{symbol}] NFTs Pregnants: {pregnant_kitties}")6970# Using the Transfer Event ABI to get info about transferred Kitties.71tx_event_abi = {72 'anonymous': False,73 'inputs': [74 {'indexed': False, 'name': 'from', 'type': 'address'},75 {'indexed': False, 'name': 'to', 'type': 'address'},76 {'indexed': False, 'name': 'tokenId', 'type': 'uint256'}],77 'name': 'Transfer',78 'type': 'event'79}8081# We need the event's signature to filter the logs82event_signature = w3.sha3(text="Transfer(address,address,uint256)").hex()8384logs = w3.eth.getLogs({85 "fromBlock": w3.eth.blockNumber - 120,86 "address": w3.toChecksumAddress(ck_token_addr),87 "topics": [event_signature]88})8990# Notes:91# - 120 blocks is the max range for CloudFlare Provider92# - If you didn't find any Transfer event you can also try to get a tokenId at:93# https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events94# Click to expand the event's logs and copy its "tokenId" argument9596recent_tx = [get_event_data(tx_event_abi, log)["args"] for log in logs]9798kitty_id = recent_tx[0]['tokenId'] # Paste the "tokenId" here from the link above99is_pregnant = ck_contract.functions.isPregnant(kitty_id).call()100print(f"{name} [{symbol}] NFTs {kitty_id} is pregnant: {is_pregnant}")101Afficher toutCopier
Le contrat CryptoKitties comporte des événements intéressants en dehors des événements standards.
Vérifions deux d'entre eux, Pregnant
et Birth
.
1# Using the Pregnant and Birth Events ABI to get info about new Kitties.2ck_extra_events_abi = [3 {4 'anonymous': False,5 'inputs': [6 {'indexed': False, 'name': 'owner', 'type': 'address'},7 {'indexed': False, 'name': 'matronId', 'type': 'uint256'},8 {'indexed': False, 'name': 'sireId', 'type': 'uint256'},9 {'indexed': False, 'name': 'cooldownEndBlock', 'type': 'uint256'}],10 'name': 'Pregnant',11 'type': 'event'12 },13 {14 'anonymous': False,15 'inputs': [16 {'indexed': False, 'name': 'owner', 'type': 'address'},17 {'indexed': False, 'name': 'kittyId', 'type': 'uint256'},18 {'indexed': False, 'name': 'matronId', 'type': 'uint256'},19 {'indexed': False, 'name': 'sireId', 'type': 'uint256'},20 {'indexed': False, 'name': 'genes', 'type': 'uint256'}],21 'name': 'Birth',22 'type': 'event'23 }]2425# We need the event's signature to filter the logs26ck_event_signatures = [27 w3.sha3(text="Pregnant(address,uint256,uint256,uint256)").hex(),28 w3.sha3(text="Birth(address,uint256,uint256,uint256,uint256)").hex(),29]3031# Here is a Pregnant Event:32# - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog33pregnant_logs = w3.eth.getLogs({34 "fromBlock": w3.eth.blockNumber - 120,35 "address": w3.toChecksumAddress(ck_token_addr),36 "topics": [ck_extra_events_abi[0]]37})3839recent_pregnants = [get_event_data(ck_extra_events_abi[0], log)["args"] for log in pregnant_logs]4041# Here is a Birth Event:42# - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a43birth_logs = w3.eth.getLogs({44 "fromBlock": w3.eth.blockNumber - 120,45 "address": w3.toChecksumAddress(ck_token_addr),46 "topics": [ck_extra_events_abi[1]]47})4849recent_births = [get_event_data(ck_extra_events_abi[1], log)["args"] for log in birth_logs]50Afficher toutCopier
NFT populaires
- Etherscan NFT Tracker répertorie les NFT les plus importants sur Ethereum en termes de volume de transferts.
- CryptoKitties est un jeu axé sur des créatures de collection adorables dont on peut faire l'élevage et que nous appelons CryptoKitties.
- Sorare est un jeu de football mondial où vous pouvez collectionner des objets en édition limitée, gérer vos équipes et concourir pour gagner des prix.
- Ethereum Name Service (ENS) offre un moyen sécurisé et décentralisé d'adresser des ressources à la fois sur et hors de la blockchain en utilisant des noms simples et lisibles.
- Unstoppable Domains est une société basée à San Francisco, qui construit des domaines sur des blockchains. Les domaines de blockchains remplacent les adresses des cryptomonnaies par des noms lisibles et peuvent être utilisés pour activer des sites Web résistants à la censure.
- Gods Unchained Cards est un jeu de cartes à collectionner (JCC) de la blockchain Ethereum, qui utilise des NFT pour apporter une vraie propriété aux actifs en jeu.
Complément d'information
- EIP-721: ERC-721 Non-Fungible Token Standard
- OpenZeppelin - ERC-721 Docs
- OpenZeppelin - Implémentation ERC-721