Norme de jeton non fongible ERC-721
Dernière modification: @DylanCONIN(opens in a new tab), 19 novembre 2023
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
ainsi, pour tout contrat ERC-721, la paire contract address, uint256 tokenId
doit être globalement unique. Cela dit, une dApp peut avoir un « convertisseur » qui utilisent le tokenld
comme entrée et affiche une image de quelque chose de cool, comme des zombies, des armes, des compétences ou des incroyables chatons !
Prérequis
Présentation
L'ERC-721 (pour "Ethereum Request for Comments 721") proposé 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(opens in a new tab) :
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);Afficher 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);Copier
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(opens in a new tab):
1pip install web3
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.to_checksum_address(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.keccak(text="Transfer(address,address,uint256)").hex()8384logs = w3.eth.get_logs({85 "fromBlock": w3.eth.block_number - 120,86 "address": w3.to_checksum_address(ck_token_addr),87 "topics": [event_signature]88})8990# Notes:91# - Increase the number of blocks up from 120 if no Transfer event is returned.92# - 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" argument95recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs]9697if recent_tx:98 kitty_id = recent_tx[0]['tokenId'] # Paste the "tokenId" here from the link above99 is_pregnant = ck_contract.functions.isPregnant(kitty_id).call()100 print(f"{name} [{symbol}] NFTs {kitty_id} is pregnant: {is_pregnant}")Afficher 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.keccak(text="Pregnant(address,uint256,uint256,uint256)").hex(),28 w3.keccak(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.get_logs({34 "fromBlock": w3.eth.block_number - 120,35 "address": w3.to_checksum_address(ck_token_addr),36 "topics": [ck_event_signatures[0]]37})3839recent_pregnants = [get_event_data(w3.codec, 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.get_logs({44 "fromBlock": w3.eth.block_number - 120,45 "address": w3.to_checksum_address(ck_token_addr),46 "topics": [ck_event_signatures[1]]47})4849recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] for log in birth_logs]Afficher toutCopier
NFT populaires
- Etherscan NFT Tracker(opens in a new tab) répertorie les NFT les plus importants sur Ethereum en termes de volume de transferts.
- CryptoKitties(opens in a new tab) est un jeu axé sur des créatures de collection adorables dont on peut faire l'élevage et que nous appelons CryptoKitties.
- Sorare(opens in a new tab) 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)(opens in a new tab) 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.
- POAP(opens in a new tab) fournit des NFT gratuits aux personnes qui assistent à des événements ou accomplissent des actions spécifiques. Les POAP sont libres de création et de distribution.
- Unstoppable Domains(opens in a new tab) 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(opens in a new tab) 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.
- Bored Ape Yacht Club(opens in a new tab) est une collection de 10 000 NFT uniques qui, en plus d'être une œuvre d'art remarquablement rare, agit en tant que jeton d’adhésion au club en fournissant aux membres des atouts et des avantages qui augmentent au fil du temps grâce aux efforts de la communauté.
Complément d'information
- EIP-721: ERC-721 Non-Fungible Token Standard(opens in a new tab)
- OpenZeppelin - ERC-721 Docs(opens in a new tab)
- OpenZeppelin - Implémentation ERC-721(opens in a new tab)
- API NFT d'Alchemy(opens in a new tab)