Preskoči na glavno vsebino
Change page

ERC-721 standard za nezamenljive žetone

Nazadnje urejeno: @PeterKecman(opens in a new tab), 19. november 2023

Uvod

Kaj je nezamenljiv žeton?

Nezamenljiv žeton (NFT) se uporablja za identifikacijo nečesa oz. nekoga na edinstven način. Ta tip žetona je popoln za uporabo na platformah, ki ponujajo zbirateljske predmete, ključe za dostop, loterijske srečke, oštevilčene sedeže za koncerte in športne tekme itd. Ta posebni tip žetona ima izjemne možnosti, zato si zasluži lasten standard. ERC-721 je namenjen točno temu!

Kaj je ERC-721?

ERC-721 predstavlja standard za NFT-je. Z drugimi besedami: ta tip žetona je edinstven in ima lahko različno vrednost glede na drug žeton iz iste pametne pogodbe, morda zaradi svoje starosti, redkosti ali celo nečesa drugega, kot je njegov videz. Počakajte, videz?

Da! Vsi NFT-ji imajo spremenljivko uint256, ki se imenuje tokenId, tako da morata biti za katerokoli pogodbo ERC-721 naslov pogodbe, uint256 tokenId globalno edinstvena. Glede na to ima lahko dapp "pretvornik", ki uporablja tokenId kot vnos in tako izda sliko nečesa zanimivega, kot so zombiji, orožje, vrline ali izjemni mucki!

Predpogoji

  • Računi
  • Pametne pogodbe
  • Standardi za žetone

Jedro

ERC-721 (Zahteva Ethereum za komentarje 721), ki so ga januarja 2018 predlagali William Entriken, Dieter Shirley, Jacob Evans in Nastassia Sachs, je standard za nezamenljive žetone, ki implementira API za žetone znotraj pametnih pogodb.

Zagotavlja funkcionalnosti, kot so prenos žetonov z enega računa na drugega, prejem trenutnega stanja žetonov določenega računa in tudi prejem skupne količine žetonov, ki je na voljo v omrežju. Poleg tega ima tudi nekaj drugih funkcionalnosti, kot je potrditev porabe določene količine žetonov z enega računa s strani računa tretje osebe.

Če pametna pogodba implementira naslednje metode in dogodke, se lahko imenuje pogodba nezamenljivega žetona ERC-721. Ko je enkrat uveljavljena, bo odgovorna za sledenje ustvarjenih žetonov na Ethereumu.

Od EIP-721(opens in a new tab):

Metode

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);
Prikaži vse
Kopiraj

Dogodki

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);
Kopiraj

Primeri

Oglejmo si, zakaj je standard tako pomemben za to, da poenostavi pregled katerekoli pogodbe žetona ERC-721 na Ethereumu. Za ustvarjanje vmesnika za katerikoli žeton ERC-721 potrebujemo le binarni vmesnik pogodbene aplikacije (ABI). Kot lahko vidite spodaj, bomo uporabili poenostavljen ABI, da bi ustvarili primer z nizkim trenjem.

Primer Web3.py

Najprej se prepričajte, da ste namestili knjižnico Web3.py(opens in a new tab) Python:

pip install web3
1from web3 import Web3
2from web3._utils.events import get_event_data
3
4
5w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))
6
7ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # CryptoKitties Contract
8
9acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # CryptoKitties Sales Auction
10
11# 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': True
19 },
20 {
21 'inputs': [],
22 'name': 'name',
23 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],
24 'stateMutability': 'view', 'type': 'function', 'constant': True
25 },
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': True
31 },
32 {
33 'inputs': [],
34 'name': 'symbol',
35 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],
36 'stateMutability': 'view', 'type': 'function', 'constant': True
37 },
38 {
39 'inputs': [],
40 'name': 'totalSupply',
41 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],
42 'stateMutability': 'view', 'type': 'function', 'constant': True
43 },
44]
45
46ck_extra_abi = [
47 {
48 'inputs': [],
49 'name': 'pregnantKitties',
50 'outputs': [{'name': '', 'type': 'uint256'}],
51 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
52 },
53 {
54 'inputs': [{'name': '_kittyId', 'type': 'uint256'}],
55 'name': 'isPregnant',
56 'outputs': [{'name': '', 'type': 'bool'}],
57 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
58 }
59]
60
61ck_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}")
66
67pregnant_kitties = ck_contract.functions.pregnantKitties().call()
68print(f"{name} [{symbol}] NFTs Pregnants: {pregnant_kitties}")
69
70# 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}
80
81# We need the event's signature to filter the logs
82event_signature = w3.sha3(text="Transfer(address,address,uint256)").hex()
83
84logs = w3.eth.getLogs({
85 "fromBlock": w3.eth.blockNumber - 120,
86 "address": w3.toChecksumAddress(ck_token_addr),
87 "topics": [event_signature]
88})
89
90# Notes:
91# - 120 blocks is the max range for CloudFlare Provider
92# - If you didn't find any Transfer event you can also try to get a tokenId at:
93# https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events
94# Click to expand the event's logs and copy its "tokenId" argument
95
96recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs]
97
98kitty_id = recent_tx[0]['tokenId'] # Paste the "tokenId" here from the link above
99is_pregnant = ck_contract.functions.isPregnant(kitty_id).call()
100print(f"{name} [{symbol}] NFTs {kitty_id} is pregnant: {is_pregnant}")
Prikaži vse
Kopiraj

Pogodba CryptoKitties ima poleg standardnih tudi nekaj drugih zanimivih dogodkov.

Oglejmo si dva od njih: Nosečnost in Rojstvo.

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 }]
24
25# We need the event's signature to filter the logs
26ck_event_signatures = [
27 w3.sha3(text="Pregnant(address,uint256,uint256,uint256)").hex(),
28 w3.sha3(text="Birth(address,uint256,uint256,uint256,uint256)").hex(),
29]
30
31# Here is a Pregnant Event:
32# - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog
33pregnant_logs = w3.eth.getLogs({
34 "fromBlock": w3.eth.blockNumber - 120,
35 "address": w3.toChecksumAddress(ck_token_addr),
36 "topics": [ck_event_signatures[0]]
37})
38
39recent_pregnants = [get_event_data(w3.codec, ck_extra_events_abi[0], log)["args"] for log in pregnant_logs]
40
41# Here is a Birth Event:
42# - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a
43birth_logs = w3.eth.getLogs({
44 "fromBlock": w3.eth.blockNumber - 120,
45 "address": w3.toChecksumAddress(ck_token_addr),
46 "topics": [ck_event_signatures[1]]
47})
48
49recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] for log in birth_logs]
Prikaži vse
Kopiraj

Nadaljnje branje

Je bil ta članek uporaben?