Vyper ERC-721 కాంట్రాక్ట్ వాక్త్రూ
పరిచయం
ERC-721 ప్రమాణం నాన్-ఫంగిబుల్ టోకెన్ల (NFT) యాజమాన్యాన్ని కలిగి ఉండటానికి ఉపయోగించబడుతుంది. ERC-20 టోకెన్లు ఒక వస్తువుగా ప్రవర్తిస్తాయి, ఎందుకంటే వ్యక్తిగత టోకెన్ల మధ్య తేడా ఉండదు. దీనికి విరుద్ధంగా, ERC-721 టోకెన్లు ఒకేలా ఉండే కానీ ఒకేలా లేని ఆస్తుల కోసం రూపొందించబడ్డాయి, ఉదాహరణకు విభిన్న పిల్లి కార్టూన్లు లేదా విభిన్న రియల్ ఎస్టేట్ ముక్కలకు చెందిన టైటిళ్లు.
ఈ ఆర్టికల్లో మేము ర్యూయా నకమురా వారి ERC-721 కాంట్రాక్ట్ను (opens in a new tab) విశ్లేషిస్తాము. ఈ కాంట్రాక్ట్ Vyper (opens in a new tab)లో వ్రాయబడింది, ఇది సోలిడిటీలో ఉన్నదానికంటే అసురక్షిత కోడ్ను వ్రాయడాన్ని కష్టతరం చేయడానికి రూపొందించిన పైథాన్ లాంటి కాంట్రాక్ట్ భాష.
కాంట్రాక్ట్
# @dev ERC-721 నాన్-ఫంగిబుల్ టోకెన్ ప్రమాణం యొక్క అమలు.
# @రచయిత ర్యూయా నకమురా (@nrryuya)
# దీని నుండి సవరించబడింది: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy
Vyperలో, పైథాన్లో వలె, వ్యాఖ్యలు హాష్ (#)తో ప్రారంభమై లైన్ చివరి వరకు కొనసాగుతాయి. @<keyword>
ను కలిగి ఉన్న వ్యాఖ్యలు మానవ-చదవగలిగే
డాక్యుమెంటేషన్ను రూపొందించడానికి NatSpec (opens in a new tab) ద్వారా ఉపయోగించబడతాయి.
from vyper.interfaces import ERC721
implements: ERC721
ERC-721 ఇంటర్ఫేస్ Vyper భాషలో నిర్మించబడింది. మీరు కోడ్ నిర్వచనాన్ని ఇక్కడ చూడవచ్చు (opens in a new tab). ఇంటర్ఫేస్ నిర్వచనం Vyperలో కాకుండా పైథాన్లో వ్రాయబడింది, ఎందుకంటే ఇంటర్ఫేసులు బ్లాక్ చైను లోపల మాత్రమే కాకుండా, పైథాన్లో వ్రాయబడిన బాహ్య క్లయింట్ నుండి బ్లాక్ చైనుకు లావాదేవీని పంపేటప్పుడు కూడా ఉపయోగించబడతాయి.
మొదటి లైన్ ఇంటర్ఫేస్ను దిగుమతి చేస్తుంది మరియు రెండవది మనం ఇక్కడ దాన్ని అమలు చేస్తున్నామని నిర్దేశిస్తుంది.
ERC721రిసీవర్ ఇంటర్ఫేస్
# safeTransferFrom() ద్వారా పిలువబడే కాంట్రాక్ట్ కోసం ఇంటర్ఫేస్
interface ERC721Receiver:
def onERC721Received(
ERC-721 రెండు రకాల బదిలీలకు మద్దతు ఇస్తుంది:
transferFrom, ఇది పంపినవారికి ఏదైనా గమ్యస్థాన చిరునామాను పేర్కొనడానికి వీలు కల్పిస్తుంది మరియు బదిలీ బాధ్యతను పంపినవారిపై ఉంచుతుంది. దీని అర్థం మీరు చెల్లని చిరునామాకు బదిలీ చేయవచ్చు, ఈ సందర్భంలో NFT శాశ్వతంగా పోతుంది.safeTransferFrom, ఇది గమ్యస్థాన చిరునామా కాంట్రాక్ట్ కాదా అని తనిఖీ చేస్తుంది. అలా అయితే, ERC-721 కాంట్రాక్ట్ NFTని స్వీకరించాలనుకుంటున్నారా అని స్వీకరించే కాంట్రాక్ట్ను అడుగుతుంది.
safeTransferFrom అభ్యర్థనలకు సమాధానం ఇవ్వడానికి, స్వీకరించే కాంట్రాక్ట్ ERC721Receiverను అమలు చేయాలి.
_operator: address,
_from: address,
_from చిరునామా టోకెన్ యొక్క ప్రస్తుత యజమాని. _operator చిరునామా అనేది
బదిలీని అభ్యర్థించినది (అలవెన్సుల కారణంగా ఆ రెండూ ఒకేలా ఉండకపోవచ్చు).
_tokenId: uint256,
ERC-721 టోకెన్ IDలు 256 బిట్లు. సాధారణంగా అవి టోకెన్ దేనిని సూచిస్తుందో దాని వివరణను హాష్ చేయడం ద్వారా సృష్టించబడతాయి.
_data: Bytes[1024]
అభ్యర్థనలో 1024 బైట్ల వరకు వినియోగదారు డేటా ఉండవచ్చు.
) -> bytes32: view
ఒక కాంట్రాక్ట్ అనుకోకుండా బదిలీని అంగీకరించే సందర్భాలను నివారించడానికి, తిరిగి వచ్చే విలువ బూలియన్ కాదు, కానీ ఒక నిర్దిష్ట విలువతో 256 బిట్లు.
ఈ ఫంక్షన్ ఒక view, అంటే ఇది బ్లాక్ చైను యొక్క స్టేట్ను చదవగలదు, కానీ దానిని సవరించలేదు.
ఈవెంట్లు
ఈవెంట్లు (opens in a new tab) బ్లాక్ చైను వెలుపల ఉన్న వినియోగదారులు మరియు సర్వర్లకు ఈవెంట్ల గురించి తెలియజేయడానికి విడుదల చేయబడతాయి. ఈవెంట్ల కంటెంట్ బ్లాక్ చైనులోని కాంట్రాక్ట్లకు అందుబాటులో లేదని గమనించండి.
# @dev ఏదైనా మెకానిజం ద్వారా ఏదైనా NFT యాజమాన్యం మారినప్పుడు విడుదల అవుతుంది. NFTలు సృష్టించబడినప్పుడు ఈ ఈవెంట్ విడుదల అవుతుంది
# (`from` == 0) మరియు నాశనం చేయబడినప్పుడు (`to` == 0). మినహాయింపు: కాంట్రాక్ట్ సృష్టి సమయంలో, ఏదైనా
# బదిలీని విడుదల చేయకుండా NFTల సంఖ్యను సృష్టించవచ్చు మరియు కేటాయించవచ్చు. ఏదైనా సమయంలో
# బదిలీ, ఆ NFTకి ఆమోదించబడిన చిరునామా (ఏదైనా ఉంటే) ఏదీ లేకుండా రీసెట్ చేయబడుతుంది.
# @param _from NFT పంపినవారు (చిరునామా సున్నా చిరునామా అయితే అది టోకెన్ సృష్టిని సూచిస్తుంది).
# @param _to NFT గ్రహీత (చిరునామా సున్నా చిరునామా అయితే అది టోకెన్ నాశనాన్ని సూచిస్తుంది).
# @param _tokenId బదిలీ చేయబడిన NFT.
event Transfer:
sender: indexed(address)
receiver: indexed(address)
tokenId: indexed(uint256)
ఇది ERC-20 బదిలీ ఈవెంట్ను పోలి ఉంటుంది, కానీ మేము మొత్తం బదులుగా tokenIdని నివేదిస్తాము.
సున్నా చిరునామా ఎవరికీ స్వంతం కాదు, కాబట్టి సంప్రదాయం ప్రకారం టోకెన్ల సృష్టి మరియు నాశనాన్ని నివేదించడానికి మేము దానిని ఉపయోగిస్తాము.
# @dev NFT కోసం ఆమోదించబడిన చిరునామా మార్చబడినప్పుడు లేదా పునరుద్ఘాటించబడినప్పుడు ఇది విడుదల అవుతుంది. సున్నా
# చిరునామా ఆమోదించబడిన చిరునామా లేదని సూచిస్తుంది. బదిలీ ఈవెంట్ విడుదల అయినప్పుడు, ఇది కూడా
# ఆ NFTకి ఆమోదించబడిన చిరునామా (ఏదైనా ఉంటే) ఏదీ లేకుండా రీసెట్ చేయబడిందని సూచిస్తుంది.
# @param _owner NFT యజమాని.
# @param _approved మేము ఆమోదిస్తున్న చిరునామా.
# @param _tokenId మేము ఆమోదిస్తున్న NFT.
event Approval:
owner: indexed(address)
approved: indexed(address)
tokenId: indexed(uint256)
ERC-721 ఆమోదం ERC-20 అలవెన్సును పోలి ఉంటుంది. ఒక నిర్దిష్ట టోకెన్ను బదిలీ చేయడానికి ఒక నిర్దిష్ట చిరునామా అనుమతించబడుతుంది. ఇది కాంట్రాక్ట్లు టోకెన్ను అంగీకరించినప్పుడు స్పందించడానికి ఒక యంత్రాంగాన్ని అందిస్తుంది. కాంట్రాక్ట్లు ఈవెంట్లను వినలేవు, కాబట్టి మీరు వాటికి టోకెన్ను బదిలీ చేస్తే, వాటికి దాని గురించి "తెలియదు". ఈ విధంగా యజమాని మొదట ఆమోదాన్ని సమర్పించి, ఆపై కాంట్రాక్ట్కు అభ్యర్థనను పంపుతారు: "టోకెన్ Xను బదిలీ చేయడానికి నేను మీకు ఆమోదం ఇచ్చాను , దయచేసి చేయండి ...".
ERC-721 ప్రమాణాన్ని ERC-20 ప్రమాణానికి సమానంగా చేయడానికి ఇది ఒక డిజైన్ ఎంపిక. ఎందుకంటే ERC-721 టోకెన్లు ఫంగిబుల్ కావు, ఒక కాంట్రాక్ట్ టోకెన్ యాజమాన్యాన్ని చూడటం ద్వారా ఒక నిర్దిష్ట టోకెన్ను పొందిందని కూడా గుర్తించగలదు.
# @dev ఒక యజమాని కోసం ఒక ఆపరేటర్ ఎనేబుల్ లేదా డిసేబుల్ చేయబడినప్పుడు ఇది విడుదల అవుతుంది. ఆపరేటర్ నిర్వహించగలడు
# యజమాని యొక్క అన్ని NFTలు.
# @param _owner NFT యజమాని.
# @param _operator మేము ఆపరేటర్ హక్కులను సెట్ చేస్తున్న చిరునామా.
# @param _approved ఆపరేటర్ హక్కుల స్థితి (ఆపరేటర్ హక్కులు ఇస్తే నిజం మరియు కాకపోతే తప్పు
# రద్దు చేయబడింది).
event ApprovalForAll:
owner: indexed(address)
operator: indexed(address)
approved: bool
కొన్నిసార్లు ఒక నిర్దిష్ట రకానికి చెందిన ఖాతా యొక్క అన్ని టోకెన్లను (ఒక నిర్దిష్ట కాంట్రాక్ట్ ద్వారా నిర్వహించబడేవి) నిర్వహించగల ఆపరేటర్ కలిగి ఉండటం ఉపయోగకరంగా ఉంటుంది, ఇది పవర్ ఆఫ్ అటార్నీని పోలి ఉంటుంది. ఉదాహరణకు, నేను ఆరు నెలలుగా దానిని సంప్రదించలేదా అని తనిఖీ చేసే కాంట్రాక్ట్కు అటువంటి అధికారాన్ని ఇవ్వాలనుకోవచ్చు, మరియు అలా అయితే నా ఆస్తులను నా వారసులకు పంపిణీ చేస్తుంది (వారిలో ఒకరు అడిగితే, కాంట్రాక్ట్లు లావాదేవీ ద్వారా పిలవబడకుండా ఏమీ చేయలేవు). ERC-20లో మేము వారసత్వ కాంట్రాక్ట్కు అధిక అలవెన్సును ఇవ్వవచ్చు, కానీ ERC-721కి ఇది పనిచేయదు ఎందుకంటే టోకెన్లు ఫంగిబుల్ కావు. ఇది దానికి సమానం.
ఈవెంట్ ఆమోదం కోసమా లేదా ఆమోదం ఉపసంహరణ కోసమా అనేది approved విలువ మాకు చెబుతుంది.
స్టేట్ వేరియబుల్స్
ఈ వేరియబుల్స్ టోకెన్ల ప్రస్తుత స్టేట్ను కలిగి ఉంటాయి: ఏవి అందుబాటులో ఉన్నాయి మరియు వాటి యజమాని ఎవరు. వీటిలో చాలా వరకు
HashMap ఆబ్జెక్ట్లు, రెండు రకాల మధ్య ఉన్న ఏకదిశాత్మక మ్యాపింగ్లు (opens in a new tab).
# @dev NFT ID నుండి దాని యజమాని అయిన చిరునామాకు మ్యాపింగ్.
idToOwner: HashMap[uint256, address]
# @dev NFT ID నుండి ఆమోదించబడిన చిరునామాకు మ్యాపింగ్.
idToApprovals: HashMap[uint256, address]
Ethereumలో వినియోగదారు మరియు కాంట్రాక్ట్ గుర్తింపులు 160-బిట్ చిరునామాల ద్వారా సూచించబడతాయి. ఈ రెండు వేరియబుల్స్ టోకెన్ IDల నుండి వాటి యజమానులకు మరియు వాటిని బదిలీ చేయడానికి ఆమోదించబడిన వారికి మ్యాప్ చేస్తాయి (ప్రతిదానికి గరిష్టంగా ఒకటి). Ethereumలో, ప్రారంభించని డేటా ఎల్లప్పుడూ సున్నాగా ఉంటుంది, కాబట్టి యజమాని లేదా ఆమోదించబడిన బదిలీదారు లేకపోతే ఆ టోకెన్ విలువ సున్నాగా ఉంటుంది.
# @dev యజమాని చిరునామా నుండి అతని టోకెన్ల సంఖ్యకు మ్యాపింగ్.
ownerToNFTokenCount: HashMap[address, uint256]
ఈ వేరియబుల్ ప్రతి యజమానికి టోకెన్ల సంఖ్యను కలిగి ఉంటుంది. యజమానుల నుండి టోకెన్లకు మ్యాపింగ్ లేదు, కాబట్టి
ఒక నిర్దిష్ట యజమాని కలిగి ఉన్న టోకెన్లను గుర్తించడానికి ఏకైక మార్గం బ్లాక్ చైను ఈవెంట్ చరిత్రలో వెనక్కి తిరిగి చూడటం
మరియు తగిన Transfer ఈవెంట్లను చూడటం. మన వద్ద అన్ని NFTలు ఉన్నాయని మరియు సమయంలో మరింత వెనక్కి తిరిగి చూడాల్సిన
అవసరం లేదని తెలుసుకోవడానికి మేము ఈ వేరియబుల్ను ఉపయోగించవచ్చు.
ఈ అల్గోరిథం వినియోగదారు ఇంటర్ఫేస్లు మరియు బాహ్య సర్వర్లకు మాత్రమే పనిచేస్తుందని గమనించండి. బ్లాక్ చైనుపై నడుస్తున్న కోడ్ గత ఈవెంట్లను చదవలేదు.
# @dev యజమాని చిరునామా నుండి ఆపరేటర్ చిరునామాల మ్యాపింగ్కు మ్యాపింగ్.
ownerToOperators: HashMap[address, HashMap[address, bool]]
ఒక ఖాతాకు ఒకటి కంటే ఎక్కువ ఆపరేటర్లు ఉండవచ్చు. ఒక సాధారణ HashMap వాటిని ట్రాక్ చేయడానికి సరిపోదు,
ఎందుకంటే ప్రతి కీ ఒకే విలువకు దారితీస్తుంది. బదులుగా, మీరు విలువగా
HashMap[address, bool] ను ఉపయోగించవచ్చు. డిఫాల్ట్గా ప్రతి చిరునామాకు విలువ Falseగా ఉంటుంది, అంటే అది
ఆపరేటర్ కాదు. మీరు అవసరమైన విధంగా విలువలను Trueకి సెట్ చేయవచ్చు.
# @dev మింటర్ యొక్క చిరునామా, ఇతను ఒక టోకెన్ను మింట్ చేయగలడు
minter: address
కొత్త టోకెన్లను ఏదో ఒక విధంగా సృష్టించాలి. ఈ కాంట్రాక్ట్లో అలా చేయడానికి అనుమతించబడిన ఒకే ఒక్క సంస్థ ఉంది, అది
మింటర్. ఉదాహరణకు, ఒక ఆటకు ఇది సరిపోతుంది. ఇతర ప్రయోజనాల కోసం, మరింత సంక్లిష్టమైన వ్యాపార తర్కాన్ని
సృష్టించడం అవసరం కావచ్చు.
# @dev ఇంటర్ఫేస్ ఐడి నుండి అది మద్దతు ఇస్తుందా లేదా అనే దాని గురించి బూల్కి మ్యాపింగ్
supportedInterfaces: HashMap[bytes32, bool]
# @dev ERC165 యొక్క ERC165 ఇంటర్ఫేస్ ఐడి
ERC165_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000001ffc9a7
# @dev ERC721 యొక్క ERC165 ఇంటర్ఫేస్ ఐడి
ERC721_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000080ac58cd
ERC-165 (opens in a new tab) ఒక కాంట్రాక్ట్ దానితో అప్లికేషన్లు ఎలా కమ్యూనికేట్ చేయగలవో, అది ఏ ERCలకు అనుగుణంగా ఉంటుందో బహిర్గతం చేయడానికి ఒక యంత్రాంగాన్ని నిర్దేశిస్తుంది. ఈ సందర్భంలో, కాంట్రాక్ట్ ERC-165 మరియు ERC-721కి అనుగుణంగా ఉంటుంది.
ఫంక్షన్స్
ఇవి వాస్తవానికి ERC-721ని అమలు చేసే ఫంక్షన్లు.
కన్స్ట్రక్టర్
@external
def __init__():
Vyperలో, పైథాన్లో వలె, కన్స్ట్రక్టర్ ఫంక్షన్ను __init__ అని పిలుస్తారు.
"""
@dev కాంట్రాక్ట్ కన్స్ట్రక్టర్.
"""
పైథాన్లో, మరియు Vyperలో, మీరు మల్టీ-లైన్ స్ట్రింగ్ను పేర్కొనడం ద్వారా కూడా ఒక వ్యాఖ్యను సృష్టించవచ్చు (ఇది """తో ప్రారంభమై మరియు ముగుస్తుంది), మరియు దానిని ఏ విధంగానూ ఉపయోగించకుండా ఉండవచ్చు. ఈ వ్యాఖ్యలలో
NatSpec (opens in a new tab) కూడా ఉండవచ్చు.
self.supportedInterfaces[ERC165_INTERFACE_ID] = True
self.supportedInterfaces[ERC721_INTERFACE_ID] = True
self.minter = msg.sender
self.<variable name> ని ఉపయోగించి మీరు స్టేట్ వేరియబుల్స్ను యాక్సెస్ చేస్తారు (మళ్ళీ, పైథాన్లో వలె).
వ్యూ ఫంక్షన్లు
ఇవి బ్లాక్ చైను యొక్క స్టేట్ను సవరించని ఫంక్షన్లు, అందువల్ల వాటిని బాహ్యంగా పిలిచినట్లయితే ఉచితంగా అమలు చేయవచ్చు. వ్యూ ఫంక్షన్లను ఒక కాంట్రాక్ట్ పిలిచినట్లయితే, అవి ఇప్పటికీ ప్రతి నోడ్లో అమలు చేయబడాలి మరియు అందువల్ల గ్యాస్ ఖర్చు అవుతుంది.
@view
@external
ఒక ఫంక్షన్ నిర్వచనానికి ముందు ఉన్న ఈ కీవర్డ్లు, ఎట్ సైన్ (@)తో ప్రారంభమయ్యేవి, డెకరేషన్స్ అని పిలువబడతాయి. ఒక ఫంక్షన్ను ఏ పరిస్థితులలో పిలవవచ్చో అవి
నిర్దేశిస్తాయి.
@viewఈ ఫంక్షన్ ఒక వ్యూ అని నిర్దేశిస్తుంది.@externalఈ నిర్దిష్ట ఫంక్షన్ను లావాదేవీల ద్వారా మరియు ఇతర కాంట్రాక్ట్ల ద్వారా పిలవవచ్చని నిర్దేశిస్తుంది.
def supportsInterface(_interfaceID: bytes32) -> bool:
పైథాన్కు విరుద్ధంగా, Vyper ఒక స్టాటిక్ టైప్డ్ లాంగ్వేజ్ (opens in a new tab).
డేటా రకాన్ని (opens in a new tab) గుర్తించకుండా మీరు ఒక వేరియబుల్ను లేదా ఫంక్షన్ పారామీటర్ను ప్రకటించలేరు. ఈ సందర్భంలో ఇన్పుట్ పారామీటర్ bytes32, ఇది 256-బిట్ విలువ
(Ethereum వర్చువల్ మెషీన్ యొక్క స్థానిక వర్డ్ సైజ్ 256 బిట్లు). అవుట్పుట్ ఒక బూలియన్
విలువ. సంప్రదాయం ప్రకారం, ఫంక్షన్ పారామీటర్ల పేర్లు అండర్స్కోర్ (_)తో ప్రారంభమవుతాయి.
"""
@dev ఇంటర్ఫేస్ గుర్తింపు ERC-165లో పేర్కొనబడింది.
@param _interfaceID ఇంటర్ఫేస్ యొక్క ఐడి
"""
return self.supportedInterfaces[_interfaceID]
కన్స్ట్రక్టర్ (__init__)లో సెట్ చేయబడిన self.supportedInterfaces HashMap నుండి విలువను తిరిగి ఇవ్వండి.
### వ్యూ ఫంక్షన్లు ###
ఇవి టోకెన్ల గురించిన సమాచారాన్ని వినియోగదారులకు మరియు ఇతర కాంట్రాక్ట్లకు అందుబాటులో ఉంచే వ్యూ ఫంక్షన్లు.
@view
@external
def balanceOf(_owner: address) -> uint256:
"""
@dev `_owner` యాజమాన్యంలోని NFTల సంఖ్యను తిరిగి ఇస్తుంది.
`_owner` సున్నా చిరునామా అయితే త్రో చేస్తుంది. సున్నా చిరునామాకు కేటాయించబడిన NFTలు చెల్లనివిగా పరిగణించబడతాయి.
@param _owner ఎవరి బ్యాలెన్స్ కోసం ప్రశ్నించాలో ఆ చిరునామా.
"""
assert _owner != ZERO_ADDRESS
ఈ లైన్ _owner సున్నా కాదని నిర్ధారిస్తుంది (opens in a new tab). అది అయితే, ఒక లోపం ఉంది మరియు ఆపరేషన్ తిరిగి మార్చబడుతుంది.
return self.ownerToNFTokenCount[_owner]
@view
@external
def ownerOf(_tokenId: uint256) -> address:
"""
@dev NFT యజమాని చిరునామాను తిరిగి ఇస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
@param _tokenId ఒక NFT కోసం ఐడెంటిఫైయర్.
"""
owner: address = self.idToOwner[_tokenId]
# `_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది
assert owner != ZERO_ADDRESS
return owner
Ethereum వర్చువల్ మెషీన్ (evm)లో విలువ నిల్వ చేయని ఏ నిల్వ అయినా సున్నాగా ఉంటుంది.
_tokenId వద్ద టోకెన్ లేకపోతే, self.idToOwner[_tokenId] విలువ సున్నాగా ఉంటుంది. ఆ సందర్భంలో
ఫంక్షన్ తిరిగి మార్చబడుతుంది.
@view
@external
def getApproved(_tokenId: uint256) -> address:
"""
@dev ఒకే NFT కోసం ఆమోదించబడిన చిరునామాను పొందండి.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
@param _tokenId ఆమోదం కోసం ప్రశ్నించాల్సిన NFT యొక్క ఐడి.
"""
# `_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది
assert self.idToOwner[_tokenId] != ZERO_ADDRESS
return self.idToApprovals[_tokenId]
getApproved సున్నాను తిరిగి ఇవ్వగలదని గమనించండి. టోకెన్ చెల్లుబాటు అయితే అది self.idToApprovals[_tokenId]ని తిరిగి ఇస్తుంది.
ఆమోదించేవారు లేకపోతే ఆ విలువ సున్నా.
@view
@external
def isApprovedForAll(_owner: address, _operator: address) -> bool:
"""
@dev `_owner` కోసం `_operator` ఆమోదించబడిన ఆపరేటర్ కాదా అని తనిఖీ చేస్తుంది.
@param _owner NFTల యాజమాన్యంలోని చిరునామా.
@param _operator యజమాని తరపున పనిచేసే చిరునామా.
"""
return (self.ownerToOperators[_owner])[_operator]
ఈ కాంట్రాక్ట్లో _owner యొక్క అన్ని టోకెన్లను నిర్వహించడానికి _operator అనుమతించబడిందా అని ఈ ఫంక్షన్ తనిఖీ చేస్తుంది.
బహుళ ఆపరేటర్లు ఉండవచ్చు కాబట్టి, ఇది రెండు స్థాయిల HashMap.
బదిలీ సహాయక ఫంక్షన్లు
ఈ ఫంక్షన్లు టోకెన్లను బదిలీ చేయడం లేదా నిర్వహించడంలో భాగంగా ఉండే ఆపరేషన్లను అమలు చేస్తాయి.
### TRANSFER FUNCTION HELPERS ###
@view
@internal
ఈ డెకరేషన్, @internal, అంటే ఈ ఫంక్షన్ అదే కాంట్రాక్ట్లోని
ఇతర ఫంక్షన్ల నుండి మాత్రమే అందుబాటులో ఉంటుంది. సంప్రదాయం ప్రకారం, ఈ ఫంక్షన్ పేర్లు కూడా అండర్స్కోర్ (_)తో ప్రారంభమవుతాయి.
def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool:
"""
@dev ఇవ్వబడిన స్పెండర్ ఇవ్వబడిన టోకెన్ ఐడిని బదిలీ చేయగలరా లేదా అని తిరిగి ఇస్తుంది
@param spender ప్రశ్నించాల్సిన స్పెండర్ చిరునామా
@param tokenId బదిలీ చేయవలసిన టోకెన్ యొక్క uint256 ఐడి
@return bool msg.sender ఇవ్వబడిన టోకెన్ ఐడికి ఆమోదించబడిందా,
యజమాని యొక్క ఆపరేటర్ కాదా, లేదా టోకెన్ యజమాని కాదా అని
"""
owner: address = self.idToOwner[_tokenId]
spenderIsOwner: bool = owner == _spender
spenderIsApproved: bool = _spender == self.idToApprovals[_tokenId]
spenderIsApprovedForAll: bool = (self.ownerToOperators[owner])[_spender]
return (spenderIsOwner or spenderIsApproved) or spenderIsApprovedForAll
ఒక చిరునామా ఒక టోకెన్ను బదిలీ చేయడానికి అనుమతించబడటానికి మూడు మార్గాలు ఉన్నాయి:
- చిరునామా టోకెన్ యజమాని
- ఆ టోకెన్ను ఖర్చు చేయడానికి చిరునామా ఆమోదించబడింది
- చిరునామా టోకెన్ యజమానికి ఆపరేటర్
పై ఫంక్షన్ ఒక వ్యూ కావచ్చు ఎందుకంటే ఇది స్టేట్ను మార్చదు. నిర్వహణ ఖర్చులను తగ్గించడానికి, ఏదైనా వ్యూ కాగల ఫంక్షన్ అవశ్యంగా వ్యూ అయి ఉండాలి.
@internal
def _addTokenTo(_to: address, _tokenId: uint256):
"""
@dev ఇవ్వబడిన చిరునామాకు ఒక NFTని జోడించండి
`_tokenId` ఎవరికైనా స్వంతమైతే త్రో చేస్తుంది.
"""
# `_tokenId` ఎవరికైనా స్వంతమైతే త్రో చేస్తుంది
assert self.idToOwner[_tokenId] == ZERO_ADDRESS
# యజమానిని మార్చండి
self.idToOwner[_tokenId] = _to
# కౌంట్ ట్రాకింగ్ను మార్చండి
self.ownerToNFTokenCount[_to] += 1
@internal
def _removeTokenFrom(_from: address, _tokenId: uint256):
"""
@dev ఇవ్వబడిన చిరునామా నుండి ఒక NFTని తీసివేయండి
`_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది.
"""
# `_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది
assert self.idToOwner[_tokenId] == _from
# యజమానిని మార్చండి
self.idToOwner[_tokenId] = ZERO_ADDRESS
# కౌంట్ ట్రాకింగ్ను మార్చండి
self.ownerToNFTokenCount[_from] -= 1
బదిలీతో సమస్య ఉన్నప్పుడు మేము కాల్ను తిరిగి మార్చుతాము.
@internal
def _clearApproval(_owner: address, _tokenId: uint256):
"""
@dev ఇవ్వబడిన చిరునామా యొక్క ఆమోదాన్ని క్లియర్ చేయండి
`_owner` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది.
"""
# `_owner` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది
assert self.idToOwner[_tokenId] == _owner
if self.idToApprovals[_tokenId] != ZERO_ADDRESS:
# ఆమోదాలను రీసెట్ చేయండి
self.idToApprovals[_tokenId] = ZERO_ADDRESS
అవసరమైతే మాత్రమే విలువను మార్చండి. స్టేట్ వేరియబుల్స్ నిల్వలో ఉంటాయి. నిల్వకు వ్రాయడం అనేది EVM (Ethereum వర్చువల్ మెషీన్) చేసే అత్యంత ఖరీదైన ఆపరేషన్లలో ఒకటి (గ్యాస్ పరంగా). అందువల్ల, దానిని తగ్గించడం మంచిది, ఇప్పటికే ఉన్న విలువను వ్రాయడానికి కూడా అధిక ఖర్చు అవుతుంది.
@internal
def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: address):
"""
@dev ఒక NFT బదిలీని అమలు చేయండి.
`msg.sender` ప్రస్తుత యజమాని, అధీకృత ఆపరేటర్ లేదా ఈ NFTకి ఆమోదించబడిన చిరునామా కాకపోతే త్రో చేస్తుంది. (గమనిక: ప్రైవేట్ ఫంక్షన్లో `msg.sender` అనుమతించబడదు కాబట్టి `_sender`ను పాస్ చేయండి.)
`_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది.
`_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
"""
టోకెన్లను బదిలీ చేయడానికి రెండు మార్గాలు (సాధారణ మరియు సురక్షిత) ఉన్నందున మాకు ఈ అంతర్గత ఫంక్షన్ ఉంది, కానీ ఆడిటింగ్ సులభతరం చేయడానికి మేము దానిని చేసే కోడ్లో ఒకే ఒక్క స్థానం కావాలి.
# అవసరాలను తనిఖీ చేయండి
assert self._isApprovedOrOwner(_sender, _tokenId)
# `_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది
assert _to != ZERO_ADDRESS
# ఆమోదాన్ని క్లియర్ చేయండి. `_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది
self._clearApproval(_from, _tokenId)
# NFTని తీసివేయండి. `_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది
self._removeTokenFrom(_from, _tokenId)
# NFTని జోడించండి
self._addTokenTo(_to, _tokenId)
# బదిలీని లాగ్ చేయండి
log Transfer(_from, _to, _tokenId)
Vyperలో ఒక ఈవెంట్ను విడుదల చేయడానికి మీరు log స్టేట్మెంట్ను ఉపయోగిస్తారు (మరిన్ని వివరాల కోసం ఇక్కడ చూడండి (opens in a new tab)).
బదిలీ ఫంక్షన్లు
### TRANSFER FUNCTIONS ###
@external
def transferFrom(_from: address, _to: address, _tokenId: uint256):
"""
@dev `msg.sender` ప్రస్తుత యజమాని, అధీకృత ఆపరేటర్ లేదా ఈ NFTకి ఆమోదించబడిన చిరునామా కాకపోతే త్రో చేస్తుంది.
`_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది.
`_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
@notice `_to` NFTలను స్వీకరించగలదని నిర్ధారించుకోవాల్సిన బాధ్యత కాలర్పై ఉంటుంది, లేకపోతే
అవి శాశ్వతంగా కోల్పోవచ్చు.
@param _from NFT యొక్క ప్రస్తుత యజమాని.
@param _to కొత్త యజమాని.
@param _tokenId బదిలీ చేయవలసిన NFT.
"""
self._transferFrom(_from, _to, _tokenId, msg.sender)
ఈ ఫంక్షన్ మిమ్మల్ని ఏకపక్ష చిరునామాకు బదిలీ చేయడానికి అనుమతిస్తుంది. చిరునామా ఒక వినియోగదారు లేదా టోకెన్లను ఎలా బదిలీ చేయాలో తెలిసిన కాంట్రాక్ట్ కాకపోతే, మీరు బదిలీ చేసే ఏ టోకెన్ అయినా ఆ చిరునామాలో చిక్కుకుపోయి పనికిరానిదిగా ఉంటుంది.
@external
def safeTransferFrom(
_from: address,
_to: address,
_tokenId: uint256,
_data: Bytes[1024]=b""
):
"""
@dev ఒక NFT యాజమాన్యాన్ని ఒక చిరునామా నుండి మరొక చిరునామాకు బదిలీ చేస్తుంది.
`msg.sender` ప్రస్తుత యజమాని, అధీకృత ఆపరేటర్ లేదా ఈ
NFTకి ఆమోదించబడిన చిరునామా కాకపోతే త్రో చేస్తుంది.
`_from` ప్రస్తుత యజమాని కాకపోతే త్రో చేస్తుంది.
`_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
`_to` ఒక స్మార్ట్ కాంట్రాక్ట్ అయితే, అది `_to`పై `onERC721Received`ను పిలుస్తుంది మరియు
తిరిగి వచ్చే విలువ `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` కాకపోతే త్రో చేస్తుంది.
గమనిక: bytes4 అనేది ప్యాడింగ్తో bytes32 ద్వారా సూచించబడుతుంది
@param _from NFT యొక్క ప్రస్తుత యజమాని.
@param _to కొత్త యజమాని.
@param _tokenId బదిలీ చేయవలసిన NFT.
@param _data `_to`కు కాల్లో పంపబడిన, నిర్దిష్ట ఫార్మాట్ లేని అదనపు డేటా.
"""
self._transferFrom(_from, _to, _tokenId, msg.sender)
మొదట బదిలీ చేయడం సరైందే, ఎందుకంటే ఏదైనా సమస్య ఉంటే మేము ఎలాగూ తిరిగి మార్చుతాము, కాబట్టి కాల్లో చేసిన ప్రతిదీ రద్దు చేయబడుతుంది.
if _to.is_contract: # `_to` కాంట్రాక్ట్ చిరునామా కాదా అని తనిఖీ చేయండి
మొదట చిరునామా ఒక కాంట్రాక్ట్ కాదా అని తనిఖీ చేయండి (దానికి కోడ్ ఉంటే). కాకపోతే, అది ఒక వినియోగదారు చిరునామా
అని భావించండి మరియు వినియోగదారు టోకెన్ను ఉపయోగించగలరు లేదా దానిని బదిలీ చేయగలరు. కానీ అది మిమ్మల్ని తప్పుడు భద్రతా భావనలోకి
నెట్టనివ్వకండి. మీరు safeTransferFromతో కూడా టోకెన్లను కోల్పోవచ్చు, ఎవరికీ ప్రైవేట్ కీ తెలియని
చిరునామాకు వాటిని బదిలీ చేస్తే.
returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data)
ఇది ERC-721 టోకెన్లను స్వీకరించగలదా అని చూడటానికి లక్ష్య కాంట్రాక్ట్ను పిలవండి.
# బదిలీ గమ్యస్థానం 'onERC721Received'ను అమలు చేయని కాంట్రాక్ట్ అయితే త్రో చేస్తుంది
assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes32)
గమ్యస్థానం ఒక కాంట్రాక్ట్ అయితే, కానీ అది ERC-721 టోకెన్లను అంగీకరించనిది (లేదా ఈ నిర్దిష్ట బదిలీని అంగీకరించకూడదని నిర్ణయించుకున్నది), తిరిగి మార్చండి.
@external
def approve(_approved: address, _tokenId: uint256):
"""
@dev ఒక NFT కోసం ఆమోదించబడిన చిరునామాను సెట్ చేయండి లేదా పునరుద్ఘాటించండి. సున్నా చిరునామా ఆమోదించబడిన చిరునామా లేదని సూచిస్తుంది.
`msg.sender` ప్రస్తుత NFT యజమాని, లేదా ప్రస్తుత యజమాని యొక్క అధీకృత ఆపరేటర్ కాకపోతే త్రో చేస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది. (గమనిక: ఇది EIPలో వ్రాయబడలేదు)
`_approved` ప్రస్తుత యజమాని అయితే త్రో చేస్తుంది. (గమనిక: ఇది EIPలో వ్రాయబడలేదు)
@param _approved ఇవ్వబడిన NFT ఐడి కోసం ఆమోదించవలసిన చిరునామా.
@param _tokenId ఆమోదించవలసిన టోకెన్ యొక్క ఐడి.
"""
owner: address = self.idToOwner[_tokenId]
# `_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది
assert owner != ZERO_ADDRESS
# `_approved` ప్రస్తుత యజమాని అయితే త్రో చేస్తుంది
assert _approved != owner
సంప్రదాయం ప్రకారం, మీరు ఆమోదించేవారు ఉండకూడదనుకుంటే, మీరు సున్నా చిరునామాను నియమిస్తారు, మిమ్మల్ని కాదు.
# అవసరాలను తనిఖీ చేయండి
senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender
senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender]
assert (senderIsOwner or senderIsApprovedForAll)
ఆమోదాన్ని సెట్ చేయడానికి మీరు యజమాని కావచ్చు, లేదా యజమానిచే అధీకృతం చేయబడిన ఆపరేటర్ కావచ్చు.
# ఆమోదాన్ని సెట్ చేయండి
self.idToApprovals[_tokenId] = _approved
log Approval(owner, _approved, _tokenId)
@external
def setApprovalForAll(_operator: address, _approved: bool):
"""
@dev `msg.sender` యొక్క అన్ని ఆస్తులను నిర్వహించడానికి మూడవ పక్షం ("ఆపరేటర్") కోసం ఆమోదాన్ని
ఎనేబుల్ లేదా డిసేబుల్ చేస్తుంది. ఇది ApprovalForAll ఈవెంట్ను కూడా విడుదల చేస్తుంది.
`_operator` `msg.sender` అయితే త్రో చేస్తుంది. (గమనిక: ఇది EIPలో వ్రాయబడలేదు)
@notice పంపినవారు ఆ సమయంలో ఏ టోకెన్లను కలిగి ఉండకపోయినా ఇది పనిచేస్తుంది.
@param _operator అధీకృత ఆపరేటర్ల సెట్కు జోడించవలసిన చిరునామా.
@param _approved ఆపరేటర్ ఆమోదించబడితే నిజం, ఆమోదాన్ని రద్దు చేయడానికి తప్పు.
"""
# `_operator` `msg.sender` అయితే త్రో చేస్తుంది
assert _operator != msg.sender
self.ownerToOperators[msg.sender][_operator] = _approved
log ApprovalForAll(msg.sender, _operator, _approved)
కొత్త టోకెన్లను మింట్ చేయండి మరియు ఉన్నవాటిని నాశనం చేయండి
కాంట్రాక్ట్ను సృష్టించిన ఖాతా మింటర్, ఇది కొత్త NFTలను మింట్ చేయడానికి
అధీకృతం చేయబడిన సూపర్ వినియోగదారు. అయితే, ఉన్న టోకెన్లను బర్న్ చేయడానికి కూడా ఇది అనుమతించబడదు. యజమాని లేదా యజమానిచే అధీకృతం చేయబడిన సంస్థ
మాత్రమే అలా చేయగలదు.
### MINT & BURN FUNCTIONS ###
@external
def mint(_to: address, _tokenId: uint256) -> bool:
ఈ ఫంక్షన్ ఎల్లప్పుడూ Trueని తిరిగి ఇస్తుంది, ఎందుకంటే ఆపరేషన్ విఫలమైతే అది తిరిగి మార్చబడుతుంది.
"""
@dev టోకెన్లను మింట్ చేయడానికి ఫంక్షన్
`msg.sender` మింటర్ కాకపోతే త్రో చేస్తుంది.
`_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది.
`_tokenId` ఎవరికైనా స్వంతమైతే త్రో చేస్తుంది.
@param _to మింట్ చేయబడిన టోకెన్లను స్వీకరించే చిరునామా.
@param _tokenId మింట్ చేయవలసిన టోకెన్ ఐడి.
@return ఆపరేషన్ విజయవంతమైందా లేదా అని సూచించే బూలియన్.
"""
# `msg.sender` మింటర్ కాకపోతే త్రో చేస్తుంది
assert msg.sender == self.minter
మింటర్ మాత్రమే (ERC-721 కాంట్రాక్ట్ను సృష్టించిన ఖాతా) కొత్త టోకెన్లను మింట్ చేయగలదు. భవిష్యత్తులో మనం మింటర్ గుర్తింపును మార్చాలనుకుంటే ఇది ఒక సమస్య కావచ్చు. ఒక ప్రొడక్షన్ కాంట్రాక్ట్లో మీరు బహుశా మింటర్ అధికారాలను వేరొకరికి బదిలీ చేయడానికి అనుమతించే ఫంక్షన్ను కోరుకుంటారు.
# `_to` సున్నా చిరునామా అయితే త్రో చేస్తుంది
assert _to != ZERO_ADDRESS
# NFTని జోడించండి. `_tokenId` ఎవరికైనా స్వంతమైతే త్రో చేస్తుంది
self._addTokenTo(_to, _tokenId)
log Transfer(ZERO_ADDRESS, _to, _tokenId)
return True
సంప్రదాయం ప్రకారం, కొత్త టోకెన్ల మింటింగ్ సున్నా చిరునామా నుండి బదిలీగా పరిగణించబడుతుంది.
@external
def burn(_tokenId: uint256):
"""
@dev ఒక నిర్దిష్ట ERC721 టోకెన్ను బర్న్ చేస్తుంది.
`msg.sender` ప్రస్తుత యజమాని, అధీకృత ఆపరేటర్ లేదా ఈ
NFTకి ఆమోదించబడిన చిరునామా కాకపోతే త్రో చేస్తుంది.
`_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది.
@param _tokenId బర్న్ చేయవలసిన ERC721 టోకెన్ యొక్క uint256 ఐడి.
"""
# అవసరాలను తనిఖీ చేయండి
assert self._isApprovedOrOwner(msg.sender, _tokenId)
owner: address = self.idToOwner[_tokenId]
# `_tokenId` చెల్లుబాటు అయ్యే NFT కాకపోతే త్రో చేస్తుంది
assert owner != ZERO_ADDRESS
self._clearApproval(owner, _tokenId)
self._removeTokenFrom(owner, _tokenId)
log Transfer(owner, ZERO_ADDRESS, _tokenId)
ఒక టోకెన్ను బదిలీ చేయడానికి అనుమతించబడిన ఎవరైనా దానిని బర్న్ చేయడానికి అనుమతించబడతారు. బర్న్ సున్నా చిరునామాకు బదిలీకి సమానంగా కనిపించినప్పటికీ, సున్నా చిరునామా వాస్తవానికి టోకెన్ను స్వీకరించదు. ఇది టోకెన్ కోసం ఉపయోగించిన మొత్తం నిల్వను ఖాళీ చేయడానికి మాకు అనుమతిస్తుంది, ఇది లావాదేవీ యొక్క గ్యాస్ ఖర్చును తగ్గిస్తుంది.
ఈ కాంట్రాక్ట్ను ఉపయోగించడం
సోలిడిటీకి విరుద్ధంగా, Vyperకు ఇన్హెరిటెన్స్ లేదు. కోడ్ను స్పష్టంగా మరియు అందువల్ల సురక్షితం చేయడానికి ఇది ఉద్దేశపూర్వక డిజైన్ ఎంపిక. కాబట్టి మీ స్వంత Vyper ERC-721 కాంట్రాక్ట్ను సృష్టించడానికి మీరు ఈ కాంట్రాక్ట్ను తీసుకుని, మీకు కావలసిన వ్యాపార తర్కాన్ని అమలు చేయడానికి దాన్ని సవరించండి.
ముగింపు
సమీక్ష కోసం, ఈ కాంట్రాక్ట్లోని కొన్ని ముఖ్యమైన ఆలోచనలు ఇక్కడ ఉన్నాయి:
- సురక్షిత బదిలీతో ERC-721 టోకెన్లను స్వీకరించడానికి, కాంట్రాక్ట్లు
ERC721Receiverఇంటర్ఫేస్ను అమలు చేయాలి. - మీరు సురక్షిత బదిలీని ఉపయోగించినప్పటికీ, ప్రైవేట్ కీ తెలియని చిరునామాకు పంపితే టోకెన్లు ఇప్పటికీ చిక్కుకుపోవచ్చు.
- ఒక ఆపరేషన్తో సమస్య ఉన్నప్పుడు, కేవలం వైఫల్య విలువను తిరిగి ఇచ్చే బదులు,
కాల్ను
revertచేయడం మంచిది. - ERC-721 టోకెన్లు వాటికి యజమాని ఉన్నప్పుడు ఉంటాయి.
- ఒక NFTని బదిలీ చేయడానికి అధీకృతం కావడానికి మూడు మార్గాలు ఉన్నాయి. మీరు యజమాని కావచ్చు, ఒక నిర్దిష్ట టోకెన్ కోసం ఆమోదించబడవచ్చు, లేదా యజమాని యొక్క అన్ని టోకెన్లకు ఆపరేటర్ కావచ్చు.
- గత ఈవెంట్లు బ్లాక్ చైను వెలుపల మాత్రమే కనిపిస్తాయి. బ్లాక్ చైను లోపల నడుస్తున్న కోడ్ వాటిని చూడలేదు.
ఇప్పుడు వెళ్లి సురక్షితమైన Vyper కాంట్రాక్ట్లను అమలు చేయండి.
నా మరిన్ని పనుల కోసం ఇక్కడ చూడండి (opens in a new tab).
పేజీ చివరి నవీకరణ: 28 ఏప్రిల్, 2026