Ruka kwenda kwenye maudhui makuu

Mwongozo wa Mkataba wa ERC-721 wa Vyper

Vyper
erc-721
Python
Mwanzo
Ori Pomerantz
1 Aprili 2021
18 soma ndani ya dakika

Utangulizi

Kiwango cha ERC-721 kinatumika kushikilia umiliki wa Tokeni Zisizobadilishika (NFT). Tokeni za ERC-20 hufanya kazi kama bidhaa, kwa sababu hakuna tofauti kati ya tokeni binafsi. Tofauti na hiyo, tokeni za ERC-721 zimeundwa kwa ajili ya mali zinazofanana lakini si sawa, kama vile katuni za paka tofauti au hati miliki za vipande tofauti vya mali isiyohamishika.

Katika makala haya tutachambua mkataba wa ERC-721 wa Ryuya Nakamura (opens in a new tab). Mkataba huu umeandikwa kwa Vyper (opens in a new tab), lugha ya mkataba inayofanana na Python iliyoundwa ili iwe vigumu zaidi kuandika msimbo usio salama kuliko ilivyo katika Solidity.

Mkataba

1# @dev Utekelezaji wa kiwango cha tokeni isiyobadilishika ya ERC-721.
2# @author Ryuya Nakamura (@nrryuya)
3# Imebadilishwa kutoka: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy

Maoni katika Vyper, kama ilivyo katika Python, huanza na alama ya reli (#) na kuendelea hadi mwisho wa mstari. Maoni yanayojumuisha @<keyword> hutumiwa na NatSpec (opens in a new tab) kuzalisha nyaraka zinazoweza kusomwa na binadamu.

1from vyper.interfaces import ERC721
2
3implements: ERC721

Kiolesura cha ERC-721 kimejengewa ndani ya lugha ya Vyper. Unaweza kuona ufafanuzi wa msimbo hapa (opens in a new tab). Ufafanuzi wa kiolesura umeandikwa kwa Python, badala ya Vyper, kwa sababu violesura hutumika si tu ndani ya mnyororo wa bloku, bali pia wakati wa kutuma muamala kwenye mnyororo wa bloku kutoka kwa wateja wa nje, ambao unaweza kuandikwa kwa Python.

Mstari wa kwanza huingiza kiolesura, na wa pili unabainisha kuwa tunakitekeleza hapa.

Kiolesura cha ERC721Receiver

1# Kiolesura cha mkataba unaoitwa na safeTransferFrom()
2interface ERC721Receiver:
3 def onERC721Received(

ERC-721 inasaidia aina mbili za uhamishaji:

  • transferFrom, ambayo inamruhusu mtumaji kubainisha anwani yoyote ya marudio na kuweka jukumu la uhamishaji kwa mtumaji. Hii ina maana kwamba unaweza kuhamisha kwenda anwani batili, ambapo NFT inapotea kabisa.
  • safeTransferFrom, ambayo huangalia kama anwani ya marudio ni mkataba. Ikiwa ndivyo, mkataba wa ERC-721 huuliza mkataba mpokeaji kama unataka kupokea NFT.

Ili kujibu maombi ya safeTransferFrom, mkataba mpokeaji unapaswa kutekeleza ERC721Receiver.

1 _operator: address,
2 _from: address,

Anwani ya _from ni mmiliki wa sasa wa tokeni. Anwani ya _operator ndiyo iliyoitisha uhamishaji (hizi mbili zinaweza zisiwe sawa, kwa sababu ya posho).

1 _tokenId: uint256,

Vitambulisho vya tokeni za ERC-721 vina biti 256. Kwa kawaida huundwa kwa kuhashi maelezo ya chochote kinachowakilishwa na tokeni.

1 _data: Bytes[1024]

Ombi linaweza kuwa na baiti hadi 1024 za data ya mtumiaji.

1 ) -> bytes32: view

Ili kuzuia visa ambapo mkataba unakubali uhamishaji kimakosa, thamani ya kurejesha si ya Boolean, bali ni biti 256 zenye thamani maalum.

Kazi hii ni view, ambayo ina maana inaweza kusoma hali ya mnyororo wa bloku, lakini si kuibadilisha.

Matukio

Matukio (opens in a new tab) hutolewa ili kuwajulisha watumiaji na seva zilizo nje ya mnyororo wa bloku kuhusu matukio. Kumbuka kwamba maudhui ya matukio hayapatikani kwa mikataba kwenye mnyororo wa bloku.

1# @dev Hutoa wakati umiliki wa NFT yoyote unapobadilika kwa utaratibu wowote. Tukio hili hutolewa wakati NFTs
2# zinapoundwa (`from` == 0) na kuharibiwa (`to` == 0). Isipokuwa: wakati wa uundaji wa mkataba, idadi
3# yoyote ya NFT inaweza kuundwa na kugawiwa bila kutoa Transfer. Wakati wa uhamishaji
4# wowote, anwani iliyoidhinishwa kwa NFT hiyo (ikiwa ipo) huwekwa upya kuwa hakuna.
5# @param _from Mtumaji wa NFT (kama anwani ni anwani sifuri inaashiria uundaji wa tokeni).
6# @param _to Mpokeaji wa NFT (kama anwani ni anwani sifuri inaashiria uharibifu wa tokeni).
7# @param _tokenId NFT iliyohamishwa.
8event Transfer:
9 sender: indexed(address)
10 receiver: indexed(address)
11 tokenId: indexed(uint256)
Onyesha yote

Hili ni sawa na tukio la Uhamishaji wa ERC-20, isipokuwa kwamba tunaripoti tokenId badala ya kiasi. Hakuna anayemiliki anwani sifuri, kwa hivyo kwa kawaida tunaitumia kuripoti uundaji na uharibifu wa tokeni.

1# @dev Hii hutolewa wakati anwani iliyoidhinishwa kwa NFT inapobadilishwa au kuthibitishwa tena. Anwani sifuri
2# inaonyesha hakuna anwani iliyoidhinishwa. Tukio la Uhamishaji linapotolewa, hii pia
3# inaonyesha kwamba anwani iliyoidhinishwa kwa NFT hiyo (ikiwa ipo) huwekwa upya kuwa hakuna.
4# @param _owner Mmiliki wa NFT.
5# @param _approved Anwani tunayoidhinisha.
6# @param _tokenId NFT tunayoidhinisha.
7event Approval:
8 owner: indexed(address)
9 approved: indexed(address)
10 tokenId: indexed(uint256)
Onyesha yote

Idhini ya ERC-721 inafanana na posho ya ERC-20. Anwani maalum inaruhusiwa kuhamisha tokeni maalum. Hii inatoa utaratibu kwa mikataba kujibu wanapokubali tokeni. Mikataba haiwezi kusikiliza matukio, kwa hivyo ukihamisha tokeni kwao tu "hawajui" kuihusu. Kwa njia hii, mmiliki kwanza huwasilisha idhini kisha hutuma ombi kwa mkataba: "Nimekuidhinisha uhamishe tokeni X, tafadhali fanya ...".

Hii ni chaguo la muundo ili kufanya kiwango cha ERC-721 kifanane na kiwango cha ERC-20. Kwa sababu tokeni za ERC-721 hazibadiliki, mkataba unaweza pia kutambua kuwa umepata tokeni maalum kwa kuangalia umiliki wa tokeni.

1# @dev Hii hutolewa wakati mwendeshaji anapowezeshwa au kuzimwa kwa mmiliki. Mwendeshaji anaweza kusimamia
2# NFT zote za mmiliki.
3# @param _owner Mmiliki wa NFT.
4# @param _operator Anwani ambayo tunaweka haki za mwendeshaji.
5# @param _approved Hali ya haki za mwendeshaji (kweli ikiwa haki za mwendeshaji zimetolewa na uongo ikiwa
6# zimefutwa).
7event ApprovalForAll:
8 owner: indexed(address)
9 operator: indexed(address)
10 approved: bool
Onyesha yote

Wakati mwingine ni muhimu kuwa na operator anayeweza kusimamia tokeni zote za akaunti za aina fulani (zile zinazosimamiwa na mkataba maalum), sawa na mamlaka ya uwakili. Kwa mfano, ninaweza kutaka kutoa mamlaka kama hayo kwa mkataba unaoangalia ikiwa sijauwasiliana nao kwa miezi sita, na ikiwa ni hivyo unagawanya mali zangu kwa warithi wangu (kama mmoja wao ataomba, mikataba haiwezi kufanya chochote bila kuitwa na muamala). Katika ERC-20 tunaweza kutoa posho kubwa kwa mkataba wa urithi, lakini hilo halifanyi kazi kwa ERC-721 kwa sababu tokeni hazibadiliki. Hii ni sawa na hiyo.

Thamani ya approved inatuambia kama tukio ni la idhini, au uondoaji wa idhini.

Vigezo vya Hali

Vigezo hivi vina hali ya sasa ya tokeni: ni zipi zinapatikana na nani anazimiliki. Nyingi za hizi ni vitu vya HashMap, ramani za mwelekeo mmoja ambazo zipo kati ya aina mbili (opens in a new tab).

1# @dev Ramani kutoka kitambulisho cha NFT kwenda kwenye anwani inayomiliki.
2idToOwner: HashMap[uint256, address]
3
4# @dev Ramani kutoka kitambulisho cha NFT kwenda kwenye anwani iliyoidhinishwa.
5idToApprovals: HashMap[uint256, address]

Utambulisho wa watumiaji na mikataba katika Ethereum unawakilishwa na anwani za biti 160. Vigezo hivi viwili vinapanga ramani kutoka vitambulisho vya tokeni kwenda kwa wamiliki wao na wale walioidhinishwa kuzihamisha (kwa kiwango cha juu cha mmoja kwa kila moja). Katika Ethereum, data ambayo haijaanziwa huwa ni sifuri, kwa hivyo kama hakuna mmiliki au mhamishaji aliyeidhinishwa, thamani ya tokeni hiyo ni sifuri.

1# @dev Ramani kutoka anwani ya mmiliki kwenda kwenye hesabu ya tokeni zake.
2ownerToNFTokenCount: HashMap[address, uint256]

Kigezo hiki kinashikilia hesabu ya tokeni kwa kila mmiliki. Hakuna ramani kutoka kwa wamiliki kwenda kwenye tokeni, kwa hivyo njia pekee ya kutambua tokeni ambazo mmiliki maalum anamiliki ni kuangalia nyuma katika historia ya matukio ya mnyororo wa bloku na kuona matukio sahihi ya Transfer. Tunaweza kutumia kigezo hiki kujua wakati tuna NFT zote na hatuhitaji kuangalia mbele zaidi kwa wakati.

Kumbuka kuwa kanuni hii inafanya kazi tu kwa violesura vya mtumiaji na seva za nje. Msimbo unaoendeshwa kwenye mnyororo wa bloku wenyewe hauwezi kusoma matukio yaliyopita.

1# @dev Ramani kutoka anwani ya mmiliki kwenda kwenye ramani ya anwani za waendeshaji.
2ownerToOperators: HashMap[address, HashMap[address, bool]]

Akaunti inaweza kuwa na mwendeshaji zaidi ya mmoja. HashMap rahisi haitoshi kufuatilia, kwa sababu kila ufunguo unaelekea kwenye thamani moja. Badala yake, unaweza kutumia HashMap[address, bool] kama thamani. Kwa chaguo-msingi, thamani kwa kila anwani ni Uongo, ambayo ina maana si mwendeshaji. Unaweza kuweka thamani kuwa Kweli inapohitajika.

1# @dev Anwani ya mchapaji, anayeweza kuchapa tokeni
2minter: address

Tokeni mpya zinapaswa kuundwa kwa namna fulani. Katika mkataba huu kuna huluki moja tu inayoruhusiwa kufanya hivyo, yaani minter. Hii inawezekana kutosha kwa mchezo, kwa mfano. Kwa madhumuni mengine, inaweza kuwa muhimu kuunda mantiki ya biashara ngumu zaidi.

1# @dev Ramani ya kitambulisho cha kiolesura kwenda kwa bool kuhusu kama inasaidiwa au la
2supportedInterfaces: HashMap[bytes32, bool]
3
4# @dev Kitambulisho cha kiolesura cha ERC165 cha ERC165
5ERC165_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000001ffc9a7
6
7# @dev Kitambulisho cha kiolesura cha ERC165 cha ERC721
8ERC721_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000080ac58cd

ERC-165 (opens in a new tab) inabainisha utaratibu kwa mkataba kufichua jinsi programu zinavyoweza kuwasiliana nayo, na ni ERC zipi inazoendana nazo. Katika kesi hii, mkataba unaendana na ERC-165 na ERC-721.

Kazi

Hizi ni kazi zinazotekeleza ERC-721.

Kiunda

1@external
2def __init__():

Katika Vyper, kama ilivyo katika Python, kazi ya kiunda inaitwa __init__.

1 """
2 @dev Kiunda cha mkataba.
3 """

Katika Python, na katika Vyper, unaweza pia kuunda maoni kwa kubainisha mfuatano wa mistari mingi (unaoanza na kumalizika kwa """), na usiutumie kwa njia yoyote. Maoni haya pia yanaweza kujumuisha NatSpec (opens in a new tab).

1 self.supportedInterfaces[ERC165_INTERFACE_ID] = True
2 self.supportedInterfaces[ERC721_INTERFACE_ID] = True
3 self.minter = msg.sender

Ili kufikia vigezo vya hali unatumia self.<variable name> (tena, sawa na katika Python).

Kazi za Kuangalia

Hizi ni kazi ambazo hazibadilishi hali ya mnyororo wa bloku, na kwa hivyo zinaweza kutekelezwa bure zikiitwa kutoka nje. Ikiwa kazi za kuangalia zinaitwa na mkataba, bado zinapaswa kutekelezwa kwenye kila nodi na kwa hivyo hugharimu gesi.

1@view
2@external

Maneno haya muhimu kabla ya ufafanuzi wa kazi ambayo huanza na ishara ya at (@) huitwa mapambo. Zinabainisha hali ambazo kazi inaweza kuitwa.

  • @view inabainisha kuwa kazi hii ni ya kuangalia.
  • @external inabainisha kuwa kazi hii maalum inaweza kuitwa na miamala na kwa mikataba mingine.
1def supportsInterface(_interfaceID: bytes32) -> bool:

Tofauti na Python, Vyper ni lugha ya aina tuli (opens in a new tab). Huwezi kutangaza kigezo, au kigezo cha kazi, bila kutambua aina ya data (opens in a new tab). Katika kesi hii, kigezo cha kuingiza ni bytes32, thamani ya biti 256 (biti 256 ndio ukubwa wa neno la asili la Mashine Halisi ya Ethereum). Toleo ni thamani ya boolean. Kwa kawaida, majina ya vigezo vya kazi huanza na alama ya chini (_).

1 """
2 @dev Utambulisho wa kiolesura umebainishwa katika ERC-165.
3 @param _interfaceID Kitambulisho cha kiolesura
4 """
5 return self.supportedInterfaces[_interfaceID]

Rejesha thamani kutoka kwenye HashMap ya self.supportedInterfaces, ambayo imewekwa katika kiunda (__init__).

1### KAZI ZA KUANGALIA ###
2

Hizi ni kazi za kuangalia ambazo hufanya habari kuhusu tokeni zipatikane kwa watumiaji na mikataba mingine.

1@view
2@external
3def balanceOf(_owner: address) -> uint256:
4 """
5 @dev Inarejesha idadi ya NFT zinazomilikiwa na `_owner`.
6 Hutoa kosa ikiwa `_owner` ni anwani sifuri. NFT zilizogawiwa kwa anwani sifuri huchukuliwa kuwa batili.
7 @param _owner Anwani ambayo itauliziwa salio.
8 """
9 assert _owner != ZERO_ADDRESS
Onyesha yote

Mstari huu unathibitisha (opens in a new tab) kuwa _owner si sifuri. Ikiwa ni hivyo, kuna kosa na operesheni inarejeshwa nyuma.

1 return self.ownerToNFTokenCount[_owner]
2
3@view
4@external
5def ownerOf(_tokenId: uint256) -> address:
6 """
7 @dev Inarejesha anwani ya mmiliki wa NFT.
8 Hutoa kosa ikiwa `_tokenId` si NFT halali.
9 @param _tokenId Kitambulisho cha NFT.
10 """
11 owner: address = self.idToOwner[_tokenId]
12 # Hutoa kosa ikiwa `_tokenId` si NFT halali
13 assert owner != ZERO_ADDRESS
14 return owner
Onyesha yote

Katika Mashine Halisi ya Ethereum (evm) hifadhi yoyote ambayo haina thamani iliyohifadhiwa ndani yake ni sifuri. Ikiwa hakuna tokeni kwenye _tokenId basi thamani ya self.idToOwner[_tokenId] ni sifuri. Katika kesi hiyo, kazi inarejeshwa nyuma.

1@view
2@external
3def getApproved(_tokenId: uint256) -> address:
4 """
5 @dev Pata anwani iliyoidhinishwa kwa NFT moja.
6 Hutoa kosa ikiwa `_tokenId` si NFT halali.
7 @param _tokenId Kitambulisho cha NFT cha kuulizia idhini yake.
8 """
9 # Hutoa kosa ikiwa `_tokenId` si NFT halali
10 assert self.idToOwner[_tokenId] != ZERO_ADDRESS
11 return self.idToApprovals[_tokenId]
Onyesha yote

Kumbuka kuwa getApproved inaweza kurejesha sifuri. Ikiwa tokeni ni halali, inarejesha self.idToApprovals[_tokenId]. Ikiwa hakuna muidhinishaji, thamani hiyo ni sifuri.

1@view
2@external
3def isApprovedForAll(_owner: address, _operator: address) -> bool:
4 """
5 @dev Inaangalia kama `_operator` ni mwendeshaji aliyeidhinishwa kwa `_owner`.
6 @param _owner Anwani inayomiliki NFT.
7 @param _operator Anwani inayofanya kazi kwa niaba ya mmiliki.
8 """
9 return (self.ownerToOperators[_owner])[_operator]
Onyesha yote

Kazi hii inaangalia kama _operator anaruhusiwa kusimamia tokeni zote za _owner katika mkataba huu. Kwa sababu kunaweza kuwa na waendeshaji wengi, hii ni HashMap ya viwango viwili.

Kazi Saidizi za Uhamishaji

Kazi hizi zinatekeleza operesheni ambazo ni sehemu ya kuhamisha au kusimamia tokeni.

1
2### KAZI SAIDIZI ZA KAZI ZA UHAMISHAJI ###
3
4@view
5@internal

Mapambo haya, @internal, inamaanisha kuwa kazi inapatikana tu kutoka kwa kazi zingine ndani ya mkataba uleule. Kwa kawaida, majina ya kazi hizi pia huanza na alama ya chini (_).

1def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool:
2 """
3 @dev Inarejesha kama mtumiaji aliyetajwa anaweza kuhamisha kitambulisho cha tokeni kilichotajwa
4 @param spender anwani ya mtumiaji wa kuulizia
5 @param tokenId kitambulisho cha uint256 cha tokeni ya kuhamishwa
6 @return bool kama msg.sender ameidhinishwa kwa kitambulisho cha tokeni kilichotajwa,
7 ni mwendeshaji wa mmiliki, au ni mmiliki wa tokeni
8 """
9 owner: address = self.idToOwner[_tokenId]
10 spenderIsOwner: bool = owner == _spender
11 spenderIsApproved: bool = _spender == self.idToApprovals[_tokenId]
12 spenderIsApprovedForAll: bool = (self.ownerToOperators[owner])[_spender]
13 return (spenderIsOwner or spenderIsApproved) or spenderIsApprovedForAll
Onyesha yote

Kuna njia tatu ambazo anwani inaweza kuruhusiwa kuhamisha tokeni:

  1. Anwani ni mmiliki wa tokeni
  2. Anwani imehidhinishwa kutumia tokeni hiyo
  3. Anwani ni mwendeshaji wa mmiliki wa tokeni

Kazi iliyo hapo juu inaweza kuwa ya kuangalia kwa sababu haibadilishi hali. Ili kupunguza gharama za uendeshaji, kazi yoyote ambayo inaweza kuwa ya kuangalia inapaswa kuwa ya kuangalia.

1@internal
2def _addTokenTo(_to: address, _tokenId: uint256):
3 """
4 @dev Ongeza NFT kwenye anwani iliyotajwa
5 Hutoa kosa ikiwa `_tokenId` inamilikiwa na mtu.
6 """
7 # Hutoa kosa ikiwa `_tokenId` inamilikiwa na mtu
8 assert self.idToOwner[_tokenId] == ZERO_ADDRESS
9 # Badilisha mmiliki
10 self.idToOwner[_tokenId] = _to
11 # Badilisha ufuatiliaji wa hesabu
12 self.ownerToNFTokenCount[_to] += 1
13
14
15@internal
16def _removeTokenFrom(_from: address, _tokenId: uint256):
17 """
18 @dev Ondoa NFT kutoka kwa anwani iliyotajwa
19 Hutoa kosa ikiwa `_from` si mmiliki wa sasa.
20 """
21 # Hutoa kosa ikiwa `_from` si mmiliki wa sasa
22 assert self.idToOwner[_tokenId] == _from
23 # Badilisha mmiliki
24 self.idToOwner[_tokenId] = ZERO_ADDRESS
25 # Badilisha ufuatiliaji wa hesabu
26 self.ownerToNFTokenCount[_from] -= 1
Onyesha yote

Kunapokuwa na tatizo na uhamishaji, tunarejesha wito nyuma.

1@internal
2def _clearApproval(_owner: address, _tokenId: uint256):
3 """
4 @dev Futa idhini ya anwani iliyotajwa
5 Hutoa kosa ikiwa `_owner` si mmiliki wa sasa.
6 """
7 # Hutoa kosa ikiwa `_owner` si mmiliki wa sasa
8 assert self.idToOwner[_tokenId] == _owner
9 if self.idToApprovals[_tokenId] != ZERO_ADDRESS:
10 # Weka upya idhini
11 self.idToApprovals[_tokenId] = ZERO_ADDRESS
Onyesha yote

Badilisha tu thamani ikiwa ni lazima. Vigezo vya hali huishi kwenye hifadhi. Kuandika kwenye hifadhi ni mojawapo ya operesheni ghali zaidi ambayo EVM (Mashine Halisi ya Ethereum) hufanya (kwa upande wa gesi). Kwa hivyo, ni wazo zuri kuipunguza, hata kuandika thamani iliyopo kuna gharama kubwa.

1@internal
2def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: address):
3 """
4 @dev Tekeleza uhamishaji wa NFT.
5 Hutoa kosa isipokuwa `msg.sender` ni mmiliki wa sasa, mwendeshaji aliyeidhinishwa, au anwani
6 iliyoidhinishwa kwa NFT hii. (KUMBUKA: `msg.sender` hairuhusiwi katika kazi ya faragha kwa hivyo pitisha `_sender`.)
7 Hutoa kosa ikiwa `_to` ni anwani sifuri.
8 Hutoa kosa ikiwa `_from` si mmiliki wa sasa.
9 Hutoa kosa ikiwa `_tokenId` si NFT halali.
10 """
Onyesha yote

Tuna kazi hii ya ndani kwa sababu kuna njia mbili za kuhamisha tokeni (kawaida na salama), lakini tunataka eneo moja tu katika msimbo ambapo tunafanya hivyo ili kurahisisha ukaguzi.

1 # Angalia mahitaji
2 assert self._isApprovedOrOwner(_sender, _tokenId)
3 # Hutoa kosa ikiwa `_to` ni anwani sifuri
4 assert _to != ZERO_ADDRESS
5 # Futa idhini. Hutoa kosa ikiwa `_from` si mmiliki wa sasa
6 self._clearApproval(_from, _tokenId)
7 # Ondoa NFT. Hutoa kosa ikiwa `_tokenId` si NFT halali
8 self._removeTokenFrom(_from, _tokenId)
9 # Ongeza NFT
10 self._addTokenTo(_to, _tokenId)
11 # Ingiza uhamishaji kwenye kumbukumbu
12 log Transfer(_from, _to, _tokenId)
Onyesha yote

Ili kutoa tukio katika Vyper unatumia taarifa ya log (ona hapa kwa maelezo zaidi (opens in a new tab)).

Kazi za Uhamishaji

1
2### KAZI ZA UHAMISHAJI ###
3
4@external
5def transferFrom(_from: address, _to: address, _tokenId: uint256):
6 """
7 @dev Hutoa kosa isipokuwa `msg.sender` ni mmiliki wa sasa, mwendeshaji aliyeidhinishwa, au anwani
8 iliyoidhinishwa kwa NFT hii.
9 Hutoa kosa ikiwa `_from` si mmiliki wa sasa.
10 Hutoa kosa ikiwa `_to` ni anwani sifuri.
11 Hutoa kosa ikiwa `_tokenId` si NFT halali.
12 @notice Mwitaji anawajibika kuthibitisha kuwa `_to` ina uwezo wa kupokea NFT, vinginevyo
13 zinaweza kupotea kabisa.
14 @param _from Mmiliki wa sasa wa NFT.
15 @param _to Mmiliki mpya.
16 @param _tokenId NFT ya kuhamisha.
17 """
18 self._transferFrom(_from, _to, _tokenId, msg.sender)
Onyesha yote

Kazi hii inakuwezesha kuhamisha kwenda kwenye anwani yoyote. Isipokuwa anwani ni ya mtumiaji, au mkataba ambao unajua jinsi ya kuhamisha tokeni, tokeni yoyote utakayohamisha itakwama kwenye anwani hiyo na kuwa isiyofaa.

1@external
2def safeTransferFrom(
3 _from: address,
4 _to: address,
5 _tokenId: uint256,
6 _data: Bytes[1024]=b""
7 ):
8 """
9 @dev Huhamisha umiliki wa NFT kutoka anwani moja kwenda nyingine.
10 Hutoa kosa isipokuwa `msg.sender` ni mmiliki wa sasa, mwendeshaji aliyeidhinishwa, au anwani
11 iliyoidhinishwa kwa NFT hii.
12 Hutoa kosa ikiwa `_from` si mmiliki wa sasa.
13 Hutoa kosa ikiwa `_to` ni anwani sifuri.
14 Hutoa kosa ikiwa `_tokenId` si NFT halali.
15 Ikiwa `_to` ni mkataba-erevu, inaita `onERC721Received` kwenye `_to` na hutoa kosa ikiwa
16 thamani ya kurejesha si `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
17 KUMBUKA: bytes4 inawakilishwa na bytes32 na padding
18 @param _from Mmiliki wa sasa wa NFT.
19 @param _to Mmiliki mpya.
20 @param _tokenId NFT ya kuhamisha.
21 @param _data Data ya ziada bila umbizo maalum, iliyotumwa kwenye wito kwa `_to`.
22 """
23 self._transferFrom(_from, _to, _tokenId, msg.sender)
Onyesha yote

Ni sawa kufanya uhamishaji kwanza kwa sababu ikiwa kuna tatizo tutarejesha nyuma hata hivyo, kwa hivyo kila kitu kilichofanywa kwenye wito kitaghairishwa.

1 if _to.is_contract: # angalia kama `_to` ni anwani ya mkataba

Kwanza angalia kuona kama anwani ni mkataba (kama ina msimbo). Kama sivyo, chukulia ni anwani ya mtumiaji na mtumiaji ataweza kutumia tokeni au kuihamisha. Lakini usiruhusu ikudanganye katika hisia za uongo za usalama. Unaweza kupoteza tokeni, hata kwa safeTransferFrom, ukizihamisha kwenda anwani ambayo hakuna anayejua ufunguo wake binafsi.

1 returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data)

Piga simu mkataba lengwa kuona kama unaweza kupokea tokeni za ERC-721.

1 # Hutoa kosa ikiwa marudio ya uhamishaji ni mkataba ambao hautekelezi 'onERC721Received'
2 assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes32)

Ikiwa marudio ni mkataba, lakini ambao haukubali tokeni za ERC-721 (au ambao umeamua kutokubali uhamishaji huu maalum), rejeshwa nyuma.

1@external
2def approve(_approved: address, _tokenId: uint256):
3 """
4 @dev Weka au thibitisha tena anwani iliyoidhinishwa kwa NFT. Anwani sifuri inaonyesha hakuna anwani iliyoidhinishwa.
5 Hutoa kosa isipokuwa `msg.sender` ni mmiliki wa sasa wa NFT, au mwendeshaji aliyeidhinishwa wa mmiliki wa sasa.
6 Hutoa kosa ikiwa `_tokenId` si NFT halali. (KUMBUKA: Hii haijaandikwa kwenye EIP)
7 Hutoa kosa ikiwa `_approved` ni mmiliki wa sasa. (KUMBUKA: Hii haijaandikwa kwenye EIP)
8 @param _approved Anwani ya kuidhinishwa kwa kitambulisho cha NFT kilichotajwa.
9 @param _tokenId Kitambulisho cha tokeni ya kuidhinishwa.
10 """
11 owner: address = self.idToOwner[_tokenId]
12 # Hutoa kosa ikiwa `_tokenId` si NFT halali
13 assert owner != ZERO_ADDRESS
14 # Hutoa kosa ikiwa `_approved` ni mmiliki wa sasa
15 assert _approved != owner
Onyesha yote

Kwa kawaida, ikiwa hutaki kuwa na muidhinishaji, unateua anwani sifuri, si wewe mwenyewe.

1 # Angalia mahitaji
2 senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender
3 senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender]
4 assert (senderIsOwner or senderIsApprovedForAll)

Ili kuweka idhini unaweza kuwa mmiliki, au mwendeshaji aliyeidhinishwa na mmiliki.

1 # Weka idhini
2 self.idToApprovals[_tokenId] = _approved
3 log Approval(owner, _approved, _tokenId)
4
5
6@external
7def setApprovalForAll(_operator: address, _approved: bool):
8 """
9 @dev Inawezesha au inalemaza idhini kwa mhusika wa tatu ("mwendeshaji") kusimamia mali zote za
10 `msg.sender`. Pia hutoa tukio la ApprovalForAll.
11 Hutoa kosa ikiwa `_operator` ni `msg.sender`. (KUMBUKA: Hii haijaandikwa kwenye EIP)
12 @notice Hii inafanya kazi hata kama mtumaji hamiliki tokeni zozote kwa wakati huo.
13 @param _operator Anwani ya kuongeza kwenye seti ya waendeshaji walioidhinishwa.
14 @param _approved Kweli kama waendeshaji wameidhinishwa, uongo kufuta idhini.
15 """
16 # Hutoa kosa ikiwa `_operator` ni `msg.sender`
17 assert _operator != msg.sender
18 self.ownerToOperators[msg.sender][_operator] = _approved
19 log ApprovalForAll(msg.sender, _operator, _approved)
Onyesha yote

Chapa Tokeni Mpya na Uharibu Zilizopo

Akaunti iliyounda mkataba ndiye minter, mtumiaji mkuu aliyeidhinishwa kuchapa NFT mpya. Hata hivyo, hairuhusiwi kuchoma tokeni zilizopo. Ni mmiliki tu, au huluki iliyoihdinishwa na mmiliki, ndiyo inayoweza kufanya hivyo.

1### KAZI ZA KUCHAPA NA KUCHOMA ###
2
3@external
4def mint(_to: address, _tokenId: uint256) -> bool:

Kazi hii daima inarejesha Kweli, kwa sababu ikiwa operesheni itashindwa, inarejeshwa nyuma.

1 """
2 @dev Kazi ya kuchapa tokeni
3 Hutoa kosa ikiwa `msg.sender` si mchapaji.
4 Hutoa kosa ikiwa `_to` ni anwani sifuri.
5 Hutoa kosa ikiwa `_tokenId` inamilikiwa na mtu.
6 @param _to Anwani itakayopokea tokeni zilizochapwa.
7 @param _tokenId Kitambulisho cha tokeni cha kuchapa.
8 @return Boolean inayoonyesha kama operesheni ilifanikiwa.
9 """
10 # Hutoa kosa ikiwa `msg.sender` si mchapaji
11 assert msg.sender == self.minter
Onyesha yote

Ni mchapaji tu (akaunti iliyounda mkataba wa ERC-721) anayeweza kuchapa tokeni mpya. Hili linaweza kuwa tatizo siku zijazo ikiwa tunataka kubadilisha utambulisho wa mchapaji. Katika mkataba wa uzalishaji, labda utataka kazi inayoruhusu mchapaji kuhamisha marupurupu ya mchapaji kwa mtu mwingine.

1 # Hutoa kosa ikiwa `_to` ni anwani sifuri
2 assert _to != ZERO_ADDRESS
3 # Ongeza NFT. Hutoa kosa ikiwa `_tokenId` inamilikiwa na mtu
4 self._addTokenTo(_to, _tokenId)
5 log Transfer(ZERO_ADDRESS, _to, _tokenId)
6 return True

Kwa kawaida, uchapaji wa tokeni mpya huhesabiwa kama uhamishaji kutoka kwa anwani sifuri.

1
2@external
3def burn(_tokenId: uint256):
4 """
5 @dev Inachoma tokeni maalum ya ERC721.
6 Hutoa kosa isipokuwa `msg.sender` ni mmiliki wa sasa, mwendeshaji aliyeidhinishwa, au anwani
7 iliyoidhinishwa kwa NFT hii.
8 Hutoa kosa ikiwa `_tokenId` si NFT halali.
9 @param _tokenId kitambulisho cha uint256 cha tokeni ya ERC721 itakayochomwa.
10 """
11 # Angalia mahitaji
12 assert self._isApprovedOrOwner(msg.sender, _tokenId)
13 owner: address = self.idToOwner[_tokenId]
14 # Hutoa kosa ikiwa `_tokenId` si NFT halali
15 assert owner != ZERO_ADDRESS
16 self._clearApproval(owner, _tokenId)
17 self._removeTokenFrom(owner, _tokenId)
18 log Transfer(owner, ZERO_ADDRESS, _tokenId)
Onyesha yote

Mtu yeyote anayeruhusiwa kuhamisha tokeni anaruhusiwa kuichoma. Wakati uchomaji unaonekana sawa na uhamishaji kwenda kwa anwani sifuri, anwani sifuri haipokei tokeni hiyo. Hii inaturuhusu kuachilia hifadhi yote iliyotumika kwa tokeni, ambayo inaweza kupunguza gharama ya gesi ya muamala.

Kutumia Mkataba Huu

Tofauti na Solidity, Vyper haina urithi. Hili ni chaguo la muundo la makusudi ili kufanya msimbo uwe wazi zaidi na kwa hivyo iwe rahisi kuulinda. Kwa hivyo, ili kuunda mkataba wako wa Vyper ERC-721, unachukua mkataba huu na kuubadilisha ili kutekeleza mantiki ya biashara unayotaka.

Hitimisho

Kwa mapitio, haya ni baadhi ya mawazo muhimu zaidi katika mkataba huu:

  • Ili kupokea tokeni za ERC-721 kwa uhamishaji salama, mikataba inapaswa kutekeleza kiolesura cha ERC721Receiver.
  • Hata ukitumia uhamishaji salama, tokeni bado zinaweza kukwama ukizituma kwa anwani ambayo ufunguo wake binafsi haujulikani.
  • Kunapokuwa na tatizo na operesheni, ni wazo zuri kurejesha nyuma wito, badala ya kurejesha tu thamani ya kushindwa.
  • Tokeni za ERC-721 zipo zinapokuwa na mmiliki.
  • Kuna njia tatu za kuidhinishwa kuhamisha NFT. Unaweza kuwa mmiliki, kuidhinishwa kwa tokeni maalum, au kuwa mwendeshaji wa tokeni zote za mmiliki.
  • Matukio yaliyopita yanaonekana tu nje ya mnyororo wa bloku. Msimbo unaoendeshwa ndani ya mnyororo wa bloku hauwezi kuyaona.

Sasa nenda na utekeleze mikataba salama ya Vyper.

Tazama hapa kwa kazi zangu zaidi (opens in a new tab).

Ukurasa ulihaririwa mwisho: 3 Machi 2026

Umesaidika na mafunzo haya?