ERC-20 ఒప్పంద వాక్-త్రూ
పరిచయం
Ethereumకు అత్యంత సాధారణ ఉపయోగాలలో ఒకటి ఒక సమూహం వ్యాపారం చేయగల టోకెన్ను సృష్టించడం, ఒక రకంగా చెప్పాలంటే వారి స్వంత కరెన్సీ. ఈ టోకెన్లు సాధారణంగా ఒక ప్రామాణికాన్ని అనుసరిస్తాయి, ERC-20. ఈ ప్రమాణం, లిక్విడిటీ పూల్స్ మరియు వాలెట్లు వంటి సాధనాలను రాయడానికి వీలు కల్పిస్తుంది, ఇవి అన్ని ERC-20 టోకెన్లతో పనిచేస్తాయి. ఈ వ్యాసంలో మేము OpenZeppelin సాలిడిటీ ERC20 అమలు (opens in a new tab)ను, అలాగే ఇంటర్ఫేస్ నిర్వచనం (opens in a new tab)ను విశ్లేషిస్తాము.
ఇది వ్యాఖ్యానించబడిన సోర్స్ కోడ్. మీరు ERC-20ని అమలు చేయాలనుకుంటే, ఈ ట్యుటోరియల్ చదవండి (opens in a new tab).
ఇంటర్ఫేస్
ERC-20 వంటి ప్రమాణం యొక్క ఉద్దేశ్యం, వాలెట్లు మరియు వికేంద్రీకృత ఎక్స్ఛేంజీల వంటి అప్లికేషన్లలో పరస్పరం పనిచేసే అనేక టోకెన్ల అమలులను అనుమతించడం. దానిని సాధించడానికి, మేము ఒక ఇంటర్ఫేస్ను (opens in a new tab) సృష్టిస్తాము. టోకెన్ ఒప్పందాన్ని ఉపయోగించాల్సిన ఏదైనా కోడ్, ఇంటర్ఫేస్లో అదే నిర్వచనాలను ఉపయోగించవచ్చు మరియు దానిని ఉపయోగించే అన్ని టోకెన్ ఒప్పందాలతో అనుకూలంగా ఉంటుంది, అది MetaMask వంటి వాలెట్ అయినా, etherscan.io వంటి డాప్ అయినా, లేదా లిక్విడిటీ పూల్ వంటి విభిన్న ఒప్పందం అయినా.
మీరు అనుభవజ్ఞుడైన ప్రోగ్రామర్ అయితే, మీరు Java (opens in a new tab)లో లేదా C హెడర్ ఫైల్స్లో (opens in a new tab) కూడా ఇలాంటి నిర్మాణాలను చూసినట్లు గుర్తుండే ఉంటుంది.
ఇది OpenZeppelin నుండి వచ్చిన ERC-20 ఇంటర్ఫేస్ (opens in a new tab) యొక్క నిర్వచనం. ఇది మానవులు చదవగలిగే ప్రమాణం (opens in a new tab) యొక్క సాలిడిటీ కోడ్లోకి అనువాదం. వాస్తవానికి, ఏదైనా ఎలా చేయాలో ఇంటర్ఫేస్ స్వయంగా నిర్వచించదు. అది కింద ఉన్న ఒప్పంద సోర్స్ కోడ్లో వివరించబడింది.
1// SPDX-License-Identifier: MITసాలిడిటీ ఫైళ్లు ఒక లైసెన్స్ ఐడెంటిఫైయర్ను కలిగి ఉండాలి. మీరు ఇక్కడ లైసెన్స్ల జాబితాను చూడవచ్చు (opens in a new tab). మీకు విభిన్న లైసెన్స్ అవసరమైతే, వ్యాఖ్యలలో దానిని వివరించండి.
1pragma solidity >=0.6.0 <0.8.0;సాలిడిటీ భాష ఇంకా వేగంగా అభివృద్ధి చెందుతోంది, మరియు కొత్త వెర్షన్లు పాత కోడ్తో అనుకూలంగా ఉండకపోవచ్చు (ఇక్కడ చూడండి (opens in a new tab)). అందువల్ల, కేవలం భాష యొక్క కనీస వెర్షన్ను మాత్రమే కాకుండా, గరిష్ట వెర్షన్ను కూడా పేర్కొనడం మంచిది, ఇది మీరు కోడ్ను పరీక్షించిన తాజాది.
1/**2 * @dev EIPలో నిర్వచించిన విధంగా ERC20 ప్రమాణం యొక్క ఇంటర్ఫేస్.3 */వ్యాఖ్యలోని @dev అనేది NatSpec ఫార్మాట్ (opens in a new tab)లో ఒక భాగం, ఇది సోర్స్ కోడ్ నుండి
డాక్యుమెంటేషన్ను రూపొందించడానికి ఉపయోగపడుతుంది.
1interface IERC20 {సంప్రదాయం ప్రకారం, ఇంటర్ఫేస్ పేర్లు Iతో ప్రారంభమవుతాయి.
1 /**2 * @dev ఉనికిలో ఉన్న టోకెన్ల మొత్తాన్ని అందిస్తుంది.3 */4 function totalSupply() external view returns (uint256);ఈ ఫంక్షన్ external, అంటే ఇది ఒప్పందం బయట నుండి మాత్రమే పిలువబడుతుంది (opens in a new tab).
ఇది ఒప్పందంలోని టోకెన్ల మొత్తం సరఫరాను తిరిగి ఇస్తుంది. ఈ విలువ ఇతీరియములో అత్యంత సాధారణ రకం, గుర్తులేని 256 బిట్స్ (256 బిట్స్ EVM యొక్క స్థానిక పదం పరిమాణం) ఉపయోగించి తిరిగి ఇవ్వబడుతుంది. ఈ ఫంక్షన్ కూడా ఒక view, అంటే ఇది స్టేట్ను మార్చదు, కాబట్టి దీనిని బ్లాక్ చైనులోని ప్రతి నోడ్ అమలు చేసే బదులు ఒకే నోడ్లో అమలు చేయవచ్చు. ఈ రకమైన ఫంక్షన్ లావాదేవీని సృష్టించదు మరియు గ్యాస్ ఖర్చు కాదు.
గమనిక: సిద్ధాంతపరంగా, ఒక ఒప్పందం యొక్క సృష్టికర్త నిజమైన విలువ కంటే తక్కువ మొత్తం సరఫరాను తిరిగి ఇవ్వడం ద్వారా మోసం చేయవచ్చు, ప్రతి టోకెన్ వాస్తవానికి ఉన్నదానికంటే విలువైనదిగా కనిపించేలా చేస్తుంది. అయితే, ఆ భయం బ్లాక్ చైను యొక్క నిజమైన స్వభావాన్ని విస్మరిస్తుంది. బ్లాక్ చైనులో జరిగే ప్రతిదీ ప్రతి నోడ్ ద్వారా ధృవీకరించబడుతుంది. దీనిని సాధించడానికి, ప్రతి ఒప్పందం యొక్క మెషిన్ లాంగ్వేజ్ కోడ్ మరియు నిల్వ ప్రతి నోడ్లో అందుబాటులో ఉంటుంది. మీ ఒప్పందం కోసం మీరు సాలిడిటీ కోడ్ను ప్రచురించాల్సిన అవసరం లేనప్పటికీ, మీరు సోర్స్ కోడ్ను మరియు అది కంపైల్ చేయబడిన సాలిడిటీ వెర్షన్ను ప్రచురిస్తే తప్ప మిమ్మల్ని ఎవరూ సీరియస్గా తీసుకోరు, తద్వారా మీరు అందించిన మెషిన్ లాంగ్వేజ్ కోడ్తో దానిని సరిపోల్చి ధృవీకరించవచ్చు. ఉదాహరణకు, ఈ ఒప్పందం (opens in a new tab) చూడండి.
1 /**2 * @dev `ఖాతా` యాజమాన్యంలో ఉన్న టోకెన్ల మొత్తాన్ని అందిస్తుంది.3 */4 function balanceOf(address account) external view returns (uint256);పేరు చెప్పినట్లు, balanceOf ఒక ఖాతా యొక్క బ్యాలెన్స్ను తిరిగి ఇస్తుంది. ఇతీరియము ఖాతాలు సాలిడిటీలో చిరునామా రకం ఉపయోగించి గుర్తించబడతాయి, ఇది 160 బిట్లను కలిగి ఉంటుంది.
ఇది external మరియు view కూడా.
1 /**2 * @dev కాలర్ ఖాతా నుండి `గ్రహీత`కు `మొత్తం` టోకెన్లను తరలిస్తుంది.3 *4 * ఆపరేషన్ విజయవంతమైందో లేదో సూచించే బూలియన్ విలువను తిరిగి ఇస్తుంది.5 *6 * ఒక {Transfer} ఈవెంట్ను విడుదల చేస్తుంది.7 */8 function transfer(address recipient, uint256 amount) external returns (bool);బదిలీ ఫంక్షన్ కాలర్ నుండి వేరే చిరునామాకు టోకెన్లను బదిలీ చేస్తుంది. ఇందులో స్టేట్ మార్పు ఉంటుంది, కాబట్టి ఇది view కాదు.
ఒక వినియోగదారు ఈ ఫంక్షన్ను పిలిచినప్పుడు, అది లావాదేవీని సృష్టిస్తుంది మరియు గ్యాస్ ఖర్చవుతుంది. ఇది బ్లాక్ చైనులో ఉన్న ప్రతిఒక్కరికీ ఈ సంఘటన గురించి తెలియజేయడానికి Transfer అనే ఈవెంట్ను కూడా విడుదల చేస్తుంది.
ఫంక్షన్ రెండు విభిన్న రకాల కాలర్ల కోసం రెండు రకాల అవుట్పుట్లను కలిగి ఉంది:
- యూజర్ ఇంటర్ఫేస్ నుండి నేరుగా ఫంక్షన్ను కాల్ చేసే వినియోగదారులు. సాధారణంగా వినియోగదారు లావాదేవీని సమర్పించి, ప్రతిస్పందన కోసం వేచి ఉండడు, దీనికి నిరవధిక సమయం పట్టవచ్చు. లావాదేవీ రసీదు (ఇది లావాదేవీ హాష్ ద్వారా గుర్తించబడుతుంది) కోసం వెతకడం ద్వారా లేదా
Transferఈవెంట్ కోసం వెతకడం ద్వారా వినియోగదారు ఏమి జరిగిందో చూడవచ్చు. - మొత్తం లావాదేవీలో భాగంగా ఫంక్షన్ను కాల్ చేసే ఇతర ఒప్పందాలు. ఆ ఒప్పందాలు ఫలితాన్ని వెంటనే పొందుతాయి, ఎందుకంటే అవి అదే లావాదేవీలో నడుస్తాయి, కాబట్టి అవి ఫంక్షన్ రిటర్న్ విలువను ఉపయోగించుకోవచ్చు.
ఒప్పందం యొక్క స్టేట్ను మార్చే ఇతర ఫంక్షన్ల ద్వారా కూడా అదే రకమైన అవుట్పుట్ సృష్టించబడుతుంది.
అలవెన్సులు ఒక ఖాతాను వేరొక యజమానికి చెందిన కొన్ని టోకెన్లను ఖర్చు చేయడానికి అనుమతిస్తాయి. ఇది ఉపయోగకరంగా ఉంటుంది, ఉదాహరణకు, అమ్మకందారులుగా వ్యవహరించే ఒప్పందాల కోసం. ఒప్పందాలు ఈవెంట్లను పర్యవేక్షించలేవు, కాబట్టి కొనుగోలుదారు నేరుగా అమ్మకందారు ఒప్పందానికి టోకెన్లను బదిలీ చేస్తే, ఆ ఒప్పందానికి అది చెల్లించబడిందని తెలియదు. బదులుగా, కొనుగోలుదారు అమ్మకందారు ఒప్పందాన్ని ఒక నిర్దిష్ట మొత్తాన్ని ఖర్చు చేయడానికి అనుమతిస్తాడు, మరియు అమ్మకందారు ఆ మొత్తాన్ని బదిలీ చేస్తాడు. ఇది అమ్మకందారు ఒప్పందం పిలిచే ఒక ఫంక్షన్ ద్వారా జరుగుతుంది, కాబట్టి అమ్మకందారు ఒప్పందం అది విజయవంతమైందో లేదో తెలుసుకోగలదు.
1 /**2 * @dev `ఖర్చుదారు` {transferFrom} ద్వారా `యజమాని` తరపున ఖర్చు చేయడానికి అనుమతించబడే మిగిలిన టోకెన్ల సంఖ్యను తిరిగి ఇస్తుంది. ఇది డిఫాల్ట్గా సున్నాగా ఉంటుంది.3 *4 * {approve} లేదా {transferFrom} పిలిచినప్పుడు ఈ విలువ మారుతుంది.5 */6 function allowance(address owner, address spender) external view returns (uint256);allowance ఫంక్షన్ ఒక చిరునామా (యజమాని) మరొక చిరునామా (ఖర్చుదారు)కు ఎంత ఖర్చు చేయడానికి అనుమతి ఇస్తుందో చూడటానికి ఎవరికైనా అనుమతిస్తుంది.
1 /**2 * @dev కాలర్ యొక్క టోకెన్లపై `ఖర్చుదారు` యొక్క అలవెన్సుగా `మొత్తాన్ని` సెట్ చేస్తుంది.3 *4 * ఆపరేషన్ విజయవంతమైందో లేదో సూచించే బూలియన్ విలువను తిరిగి ఇస్తుంది.5 *6 * ముఖ్యం: ఈ పద్ధతితో అలవెన్సును మార్చడం వలన దురదృష్టవశాత్తు లావాదేవీల క్రమం ద్వారా ఎవరైనా పాత మరియు కొత్త అలవెన్సు రెండింటినీ ఉపయోగించుకునే ప్రమాదం ఉందని తెలుసుకోండి. ఈ రేస్ కండిషన్ను తగ్గించడానికి ఒక సాధ్యమైన పరిష్కారం మొదట ఖర్చుదారు యొక్క అలవెన్సును 0కి తగ్గించి, ఆపై కావలసిన విలువను సెట్ చేయడం: https://github.com/ethereum/EIPs/issues/20#issuecomment-2635247297 *8 * ఒక {Approval} ఈవెంట్ను విడుదల చేస్తుంది.9 */10 function approve(address spender, uint256 amount) external returns (bool);అన్నీ చూపించుapprove ఫంక్షన్ ఒక అలవెన్సును సృష్టిస్తుంది. దానిని ఎలా దుర్వినియోగం చేయవచ్చనే సందేశాన్ని తప్పకుండా చదవండి. ఇతీరియములో మీరు మీ స్వంత లావాదేవీల క్రమాన్ని నియంత్రించగలరు,
కానీ ఇతర వ్యక్తుల లావాదేవీలు ఏ క్రమంలో అమలు చేయబడతాయో మీరు నియంత్రించలేరు, అవతలి పక్షం యొక్క లావాదేవీ జరిగిందని మీరు చూసే వరకు మీరు మీ స్వంత లావాదేవీని సమర్పించకపోతే తప్ప.
1 /**2 * @dev `అలవెన్స్` మెకానిజం ఉపయోగించి `పంపినవారి` నుండి `గ్రహీత`కు `మొత్తం` టోకెన్లను తరలిస్తుంది.3 * ఆ తర్వాత కాలర్ యొక్క `అలవెన్స్` నుండి `amount` తీసివేయబడుతుంది.4 *5 * ఆపరేషన్ విజయవంతమైందో లేదో సూచించే బూలియన్ విలువను తిరిగి ఇస్తుంది.6 *7 * ఒక {Transfer} ఈవెంట్ను విడుదల చేస్తుంది.8 */9 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);అన్నీ చూపించుచివరగా, అలవెన్స్ను వాస్తవంగా ఖర్చు చేయడానికి ఖర్చు చేసేవారు transferFromను ఉపయోగిస్తారు.
1 /**2 * @dev ఒక ఖాతా (`from`) నుండి మరొక ఖాతాకు (`to`) `విలువ` టోకెన్లను తరలించినప్పుడు విడుదల చేయబడుతుంది.3 *4 * `విలువ` సున్నాగా ఉండవచ్చని గమనించండి.5 */6 event Transfer(address indexed from, address indexed to, uint256 value);78 /**9 * @dev {approve}కు కాల్ చేయడం ద్వారా `యజమాని` కోసం `ఖర్చు చేసేవారి` యొక్క అలవెన్స్ సెట్ చేయబడినప్పుడు విడుదల చేయబడుతుంది.10 * `విలువ` అనేది కొత్త అలవెన్స్.11 */12 event Approval(address indexed owner, address indexed spender, uint256 value);13}అన్నీ చూపించుERC-20 కాంట్రాక్ట్ యొక్క స్థితి మారినప్పుడు ఈ ఈవెంట్లు విడుదల చేయబడతాయి.
వాస్తవ కాంట్రాక్ట్
ఇది ERC-20 ప్రమాణాన్ని అమలు చేసే వాస్తవ కాంట్రాక్ట్, ఇక్కడ నుండి తీసుకోబడింది (opens in a new tab). ఇది ఉన్నది ఉన్నట్లుగా ఉపయోగించడానికి ఉద్దేశించబడలేదు, కానీ మీరు దాని నుండి ఉపయోగపడే విధంగా విస్తరించడానికి వారసత్వంగా (opens in a new tab) పొందవచ్చు.
1// SPDX-License-Identifier: MIT2pragma solidity >=0.6.0 <0.8.0;
దిగుమతి ప్రకటనలు
పైన ఉన్న ఇంటర్ఫేస్ నిర్వచనాలతో పాటు, కాంట్రాక్ట్ నిర్వచనం రెండు ఇతర ఫైల్లను దిగుమతి చేస్తుంది:
12import "../../GSN/Context.sol";3import "./IERC20.sol";4import "../../math/SafeMath.sol";GSN/Context.solఅనేది ఈథర్ లేని వినియోగదారులు బ్లాక్చెయిన్ను ఉపయోగించడానికి అనుమతించే ఒక వ్యవస్థ అయిన OpenGSN (opens in a new tab) ను ఉపయోగించడానికి అవసరమైన నిర్వచనాలు. ఇది పాత వెర్షన్ అని గమనించండి, మీరు OpenGSNతో ఇంటిగ్రేట్ చేయాలనుకుంటే ఈ ట్యుటోరియల్ని ఉపయోగించండి (opens in a new tab).- SafeMath లైబ్రరీ (opens in a new tab), ఇది Solidity వెర్షన్లు <0.8.0 కోసం అంకగణిత ఓవర్ఫ్లోలు/అండర్ఫ్లోలను నివారిస్తుంది. Solidity ≥0.8.0 లో, అంకగణిత కార్యకలాపాలు ఓవర్ఫ్లో/అండర్ఫ్లో అయినప్పుడు స్వయంచాలకంగా తిరిగి వస్తాయి, ఇది SafeMathను అనవసరంగా చేస్తుంది. ఈ కాంట్రాక్ట్ పాత కంపైలర్ వెర్షన్లతో వెనుకకు అనుకూలత కోసం SafeMathను ఉపయోగిస్తుంది.
ఈ వ్యాఖ్య కాంట్రాక్ట్ యొక్క ఉద్దేశ్యాన్ని వివరిస్తుంది.
1/**2 * @dev {IERC20} ఇంటర్ఫేస్ యొక్క అమలు.3 *4 * ఈ అమలు టోకెన్లు సృష్టించబడే విధానానికి అజ్ఞాతంగా ఉంటుంది. దీని అర్థం {_mint} ఉపయోగించి ఉత్పన్నమైన కాంట్రాక్ట్లో సరఫరా యంత్రాంగాన్ని జోడించాలి.5 * సాధారణ యంత్రాంగం కోసం {ERC20PresetMinterPauser} చూడండి.6 *7 * చిట్కా: వివరణాత్మక రచన కోసం మా గైడ్ చూడండి8 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[సరఫరా యంత్రాంగాలను ఎలా అమలు చేయాలి].9 *10 * మేము సాధారణ OpenZeppelin మార్గదర్శకాలను అనుసరించాము: వైఫల్యంపై `false` తిరిగి ఇవ్వడానికి బదులుగా ఫంక్షన్లు తిరిగి వస్తాయి. అయినప్పటికీ ఈ ప్రవర్తన సాంప్రదాయబద్ధమైనది11 * మరియు ERC20 అప్లికేషన్ల అంచనాలతో విభేదించదు.12 *13 * అదనంగా, {transferFrom}కు కాల్లపై {Approval} ఈవెంట్ విడుదల చేయబడుతుంది.14 * ఇది చెప్పబడిన ఈవెంట్లను వినడం ద్వారా అన్ని ఖాతాల కోసం అలవెన్స్ను పునర్నిర్మించడానికి అప్లికేషన్లను అనుమతిస్తుంది. EIP యొక్క ఇతర అమలులు ఈ ఈవెంట్లను విడుదల చేయకపోవచ్చు,15 * ఎందుకంటే స్పెసిఫికేషన్ ద్వారా ఇది అవసరం లేదు.16 *17 * చివరగా, అలవెన్స్లను సెట్ చేయడం చుట్టూ ఉన్న ప్రసిద్ధ సమస్యలను తగ్గించడానికి ప్రామాణికం కాని {decreaseAllowance} మరియు {increaseAllowance}18 * ఫంక్షన్లు జోడించబడ్డాయి. {IERC20-approve} చూడండి.19 */అన్నీ చూపించుకాంట్రాక్ట్ నిర్వచనం
1contract ERC20 is Context, IERC20 {ఈ లైన్ వారసత్వాన్ని నిర్దేశిస్తుంది, ఈ సందర్భంలో OpenGSN కోసం పైన ఉన్న IERC20 మరియు Context నుండి.
1 using SafeMath for uint256;ఈ లైన్ SafeMath లైబ్రరీని uint256 రకానికి జతచేస్తుంది. మీరు ఈ లైబ్రరీని ఇక్కడ (opens in a new tab) కనుగొనవచ్చు.
వేరియబుల్ నిర్వచనాలు
ఈ నిర్వచనాలు కాంట్రాక్ట్ యొక్క స్థితి వేరియబుల్స్ను నిర్దేశిస్తాయి. ఈ వేరియబుల్స్ privateగా ప్రకటించబడ్డాయి, కానీ దాని అర్థం బ్లాక్చెయిన్లోని ఇతర కాంట్రాక్టులు వాటిని చదవలేవు అని మాత్రమే. బ్లాక్చెయిన్లో రహస్యాలు లేవు, ప్రతి నోడ్లోని సాఫ్ట్వేర్ ప్రతి బ్లాక్లో ప్రతి కాంట్రాక్ట్ యొక్క స్థితిని కలిగి ఉంటుంది. సంప్రదాయం ప్రకారం, స్థితి వేరియబుల్స్కు _<something> అని పేరు పెట్టారు.
మొదటి రెండు వేరియబుల్స్ మ్యాపింగ్లు (opens in a new tab), అంటే అవి దాదాపుగా అసోసియేటివ్ అర్రేల (opens in a new tab) వలె ప్రవర్తిస్తాయి, కీలు సంఖ్యా విలువలుగా ఉండటం మినహా. డిఫాల్ట్ (సున్నా) నుండి భిన్నమైన విలువలను కలిగి ఉన్న ఎంట్రీల కోసం మాత్రమే నిల్వ కేటాయించబడుతుంది.
1 mapping (address => uint256) private _balances;మొదటి మ్యాపింగ్, _balances, ఈ టోకెన్ యొక్క చిరునామాలు మరియు వాటి సంబంధిత బ్యాలెన్స్లు. బ్యాలెన్స్ను యాక్సెస్ చేయడానికి, ఈ సింటాక్స్ను ఉపయోగించండి: _balances[<address>].
1 mapping (address => mapping (address => uint256)) private _allowances;ఈ వేరియబుల్, _allowances, ముందుగా వివరించిన అలవెన్సులను నిల్వ చేస్తుంది. మొదటి ఇండెక్స్ టోకెన్ల యజమాని, మరియు రెండవది అలవెన్స్ ఉన్న కాంట్రాక్ట్. చిరునామా B యొక్క ఖాతా నుండి చిరునామా A ఖర్చు చేయగల మొత్తాన్ని యాక్సెస్ చేయడానికి, _allowances[B][A] ఉపయోగించండి.
1 uint256 private _totalSupply;పేరు సూచించినట్లుగా, ఈ వేరియబుల్ టోకెన్ల మొత్తం సరఫరాను ట్రాక్ చేస్తుంది.
1 string private _name;2 string private _symbol;3 uint8 private _decimals;ఈ మూడు వేరియబుల్స్ చదవడానికి వీలుగా మెరుగుపరచడానికి ఉపయోగించబడతాయి. మొదటి రెండు స్వీయ-వివరణాత్మకమైనవి, కానీ _decimals కాదు.
ఒకవైపు, ఇతీరియములో ఫ్లోటింగ్ పాయింట్ లేదా భిన్నమైన వేరియబుల్స్ లేవు. మరోవైపు, మానవులు టోకెన్లను విభజించగలగడాన్ని ఇష్టపడతారు. కరెన్సీ కోసం ప్రజలు బంగారంపై స్థిరపడటానికి ఒక కారణం ఏమిటంటే, ఎవరైనా ఆవు విలువ గల బాతును కొనాలనుకున్నప్పుడు చిల్లర ఇవ్వడం కష్టంగా ఉండేది.
పరిష్కారం పూర్ణాంకాలను ట్రాక్ చేయడం, కానీ నిజమైన టోకెన్కు బదులుగా దాదాపు విలువలేని భిన్నమైన టోకెన్ను లెక్కించడం. ఈథర్ విషయంలో, భిన్నమైన టోకెన్ను wei అని పిలుస్తారు, మరియు 10^18 wei ఒక ETHకి సమానం. రాసే సమయంలో, 10,000,000,000,000 wei సుమారుగా ఒక US లేదా యూరో సెంట్కు సమానం.
అప్లికేషన్లు టోకెన్ బ్యాలెన్స్ను ఎలా ప్రదర్శించాలో తెలుసుకోవాలి. ఒక వినియోగదారుడికి 3,141,000,000,000,000,000 wei ఉంటే, అది 3.14 ETHనా? 31.41 ETH? 3,141 ETH? ఈథర్ విషయంలో ఇది ETHకి 10^18 weiగా నిర్వచించబడింది, కానీ మీ టోకెన్ కోసం మీరు వేరే విలువను ఎంచుకోవచ్చు. టోకెన్ను విభజించడం అర్థవంతం కాకపోతే, మీరు సున్నా _decimals విలువను ఉపయోగించవచ్చు. మీరు ETH వలె అదే ప్రమాణాన్ని ఉపయోగించాలనుకుంటే, 18 విలువను ఉపయోగించండి.
నిర్మాణకర్త
1 /**2 * @dev {name} మరియు {symbol} కోసం విలువలను సెట్ చేస్తుంది, {decimals} ను 18 యొక్క డిఫాల్ట్ విలువతో ప్రారంభిస్తుంది.3 *4 * {decimals} కోసం వేరే విలువను ఎంచుకోవడానికి, {_setupDecimals} ఉపయోగించండి.5 *6 * ఈ మూడు విలువలు మార్పులేనివి: అవి నిర్మాణం సమయంలో ఒకసారి మాత్రమే సెట్ చేయబడతాయి.7 */8 constructor (string memory name_, string memory symbol_) public {9 // Solidity ≥0.7.0 లో, 'public' అంతర్లీనంగా ఉంటుంది మరియు దానిని వదిలివేయవచ్చు.1011 _name = name_;12 _symbol = symbol_;13 _decimals = 18;14 }అన్నీ చూపించుకాంట్రాక్ట్ మొదటిసారి సృష్టించబడినప్పుడు నిర్మాణకర్తను పిలుస్తారు. సంప్రదాయం ప్రకారం, ఫంక్షన్ పారామితులకు <something>_ అని పేరు పెట్టారు.
వినియోగదారు ఇంటర్ఫేస్ ఫంక్షన్లు
1 /**2 * @dev టోకెన్ పేరును తిరిగి ఇస్తుంది.3 */4 function name() public view returns (string memory) {5 return _name;6 }78 /**9 * @dev టోకెన్ యొక్క చిహ్నాన్ని తిరిగి ఇస్తుంది, సాధారణంగా పేరు యొక్క చిన్న వెర్షన్.10 */11 function symbol() public view returns (string memory) {12 return _symbol;13 }1415 /**16 * @dev దాని వినియోగదారు ప్రాతినిధ్యాన్ని పొందడానికి ఉపయోగించే దశాంశాల సంఖ్యను తిరిగి ఇస్తుంది.17 * ఉదాహరణకు, `decimals` `2` కి సమానమైతే, `505` టోకెన్ల బ్యాలెన్స్ వినియోగదారునికి `5,05` (`505 / 10 ** 2`)గా ప్రదర్శించబడాలి.18 *19 * టోకెన్లు సాధారణంగా 18 విలువను ఎంచుకుంటాయి, ఈథర్ మరియు wei మధ్య సంబంధాన్ని అనుకరిస్తాయి. {_setupDecimals} పిలవబడకపోతే, {ERC20} ఉపయోగించే విలువ ఇదే.20 *21 * గమనిక: ఈ సమాచారం కేవలం _ప్రదర్శన_ ప్రయోజనాల కోసం మాత్రమే ఉపయోగించబడుతుంది: ఇది22 * {IERC20-balanceOf} మరియు {IERC20-transfer}తో సహా కాంట్రాక్ట్ యొక్క ఏ అంకగణితాన్ని ఏ విధంగానూ ప్రభావితం చేయదు.23 */24 function decimals() public view returns (uint8) {25 return _decimals;26 }అన్నీ చూపించుఈ ఫంక్షన్లు, name, symbol, మరియు decimals వినియోగదారు ఇంటర్ఫేస్లకు మీ కాంట్రాక్ట్ గురించి తెలుసుకోవడానికి సహాయపడతాయి, తద్వారా వారు దానిని సరిగ్గా ప్రదర్శించగలరు.
రిటర్న్ రకం string memory, అంటే మెమరీలో నిల్వ చేయబడిన స్ట్రింగ్ను తిరిగి ఇవ్వడం. స్ట్రింగ్ల వంటి వేరియబుల్స్ను మూడు ప్రదేశాలలో నిల్వ చేయవచ్చు:
| జీవితకాలం | కాంట్రాక్ట్ యాక్సెస్ | గ్యాస్ ఖర్చు | |
|---|---|---|---|
| మెమరీ | ఫంక్షన్ కాల్ | చదవండి/రాయండి | పదులు లేదా వందలు (అధిక ప్రదేశాలకు ఎక్కువ) |
| కాల్డేటా | ఫంక్షన్ కాల్ | చదవడానికి మాత్రమే | రిటర్న్ రకంగా ఉపయోగించలేము, కేవలం ఫంక్షన్ పారామీటర్ రకంగా మాత్రమే |
| స్టోరేజ్ | మారే వరకు | చదవండి/రాయండి | అధికం (చదవడానికి 800, రాయడానికి 20k) |
ఈ సందర్భంలో, memory ఉత్తమ ఎంపిక.
టోకెన్ సమాచారం చదవండి
ఇవి టోకెన్ గురించి సమాచారాన్ని అందించే ఫంక్షన్లు, మొత్తం సరఫరా లేదా ఖాతా యొక్క బ్యాలెన్స్.
1 /**2 * @dev {IERC20-totalSupply} చూడండి.3 */4 function totalSupply() public view override returns (uint256) {5 return _totalSupply;6 }totalSupply ఫంక్షన్ టోకెన్ల మొత్తం సరఫరాను తిరిగి ఇస్తుంది.
1 /**2 * @dev {IERC20-balanceOf} చూడండి.3 */4 function balanceOf(address account) public view override returns (uint256) {5 return _balances[account];6 }ఒక ఖాతా యొక్క బ్యాలెన్స్ చదవండి. ఎవరైనా ఇతరుల ఖాతా బ్యాలెన్స్ను పొందడానికి అనుమతించబడతారని గమనించండి. ఈ సమాచారాన్ని దాచడానికి ప్రయత్నించడంలో అర్థం లేదు, ఎందుకంటే ఇది ఏమైనప్పటికీ ప్రతి నోడ్లో అందుబాటులో ఉంటుంది. బ్లాక్చెయిన్లో రహస్యాలు లేవు.
టోకెన్లను బదిలీ చేయండి
1 /**2 * @dev {IERC20-transfer} చూడండి.3 *4 * అవసరాలు:5 *6 * - `recipient` సున్నా చిరునామాగా ఉండకూడదు.7 * - కాలర్ కనీసం `amount` బ్యాలెన్స్ కలిగి ఉండాలి.8 */9 function transfer(address recipient, uint256 amount) public virtual override returns (bool) {అన్నీ చూపించుtransfer ఫంక్షన్ పంపినవారి ఖాతా నుండి వేరొకదానికి టోకెన్లను బదిలీ చేయడానికి పిలువబడుతుంది. ఇది బూలియన్ విలువను తిరిగి ఇచ్చినా, ఆ విలువ ఎల్లప్పుడూ నిజం అని గమనించండి. బదిలీ విఫలమైతే కాంట్రాక్ట్ కాల్ను తిరిగి మారుస్తుంది.
1 _transfer(_msgSender(), recipient, amount);2 return true;3 }_transfer ఫంక్షన్ అసలు పని చేస్తుంది. ఇది ఒక ప్రైవేట్ ఫంక్షన్, దీనిని ఇతర కాంట్రాక్ట్ ఫంక్షన్లు మాత్రమే పిలవగలవు. సంప్రదాయం ప్రకారం ప్రైవేట్ ఫంక్షన్లకు _<something> అని పేరు పెట్టారు, స్థితి వేరియబుల్స్లాగే.
సాధారణంగా Solidity లో మేము సందేశం పంపినవారి కోసం msg.sender ను ఉపయోగిస్తాము. అయితే, అది OpenGSN (opens in a new tab) ను విచ్ఛిన్నం చేస్తుంది. మన టోకెన్తో ఈథర్లెస్ లావాదేవీలను అనుమతించాలనుకుంటే, మనం _msgSender() ను ఉపయోగించాలి. ఇది సాధారణ లావాదేవీల కోసం msg.sender ను తిరిగి ఇస్తుంది, కానీ ఈథర్లెస్ వాటి కోసం అసలు సంతకం చేసినవారిని తిరిగి ఇస్తుంది మరియు సందేశాన్ని ప్రసారం చేసిన కాంట్రాక్ట్ను కాదు.
అలవెన్స్ ఫంక్షన్లు
ఇవి అలవెన్స్ ఫంక్షనాలిటీని అమలు చేసే ఫంక్షన్లు: allowance, approve, transferFrom, మరియు _approve. అదనంగా, OpenZeppelin అమలు భద్రతను మెరుగుపరిచే కొన్ని ఫీచర్లను చేర్చడానికి ప్రాథమిక ప్రమాణానికి మించి ఉంటుంది: increaseAllowance, మరియు decreaseAllowance.
అలవెన్స్ ఫంక్షన్
1 /**2 * @dev {IERC20-allowance} చూడండి.3 */4 function allowance(address owner, address spender) public view virtual override returns (uint256) {5 return _allowances[owner][spender];6 }allowance ఫంక్షన్ ఎవరైనా ఏ అలవెన్స్నైనా తనిఖీ చేయడానికి అనుమతిస్తుంది.
అప్రూవ్ ఫంక్షన్
1 /**2 * @dev {IERC20-approve} చూడండి.3 *4 * అవసరాలు:5 *6 * - `spender` సున్నా చిరునామాగా ఉండకూడదు.7 */8 function approve(address spender, uint256 amount) public virtual override returns (bool) {ఈ ఫంక్షన్ ఒక అలవెన్స్ సృష్టించడానికి పిలువబడుతుంది. ఇది పైన ఉన్న transfer ఫంక్షన్ను పోలి ఉంటుంది:
- ఈ ఫంక్షన్ నిజమైన పని చేసే అంతర్గత ఫంక్షన్ను (ఈ సందర్భంలో,
_approve) పిలుస్తుంది. - ఈ ఫంక్షన్
నిజం(విజయవంతమైతే) తిరిగి ఇస్తుంది లేదా రివర్ట్ అవుతుంది (కాకపోతే).
1 _approve(_msgSender(), spender, amount);2 return true;3 }స్థితి మార్పులు జరిగే ప్రదేశాల సంఖ్యను తగ్గించడానికి మేము అంతర్గత ఫంక్షన్లను ఉపయోగిస్తాము. స్థితిని మార్చే ఏదైనా ఫంక్షన్ భద్రత కోసం ఆడిట్ చేయవలసిన సంభావ్య భద్రతా ప్రమాదం. ఈ విధంగా మనం తప్పు చేసే అవకాశాలు తక్కువగా ఉంటాయి.
transferFrom ఫంక్షన్
ఇది ఒక అలవెన్స్ను ఖర్చు చేయడానికి ఖర్చు చేసేవారు పిలిచే ఫంక్షన్. దీనికి రెండు కార్యకలాపాలు అవసరం: ఖర్చు చేస్తున్న మొత్తాన్ని బదిలీ చేయడం మరియు ఆ మొత్తం ద్వారా అలవెన్స్ను తగ్గించడం.
1 /**2 * @dev {IERC20-transferFrom} చూడండి.3 *4 * అప్డేట్ చేయబడిన అలవెన్స్ను సూచించే {Approval} ఈవెంట్ను విడుదల చేస్తుంది. ఇది5 * EIP ద్వారా అవసరం లేదు. {ERC20} ప్రారంభంలో గమనిక చూడండి.6 *7 * అవసరాలు:8 *9 * - `sender` మరియు `recipient` సున్నా చిరునామాగా ఉండకూడదు.10 * - `sender` కనీసం `amount` బ్యాలెన్స్ కలిగి ఉండాలి.11 * - కాలర్ ``sender`` యొక్క టోకెన్ల కోసం కనీసం12 * `amount` అలవెన్స్ కలిగి ఉండాలి.13 */14 function transferFrom(address sender, address recipient, uint256 amount) public virtual15 override returns (bool) {16 _transfer(sender, recipient, amount);అన్నీ చూపించు
a.sub(b, "సందేశం") ఫంక్షన్ కాల్ రెండు పనులు చేస్తుంది. మొదట, ఇది a-bను లెక్కిస్తుంది, ఇది కొత్త అలవెన్స్.
రెండవది, ఈ ఫలితం ప్రతికూలంగా లేదని ఇది తనిఖీ చేస్తుంది. ఇది ప్రతికూలంగా ఉంటే, కాల్ అందించిన సందేశంతో తిరిగి వస్తుంది. ఒక కాల్ తిరిగి వచ్చినప్పుడు, ఆ కాల్ సమయంలో ముందుగా చేసిన ఏ ప్రాసెసింగ్ అయినా విస్మరించబడుతుంది కాబట్టి మనం _transferను రద్దు చేయవలసిన అవసరం లేదని గమనించండి.
1 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount,2 "ERC20: transfer amount exceeds allowance"));3 return true;4 }OpenZeppelin భద్రతా చేర్పులు
సున్నా కాని అలవెన్స్ను మరొక సున్నా కాని విలువకు సెట్ చేయడం ప్రమాదకరం, ఎందుకంటే మీరు మీ స్వంత లావాదేవీల క్రమాన్ని మాత్రమే నియంత్రిస్తారు, మరెవరిదీ కాదు. మీకు ఇద్దరు వినియోగదారులు ఉన్నారని ఊహించుకోండి, అమాయకురాలైన ఆలిస్ మరియు నిజాయితీ లేని బిల్. ఆలిస్కు బిల్ నుండి కొంత సేవ కావాలి, దాని ధర ఐదు టోకెన్లు అని ఆమె అనుకుంటుంది - కాబట్టి ఆమె బిల్కు ఐదు టోకెన్ల అలవెన్స్ ఇస్తుంది.
అప్పుడు ఏదో మారుతుంది మరియు బిల్ ధర పది టోకెన్లకు పెరుగుతుంది. ఇంకా సేవ కావాలనుకునే ఆలిస్, బిల్ అలవెన్స్ను పదికి సెట్ చేసే లావాదేవీని పంపుతుంది. లావాదేవీల పూల్లో ఈ కొత్త లావాదేవీని చూసిన క్షణం, బిల్ ఆలిస్ యొక్క ఐదు టోకెన్లను ఖర్చు చేసే లావాదేవీని పంపుతాడు మరియు అది వేగంగా మైన్ చేయబడటానికి చాలా ఎక్కువ గ్యాస్ ధరను కలిగి ఉంటుంది. ఆ విధంగా బిల్ మొదట ఐదు టోకెన్లను ఖర్చు చేయగలడు మరియు తరువాత, ఆలిస్ యొక్క కొత్త అలవెన్స్ మైన్ చేయబడిన తర్వాత, మొత్తం పదిహేను టోకెన్ల ధరకు మరో పది ఖర్చు చేయగలడు, ఇది ఆలిస్ అధికారం ఇవ్వడానికి ఉద్దేశించిన దానికంటే ఎక్కువ. ఇతీరియములో మీరు మీ స్వంత లావాదేవీల క్రమాన్ని నియంత్రించగలరు, కానీ ఇతర వ్యక్తుల లావాదేవీలు ఏ క్రమంలో అమలు చేయబడతాయో మీరు నియంత్రించలేరు, అవతలి పక్షం లావాదేవీ జరిగిందని మీరు చూసే వరకు మీరు మీ స్వంత లావాదేవీని సమర్పించకపోతే తప్ప.
| ఆలిస్ లావాదేవీ | ఆలిస్ నాన్స్ | బిల్ లావాదేవీ | బిల్ నాన్స్ | బిల్ అలవెన్స్ | ఆలిస్ నుండి బిల్ మొత్తం ఆదాయం |
|---|---|---|---|---|---|
| approve(Bill, 5) | 10 | 5 | 0 | ||
| transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | ||
| approve(Bill, 10) | 11 | 10 | 5 | ||
| transferFrom(Alice, Bill, 10) | 10,124 | 0 | 15 |
ఈ సమస్యను నివారించడానికి, ఈ రెండు ఫంక్షన్లు (increaseAllowance మరియు decreaseAllowance) అలవెన్స్ను ఒక నిర్దిష్ట మొత్తం ద్వారా సవరించడానికి మిమ్మల్ని అనుమతిస్తాయి. కాబట్టి బిల్ ఇప్పటికే ఐదు టోకెన్లను ఖర్చు చేసి ఉంటే, అతను కేవలం మరో ఐదు ఖర్చు చేయగలడు. సమయాన్ని బట్టి, ఇది పని చేయడానికి రెండు మార్గాలు ఉన్నాయి, రెండూ బిల్ కేవలం పది టోకెన్లను పొందడంతో ముగుస్తాయి:
A:
| ఆలిస్ లావాదేవీ | ఆలిస్ నాన్స్ | బిల్ లావాదేవీ | బిల్ నాన్స్ | బిల్ అలవెన్స్ | ఆలిస్ నుండి బిల్ మొత్తం ఆదాయం |
|---|---|---|---|---|---|
| approve(Bill, 5) | 10 | 5 | 0 | ||
| transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | ||
| increaseAllowance(Bill, 5) | 11 | 0+5 = 5 | 5 | ||
| transferFrom(Alice, Bill, 5) | 10,124 | 0 | 10 |
B:
| ఆలిస్ లావాదేవీ | ఆలిస్ నాన్స్ | బిల్ లావాదేవీ | బిల్ నాన్స్ | బిల్ అలవెన్స్ | ఆలిస్ నుండి బిల్ మొత్తం ఆదాయం |
|---|---|---|---|---|---|
| approve(Bill, 5) | 10 | 5 | 0 | ||
| increaseAllowance(Bill, 5) | 11 | 5+5 = 10 | 0 | ||
| transferFrom(Alice, Bill, 10) | 10,124 | 0 | 10 |
1 /**2 * @dev కాలర్ ద్వారా `spender`కు మంజూరు చేయబడిన అలవెన్స్ను అణురూపంగా పెంచుతుంది.3 *4 * ఇది {approve}కు ఒక ప్రత్యామ్నాయం, ఇది {IERC20-approve}లో వివరించిన సమస్యలకు ఉపశమనంగా ఉపయోగించబడుతుంది.5 *6 * అప్డేట్ చేయబడిన అలవెన్స్ను సూచించే {Approval} ఈవెంట్ను విడుదల చేస్తుంది.7 *8 * అవసరాలు:9 *10 * - `spender` సున్నా చిరునామాగా ఉండకూడదు.11 */12 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {13 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));14 return true;15 }అన్నీ చూపించుa.add(b) ఫంక్షన్ ఒక సురక్షితమైన కూడిక. a+b>=2^256 అయ్యే అసంభవమైన సందర్భంలో, ఇది సాధారణ కూడిక వలె చుట్టుముట్టదు.
1 /**2 * @dev కాలర్ ద్వారా `spender`కు మంజూరు చేయబడిన అలవెన్స్ను అణురూపంగా తగ్గిస్తుంది.3 *4 * ఇది {approve}కు ఒక ప్రత్యామ్నాయం, ఇది {IERC20-approve}లో వివరించిన సమస్యలకు ఉపశమనంగా ఉపయోగించబడుతుంది.5 *6 * అప్డేట్ చేయబడిన అలవెన్స్ను సూచించే {Approval} ఈవెంట్ను విడుదల చేస్తుంది.7 *8 * అవసరాలు:9 *10 * - `spender` సున్నా చిరునామాగా ఉండకూడదు.11 * - `spender` కనీసం12 * `subtractedValue` కాలర్ కోసం అలవెన్స్ కలిగి ఉండాలి.13 */14 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {15 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue,16 "ERC20: అలవెన్స్ సున్నా కంటే తక్కువకు తగ్గించబడింది"));17 return true;18 }అన్నీ చూపించుటోకెన్ సమాచారాన్ని సవరించే ఫంక్షన్లు
ఇవి అసలు పని చేసే నాలుగు ఫంక్షన్లు: _transfer, _mint, _burn, మరియు _approve.
_transfer ఫంక్షన్
1 /**2 * @dev `పంపినవారి` నుండి `గ్రహీత`కు `మొత్తం` టోకెన్లను తరలిస్తుంది.3 *4 * ఈ అంతర్గత ఫంక్షన్ {transfer}కు సమానం, మరియు దీనిని5 * ఉదాహరణకు, ఆటోమేటిక్ టోకెన్ ఫీజులు, స్లాషింగ్ మెకానిజమ్స్ మొదలైనవాటిని అమలు చేయడానికి ఉపయోగించవచ్చు.6 *7 * ఒక {Transfer} ఈవెంట్ను విడుదల చేస్తుంది.8 *9 * అవసరాలు:10 *11 * - `sender` సున్నా చిరునామాగా ఉండకూడదు.12 * - `recipient` సున్నా చిరునామాగా ఉండకూడదు.13 * - `sender` కనీసం `amount` బ్యాలెన్స్ కలిగి ఉండాలి.14 */15 function _transfer(address sender, address recipient, uint256 amount) internal virtual {అన్నీ చూపించుఈ ఫంక్షన్, _transfer, టోకెన్లను ఒక ఖాతా నుండి మరొకదానికి బదిలీ చేస్తుంది. ఇది transfer (పంపినవారి స్వంత ఖాతా నుండి బదిలీల కోసం) మరియు transferFrom (ఇతరుల ఖాతా నుండి బదిలీ చేయడానికి అలవెన్సులను ఉపయోగించడం కోసం) రెండింటి ద్వారా పిలువబడుతుంది.
1 require(sender != address(0), "ERC20: transfer from the zero address");2 require(recipient != address(0), "ERC20: transfer to the zero address");ఇతీరియములో సున్నా చిరునామాను ఎవరూ నిజంగా కలిగి లేరు (అంటే, ఎవరికి సరిపోలే పబ్లిక్ కీ సున్నా చిరునామాకు రూపాంతరం చెందుతుందో ఆ ప్రైవేట్ కీ ఎవరికీ తెలియదు). ప్రజలు ఆ చిరునామాను ఉపయోగించినప్పుడు, అది సాధారణంగా ఒక సాఫ్ట్వేర్ బగ్ - కాబట్టి పంపినవారు లేదా గ్రహీతగా సున్నా చిరునామాను ఉపయోగించినట్లయితే మేము విఫలమవుతాము.
1 _beforeTokenTransfer(sender, recipient, amount);ఈ కాంట్రాక్ట్ను ఉపయోగించడానికి రెండు మార్గాలు ఉన్నాయి:
- మీ స్వంత కోడ్ కోసం దీనిని ఒక టెంప్లేట్గా ఉపయోగించండి
- దాని నుండి వారసత్వం పొందండి (opens in a new tab), మరియు మీరు సవరించాల్సిన ఫంక్షన్లను మాత్రమే ఓవర్రైడ్ చేయండి
రెండవ పద్ధతి చాలా మంచిది ఎందుకంటే OpenZeppelin ERC-20 కోడ్ ఇప్పటికే ఆడిట్ చేయబడింది మరియు సురక్షితమని చూపబడింది. మీరు వారసత్వాన్ని ఉపయోగించినప్పుడు మీరు సవరించే ఫంక్షన్లు ఏమిటో స్పష్టంగా ఉంటుంది, మరియు మీ కాంట్రాక్ట్ను విశ్వసించడానికి ప్రజలు ఆ నిర్దిష్ట ఫంక్షన్లను మాత్రమే ఆడిట్ చేయాలి.
ప్రతిసారీ టోకెన్లు చేతులు మారినప్పుడు ఒక ఫంక్షన్ను నిర్వహించడం తరచుగా ఉపయోగకరంగా ఉంటుంది. అయితే, _transfer చాలా ముఖ్యమైన ఫంక్షన్ మరియు దానిని అసురక్షితంగా రాయడం సాధ్యమవుతుంది (క్రింద చూడండి), కాబట్టి దానిని ఓవర్రైడ్ చేయకపోవడమే మంచిది. పరిష్కారం _beforeTokenTransfer, ఒక హుక్ ఫంక్షన్ (opens in a new tab). మీరు ఈ ఫంక్షన్ను ఓవర్రైడ్ చేయవచ్చు, మరియు ఇది ప్రతి బదిలీపై పిలువబడుతుంది.
1 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");2 _balances[recipient] = _balances[recipient].add(amount);ఇవి వాస్తవానికి బదిలీ చేసే లైన్లు. వాటి మధ్య ఏమీ లేదని గమనించండి, మరియు మేము బదిలీ చేయబడిన మొత్తాన్ని పంపినవారి నుండి తీసివేసి, ఆ తర్వాత గ్రహీతకు జోడిస్తాము. ఇది ముఖ్యం ఎందుకంటే మధ్యలో వేరే కాంట్రాక్ట్కు కాల్ ఉంటే, అది ఈ కాంట్రాక్ట్ను మోసం చేయడానికి ఉపయోగించబడి ఉండవచ్చు. ఈ విధంగా బదిలీ అణురూపంగా ఉంటుంది, దాని మధ్యలో ఏమీ జరగదు.
1 emit Transfer(sender, recipient, amount);2 }చివరగా, ఒక Transfer ఈవెంట్ను విడుదల చేయండి. ఈవెంట్లు స్మార్ట్ కాంట్రాక్ట్లకు అందుబాటులో ఉండవు, కానీ బ్లాక్చెయిన్ వెలుపల నడుస్తున్న కోడ్ ఈవెంట్లను విని వాటికి ప్రతిస్పందించగలదు. ఉదాహరణకు, ఒక వాలెట్ యజమానికి ఎక్కువ టోకెన్లు వచ్చినప్పుడు ట్రాక్ చేయగలదు.
_mint మరియు _burn ఫంక్షన్లు
ఈ రెండు ఫంక్షన్లు (_mint మరియు _burn) టోకెన్ల మొత్తం సరఫరాను సవరిస్తాయి.
అవి అంతర్గతమైనవి మరియు ఈ కాంట్రాక్ట్లో వాటిని పిలిచే ఫంక్షన్ ఏదీ లేదు, కాబట్టి మీరు కాంట్రాక్ట్ నుండి వారసత్వం పొంది, కొత్త టోకెన్లను ఏ పరిస్థితులలో మింట్ చేయాలో లేదా ఉన్నవాటిని బర్న్ చేయాలో నిర్ణయించడానికి మీ స్వంత లాజిక్ను జోడిస్తేనే అవి ఉపయోగపడతాయి.
గమనిక: ప్రతి ERC-20 టోకెన్ టోకెన్ నిర్వహణను నిర్దేశించే దాని స్వంత వ్యాపార తర్కాన్ని కలిగి ఉంటుంది.
ఉదాహరణకు, ఒక స్థిర సరఫరా కాంట్రాక్ట్ నిర్మాణకర్తలో మాత్రమే _mintను పిలవవచ్చు మరియు _burnను ఎప్పుడూ పిలవకపోవచ్చు. టోకెన్లను అమ్మే ఒక కాంట్రాక్ట్ చెల్లింపు జరిగినప్పుడు _mintను పిలుస్తుంది, మరియు నియంత్రణ లేని ద్రవ్యోల్బణాన్ని నివారించడానికి ఏదో ఒక సమయంలో _burnను పిలుస్తుంది.
1 /** @dev `amount` టోకెన్లను సృష్టిస్తుంది మరియు వాటిని `account`కు కేటాయిస్తుంది, మొత్తం సరఫరాను పెంచుతుంది.2 *3 * `from`ను సున్నా చిరునామాకు సెట్ చేసి {Transfer} ఈవెంట్ను విడుదల చేస్తుంది.4 *5 * అవసరాలు:6 *7 * - `to` సున్నా చిరునామాగా ఉండకూడదు.8 */9 function _mint(address account, uint256 amount) internal virtual {10 require(account != address(0), "ERC20: mint to the zero address");11 _beforeTokenTransfer(address(0), account, amount);12 _totalSupply = _totalSupply.add(amount);13 _balances[account] = _balances[account].add(amount);14 emit Transfer(address(0), account, amount);15 }అన్నీ చూపించుటోకెన్ల మొత్తం సంఖ్య మారినప్పుడు _totalSupplyను అప్డేట్ చేయాలని నిర్ధారించుకోండి.
1 /**2 * @dev `account` నుండి `amount` టోకెన్లను నాశనం చేస్తుంది, మొత్తం సరఫరాను తగ్గిస్తుంది.3 *4 * `to`ను సున్నా చిరునామాకు సెట్ చేసి {Transfer} ఈవెంట్ను విడుదల చేస్తుంది.5 *6 * అవసరాలు:7 *8 * - `account` సున్నా చిరునామాగా ఉండకూడదు.9 * - `account` కనీసం `amount` టోకెన్లను కలిగి ఉండాలి.10 */11 function _burn(address account, uint256 amount) internal virtual {12 require(account != address(0), "ERC20: burn from the zero address");1314 _beforeTokenTransfer(account, address(0), amount);1516 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");17 _totalSupply = _totalSupply.sub(amount);18 emit Transfer(account, address(0), amount);19 }అన్నీ చూపించు_burn ఫంక్షన్ దాదాపుగా _mint వలె ఉంటుంది, అయితే ఇది వ్యతిరేక దిశలో వెళ్తుంది.
_approve ఫంక్షన్
ఇది వాస్తవానికి అలవెన్సులను నిర్దేశించే ఫంక్షన్. యజమాని ప్రస్తుత బ్యాలెన్స్ కంటే ఎక్కువ ఉన్న అలవెన్స్ను నిర్దేశించడానికి ఇది అనుమతిస్తుందని గమనించండి. ఇది సరే ఎందుకంటే బదిలీ సమయంలో బ్యాలెన్స్ తనిఖీ చేయబడుతుంది, అప్పుడు అది అలవెన్స్ సృష్టించబడినప్పుడు ఉన్న బ్యాలెన్స్ నుండి భిన్నంగా ఉండవచ్చు.
1 /**2 * @dev `యజమాని` టోకెన్లపై `ఖర్చు చేసేవారి` యొక్క అలవెన్స్గా `మొత్తాన్ని` సెట్ చేస్తుంది.3 *4 * ఈ అంతర్గత ఫంక్షన్ `approve`కు సమానం, మరియు దీనిని5 * ఉదాహరణకు, కొన్ని ఉపవ్యవస్థల కోసం ఆటోమేటిక్ అలవెన్సులను సెట్ చేయడానికి మొదలైన వాటికి ఉపయోగించవచ్చు.6 *7 * ఒక {Approval} ఈవెంట్ను విడుదల చేస్తుంది.8 *9 * అవసరాలు:10 *11 * - `owner` సున్నా చిరునామాగా ఉండకూడదు.12 * - `spender` సున్నా చిరునామాగా ఉండకూడదు.13 */14 function _approve(address owner, address spender, uint256 amount) internal virtual {15 require(owner != address(0), "ERC20: approve from the zero address");16 require(spender != address(0), "ERC20: approve to the zero address");1718 _allowances[owner][spender] = amount;అన్నీ చూపించు
ఒక Approval ఈవెంట్ను విడుదల చేయండి. అప్లికేషన్ ఎలా వ్రాయబడింది అనేదానిపై ఆధారపడి, ఖర్చు చేసే కాంట్రాక్ట్కు యజమాని ద్వారా లేదా ఈ ఈవెంట్లను వినే సర్వర్ ద్వారా ఆమోదం గురించి తెలియజేయవచ్చు.
1 emit Approval(owner, spender, amount);2 }దశాంశాల వేరియబుల్ను సవరించండి
1 /**2 * @dev {decimals}ను 18 యొక్క డిఫాల్ట్ విలువ కాకుండా వేరే విలువకు సెట్ చేస్తుంది.3 *4 * హెచ్చరిక: ఈ ఫంక్షన్ నిర్మాణకర్త నుండి మాత్రమే పిలవబడాలి. టోకెన్ కాంట్రాక్ట్లతో పరస్పర చర్య జరిపే చాలా అప్లికేషన్లు5 * {decimals} ఎప్పుడూ మారుతుందని ఊహించవు, మరియు అలా మారితే తప్పుగా పని చేయవచ్చు.6 */7 function _setupDecimals(uint8 decimals_) internal {8 _decimals = decimals_;9 }అన్నీ చూపించుఈ ఫంక్షన్ _decimals వేరియబుల్ను సవరిస్తుంది, ఇది వినియోగదారు ఇంటర్ఫేస్లకు మొత్తాన్ని ఎలా అర్థం చేసుకోవాలో చెప్పడానికి ఉపయోగించబడుతుంది.
మీరు దీనిని నిర్మాణకర్త నుండి పిలవాలి. తర్వాతి ఏ సమయంలోనైనా దీనిని పిలవడం నిజాయితీ లేనిదిగా ఉంటుంది, మరియు అప్లికేషన్లు దీనిని నిర్వహించడానికి రూపొందించబడలేదు.
హుక్స్
1 /**2 * @dev టోకెన్ల ఏ బదిలీకి ముందు పిలవబడే హుక్. ఇందులో3 * మింటింగ్ మరియు బర్నింగ్ కూడా ఉంటాయి.4 *5 * పిలిచే పరిస్థితులు:6 *7 * - `from` మరియు `to` రెండూ సున్నా కానివి అయినప్పుడు, ``from`` యొక్క టోకెన్ల `మొత్తం`8 * `to`కు బదిలీ చేయబడుతుంది.9 * - `from` సున్నా అయినప్పుడు, `to` కోసం `amount` టోకెన్లు మింట్ చేయబడతాయి.10 * - `to` సున్నా అయినప్పుడు, ``from`` యొక్క టోకెన్ల `amount` బర్న్ చేయబడుతుంది.11 * - `from` మరియు `to` రెండూ ఎప్పుడూ సున్నా కావు.12 *13 * హుక్స్ గురించి మరింత తెలుసుకోవడానికి, xref:ROOT:extending-contracts.adoc#using-hooks[హుక్స్ ఉపయోగించడం]కు వెళ్లండి.14 */15 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }అన్నీ చూపించుఇది బదిలీల సమయంలో పిలవబడే హుక్ ఫంక్షన్. ఇక్కడ ఇది ఖాళీగా ఉంది, కానీ మీకు అది ఏదైనా చేయవలసి వస్తే మీరు దానిని ఓవర్రైడ్ చేయండి.
ముగింపు
సమీక్ష కోసం, ఈ కాంట్రాక్ట్లోని కొన్ని ముఖ్యమైన ఆలోచనలు ఇక్కడ ఉన్నాయి (నా అభిప్రాయం ప్రకారం, మీది మారే అవకాశం ఉంది):
- బ్లాక్చెయిన్లో రహస్యాలు లేవు. ఒక స్మార్ట్ కాంట్రాక్ట్ యాక్సెస్ చేయగల ఏ సమాచారం అయినా ప్రపంచం మొత్తానికి అందుబాటులో ఉంటుంది.
- మీరు మీ స్వంత లావాదేవీల క్రమాన్ని నియంత్రించగలరు, కానీ ఇతర వ్యక్తుల లావాదేవీలు ఎప్పుడు జరుగుతాయో కాదు. అలవెన్స్ను మార్చడం ప్రమాదకరంగా ఉండటానికి ఇదే కారణం, ఎందుకంటే ఇది ఖర్చు చేసేవారికి రెండు అలవెన్స్ల మొత్తాన్ని ఖర్చు చేయడానికి అనుమతిస్తుంది.
uint256రకం విలువలు చుట్టుముడతాయి. మరో మాటలో చెప్పాలంటే, 0-1=2^256-1. అది కావాల్సిన ప్రవర్తన కాకపోతే, మీరు దాని కోసం తనిఖీ చేయాలి (లేదా మీ కోసం చేసే SafeMath లైబ్రరీని ఉపయోగించండి). Solidity 0.8.0 (opens in a new tab)లో ఇది మారిందని గమనించండి.- ఒక నిర్దిష్ట రకానికి చెందిన అన్ని స్థితి మార్పులను ఒక నిర్దిష్ట ప్రదేశంలో చేయండి, ఎందుకంటే ఇది ఆడిటింగ్ను సులభతరం చేస్తుంది.
ఉదాహరణకు,
approve,transferFrom,increaseAllowance, మరియుdecreaseAllowanceద్వారా పిలువబడే_approveమనకు ఉండటానికి ఇదే కారణం - స్థితి మార్పులు అణురూపంగా ఉండాలి, వాటి మధ్యలో మరే ఇతర చర్య లేకుండా (
_transferలో మీరు చూడవచ్చు). ఇది ఎందుకంటే స్థితి మార్పు సమయంలో మీకు అస్థిరమైన స్థితి ఉంటుంది. ఉదాహరణకు, మీరు పంపినవారి బ్యాలెన్స్ నుండి తీసివేసే సమయం మరియు గ్రహీత బ్యాలెన్స్కు జోడించే సమయం మధ్యలో ఉండాల్సిన దానికంటే తక్కువ టోకెన్లు ఉనికిలో ఉంటాయి. వాటి మధ్య కార్యకలాపాలు ఉంటే, ముఖ్యంగా వేరే కాంట్రాక్ట్కు కాల్స్ ఉంటే ఇది దుర్వినియోగం చేయబడే అవకాశం ఉంది.
ఇప్పుడు మీరు OpenZeppelin ERC-20 కాంట్రాక్ట్ ఎలా వ్రాయబడింది, మరియు ముఖ్యంగా అది ఎలా మరింత సురక్షితంగా చేయబడింది అని చూశారు, వెళ్లి మీ స్వంత సురక్షితమైన కాంట్రాక్ట్లు మరియు అప్లికేషన్లను వ్రాయండి.
నా మరిన్ని పనుల కోసం ఇక్కడ చూడండి (opens in a new tab).
పేజీ చివరి అప్డేట్: 22 అక్టోబర్, 2025
