Ruka hadi kwenye maudhui makuu

Mwongozo wa Mkataba wa ERC-20

Solidity
erc-20
Mwanzilishi
Ori Pomerantz
9 Machi 2021
25 dakika za kusoma

Utangulizi

Moja ya matumizi ya kawaida ya Ethereum ni kwa kikundi kuunda tokeni inayoweza kuuzwa, kwa maana fulani sarafu yao wenyewe. Tokeni hizi kwa kawaida hufuata kiwango, ERC-20. Kiwango hiki hufanya iwezekane kuandika zana, kama vile mabwawa ya ukwasi na mikoba, zinazofanya kazi na tokeni zote za ERC-20. Katika makala haya tutachambua utekelezaji wa ERC20 wa Solidity wa OpenZeppelin (opens in a new tab), pamoja na ufafanuzi wa kiolesura (opens in a new tab).

Huu ni msimbo wa chanzo uliofafanuliwa. Ikiwa unataka kutekeleza ERC-20, soma mafunzo haya (opens in a new tab).

Kiolesura

Kusudi la kiwango kama ERC-20 ni kuruhusu utekelezaji wa tokeni nyingi zinazoingiliana katika programu, kama vile mikoba na mabadilishano yaliyogatuliwa. Ili kufanikisha hilo, tunaunda kiolesura (opens in a new tab). Msimbo wowote unaohitaji kutumia mkataba wa tokeni unaweza kutumia ufafanuzi sawa katika kiolesura na kuendana na mikataba yote ya tokeni inayoitumia, iwe ni mkoba kama vile MetaMask, programu tumizi iliyogatuliwa (dapp) kama vile etherscan.io, au mkataba tofauti kama vile bwawa la ukwasi.

Illustration of the ERC-20 interface

Ikiwa wewe ni mtayarishaji programu mzoefu, labda unakumbuka kuona miundo sawa katika Java (opens in a new tab) au hata katika faili za kichwa za C (opens in a new tab).

Huu ni ufafanuzi wa Kiolesura cha ERC-20 (opens in a new tab) kutoka OpenZeppelin. Ni tafsiri ya kiwango kinachosomeka na binadamu (opens in a new tab) kuwa msimbo wa Solidity. Bila shaka, kiolesura chenyewe hakifafanui jinsi ya kufanya chochote. Hilo linaelezwa katika msimbo wa chanzo wa mkataba hapa chini.

 

// SPDX-License-Identifier: MIT

Faili za Solidity zinapaswa kujumuisha kitambulisho cha leseni. Unaweza kuona orodha ya leseni hapa (opens in a new tab). Ikiwa unahitaji leseni tofauti, ieleze tu kwenye maoni.

 

pragma solidity >=0.6.0 <0.8.0;

Lugha ya Solidity bado inabadilika haraka, na matoleo mapya yanaweza yasiendane na msimbo wa zamani (tazama hapa (opens in a new tab)). Kwa hivyo, ni wazo zuri kubainisha sio tu toleo la chini la lugha, bali pia toleo la juu zaidi, la hivi punde ambalo ulijaribu msimbo nalo.

 

/**
 * @dev Kiolesura cha kiwango cha ERC-20 kama kilivyofafanuliwa katika EIP.
 */

@dev katika maoni ni sehemu ya umbizo la NatSpec (opens in a new tab), linalotumika kutoa nyaraka kutoka kwa msimbo wa chanzo.

 

interface IERC20 {

Kwa kawaida, majina ya kiolesura huanza na I.

 

    /**
     * @dev Inarejesha kiasi cha tokeni zilizopo.
     */
    function totalSupply() external view returns (uint256);

Kazi hii ni external, ikimaanisha inaweza tu kuitwa kutoka nje ya mkataba (opens in a new tab). Inarudisha jumla ya usambazaji wa tokeni katika mkataba. Thamani hii inarudishwa kwa kutumia aina ya kawaida zaidi katika Ethereum, biti 256 zisizo na saini (biti 256 ni saizi ya neno asili ya EVM). Kazi hii pia ni view, ambayo inamaanisha kuwa haibadilishi hali, kwa hivyo inaweza kutekelezwa kwenye nodi moja badala ya kuwa na kila nodi katika mnyororo wa vitalu kuiendesha. Aina hii ya kazi haizalishi muamala na haigharimu gesi.

Kumbuka: Kinadharia inaweza kuonekana kuwa muundaji wa mkataba anaweza kudanganya kwa kurudisha jumla ya usambazaji mdogo kuliko thamani halisi, na kufanya kila tokeni ionekane ya thamani zaidi kuliko ilivyo kweli. Hata hivyo, hofu hiyo inapuuza asili ya kweli ya mnyororo wa vitalu. Kila kitu kinachotokea kwenye mnyororo wa vitalu kinaweza kuthibitishwa na kila nodi. Ili kufanikisha hili, msimbo wa lugha ya mashine ya kila mkataba na hifadhi inapatikana kwenye kila nodi. Ingawa hauhitajiki kuchapisha msimbo wa Solidity kwa mkataba wako, hakuna mtu atakayekuchukulia kwa uzito isipokuwa uchapishe msimbo wa chanzo na toleo la Solidity ambalo lilikusanywa nalo, ili iweze kuthibitishwa dhidi ya msimbo wa lugha ya mashine uliotoa. Kwa mfano, tazama mkataba huu (opens in a new tab).

 

    /**
     * @dev Inarejesha kiasi cha tokeni zinazomilikiwa na `akaunti`.
     */
    function balanceOf(address account) external view returns (uint256);

Kama jina linavyosema, balanceOf inarudisha salio la akaunti. Akaunti za Ethereum zinatambuliwa katika Solidity kwa kutumia aina ya address, ambayo inashikilia biti 160. Pia ni external na view.

 

    /**
     * @dev Inahamisha tokeni `amount` kutoka kwenye akaunti ya mpigaji kwenda kwa `recipient`.
     *
     * Inarejesha thamani ya boolean inayoonyesha ikiwa operesheni imefaulu.
     *
     * Inatoa tukio la {hamisho}.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

Kazi ya transfer inahamisha tokeni kutoka kwa mpigaji kwenda kwa anwani tofauti. Hii inahusisha mabadiliko ya hali, kwa hivyo sio view. Mtumiaji anapoita kazi hii inaunda muamala na kugharimu gesi. Pia inatoa tukio, Transfer, ili kuarifu kila mtu kwenye mnyororo wa vitalu kuhusu tukio hilo.

Kazi ina aina mbili za matokeo kwa aina mbili tofauti za wapigaji:

  • Watumiaji wanaopiga kazi moja kwa moja kutoka kwa kiolesura cha mtumiaji. Kwa kawaida mtumiaji huwasilisha muamala na hasubiri jibu, ambalo linaweza kuchukua muda usiojulikana. Mtumiaji anaweza kuona kilichotokea kwa kutafuta stakabadhi ya muamala (ambayo inatambuliwa na heshi ya muamala) au kwa kutafuta tukio la Transfer.
  • Mikataba mingine, ambayo huita kazi kama sehemu ya muamala wa jumla. Mikataba hiyo hupata matokeo mara moja, kwa sababu inaendeshwa katika muamala huo huo, kwa hivyo inaweza kutumia thamani ya kurudi ya kazi.

Aina sawa ya matokeo inaundwa na kazi zingine zinazobadilisha hali ya mkataba.

 

Vibali huruhusu akaunti kutumia baadhi ya tokeni ambazo ni za mmiliki tofauti. Hii ni muhimu, kwa mfano, kwa mikataba inayofanya kazi kama wauzaji. Mikataba haiwezi kufuatilia matukio, kwa hivyo ikiwa mnunuzi angehamisha tokeni kwa mkataba wa muuzaji moja kwa moja mkataba huo usingejua umelipwa. Badala yake, mnunuzi anaruhusu mkataba wa muuzaji kutumia kiasi fulani, na muuzaji anahamisha kiasi hicho. Hii inafanywa kupitia kazi ambayo mkataba wa muuzaji unaita, ili mkataba wa muuzaji uweze kujua ikiwa ulifanikiwa.

    /**
     * @dev Inarejesha idadi iliyobaki ya tokeni ambazo `spender` ataruhusiwa
     * kutumia kwa niaba ya `owner` kupitia {transferFrom}. Hii ni
     * sifuri kwa chaguo-msingi.
     *
     * Thamani hii inabadilika wakati {idhinisha} au {transferFrom} inapoitwa.
     */
    function allowance(address owner, address spender) external view returns (uint256);

Kazi ya allowance inaruhusu mtu yeyote kuuliza ili kuona ni kibali gani ambacho anwani moja (owner) inaruhusu anwani nyingine (spender) kutumia.

 

Kazi ya approve inaunda kibali. Hakikisha unasoma ujumbe kuhusu jinsi inavyoweza kutumiwa vibaya. Katika Ethereum unadhibiti mpangilio wa miamala yako mwenyewe, lakini huwezi kudhibiti mpangilio ambao miamala ya watu wengine itatekelezwa, isipokuwa usipowasilisha muamala wako mwenyewe hadi uone muamala wa upande mwingine umetokea.

 

Hatimaye, transferFrom inatumiwa na mtumiaji kutumia kibali hicho.

 

Matukio haya hutolewa wakati hali ya mkataba wa ERC-20 inabadilika.

Mkataba Halisi

Huu ndio mkataba halisi unaotekeleza kiwango cha ERC-20, uliochukuliwa kutoka hapa (opens in a new tab). Haukusudiwi kutumiwa kama ulivyo, lakini unaweza kurithi (opens in a new tab) kutoka kwake ili kuupanua kuwa kitu kinachoweza kutumika.

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;

 

Taarifa za Uingizaji

Mbali na ufafanuzi wa kiolesura hapo juu, ufafanuzi wa mkataba unaingiza faili zingine mbili:


import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
  • GSN/Context.sol ni ufafanuzi unaohitajika kutumia OpenGSN (opens in a new tab), mfumo unaoruhusu watumiaji wasio na Etha kutumia mnyororo wa vitalu. Kumbuka kuwa hili ni toleo la zamani, ikiwa unataka kuunganisha na OpenGSN tumia mafunzo haya (opens in a new tab).
  • Maktaba ya SafeMath (opens in a new tab), ambayo inazuia mizidio/upungufu wa hesabu kwa matoleo ya Solidity <0.8.0. Katika Solidity ≥0.8.0, shughuli za hesabu hutengua kiotomatiki kwenye mzidio/upungufu, na kufanya SafeMath isiwe ya lazima. Mkataba huu unatumia SafeMath kwa utangamano wa nyuma na matoleo ya zamani ya kikusanyaji.

 

Maoni haya yanaelezea madhumuni ya mkataba.

Ufafanuzi wa Mkataba

contract ERC20 is Context, IERC20 {

Mstari huu unabainisha urithi, katika kesi hii kutoka kwa IERC20 kutoka hapo juu na Context, kwa OpenGSN.

 


    using SafeMath for uint256;

Mstari huu unaambatanisha maktaba ya SafeMath kwenye aina ya uint256. Unaweza kupata maktaba hii hapa (opens in a new tab).

Ufafanuzi wa Vigezo

Ufafanuzi huu unabainisha vigezo vya hali ya mkataba. Vigezo hivi vimetangazwa kama private, lakini hiyo inamaanisha tu kwamba mikataba mingine kwenye mnyororo wa vitalu haiwezi kuvisoma. Hakuna siri kwenye mnyororo wa vitalu, programu kwenye kila nodi ina hali ya kila mkataba katika kila kitalu. Kwa kawaida, vigezo vya hali hupewa jina _<something>.

Vigezo viwili vya kwanza ni ramani (opens in a new tab), ikimaanisha vinafanya kazi takriban sawa na safu shirikishi (opens in a new tab), isipokuwa kwamba funguo ni thamani za nambari. Hifadhi inatengwa tu kwa maingizo ambayo yana thamani tofauti na chaguo-msingi (sifuri).

    mapping (address => uint256) private _balances;

Ramani ya kwanza, _balances, ni anwani na salio zao husika za tokeni hii. Ili kufikia salio, tumia sintaksia hii: _balances[<address>].

 

    mapping (address => mapping (address => uint256)) private _allowances;

Kigezo hiki, _allowances, kinahifadhi vibali vilivyoelezwa hapo awali. Faharisi ya kwanza ni mmiliki wa tokeni, na ya pili ni mkataba wenye kibali. Ili kufikia kiasi ambacho anwani A inaweza kutumia kutoka kwa akaunti ya anwani B, tumia _allowances[B][A].

 

    uint256 private _totalSupply;

Kama jina linavyopendekeza, kigezo hiki hufuatilia jumla ya usambazaji wa tokeni.

 

    string private _name;
    string private _symbol;
    uint8 private _decimals;

Vigezo hivi vitatu vinatumika kuboresha usomaji. Viwili vya kwanza vinajieleza, lakini _decimals haijielezi.

Kwa upande mmoja, Ethereum haina vigezo vya nambari za desimali au sehemu. Kwa upande mwingine, binadamu wanapenda kuweza kugawanya tokeni. Sababu moja iliyofanya watu wakubaliane kutumia dhahabu kwa sarafu ni kwamba ilikuwa vigumu kutoa chenji wakati mtu alipotaka kununua ng'ombe kwa thamani ya bata.

Suluhisho ni kufuatilia nambari kamili, lakini kuhesabu badala ya tokeni halisi tokeni ya sehemu ambayo inakaribia kukosa thamani. Katika kesi ya Etha, tokeni ya sehemu inaitwa Wei, na Wei 10^18 ni sawa na ETH moja. Wakati wa kuandika, Wei 10,000,000,000,000 ni takriban senti moja ya Marekani au Euro.

Programu zinahitaji kujua jinsi ya kuonyesha salio la tokeni. Ikiwa mtumiaji ana Wei 3,141,000,000,000,000,000, je, hiyo ni ETH 3.14? ETH 31.41? ETH 3,141? Katika kesi ya Etha inafafanuliwa Wei 10^18 kwa ETH, lakini kwa tokeni yako unaweza kuchagua thamani tofauti. Ikiwa kugawanya tokeni hakuna maana, unaweza kutumia thamani ya _decimals ya sifuri. Ikiwa unataka kutumia kiwango sawa na ETH, tumia thamani 18.

Konstrukta

Konstrukta inaitwa wakati mkataba unaundwa kwa mara ya kwanza. Kwa kawaida, vigezo vya kazi hupewa jina <something>_.

Kazi za Kiolesura cha Mtumiaji

Kazi hizi, name, symbol, na decimals husaidia violesura vya mtumiaji kujua kuhusu mkataba wako ili viweze kuuonyesha ipasavyo.

Aina ya kurudi ni string memory, ikimaanisha kurudisha mfuatano ambao umehifadhiwa kwenye kumbukumbu. Vigezo, kama vile mifuatano, vinaweza kuhifadhiwa katika maeneo matatu:

Muda wa KuishiUfikiaji wa MkatabaGharama ya Gesi
MemoryMwito wa kaziSoma/AndikaMakumi au mamia (juu zaidi kwa maeneo ya juu)
CalldataMwito wa kaziSoma TuHaiwezi kutumika kama aina ya kurudi, tu kama aina ya kigezo cha kazi
StorageHadi ibadilishweSoma/AndikaJuu (800 kwa kusoma, 20k kwa kuandika)

Katika kesi hii, memory ndio chaguo bora.

Soma Taarifa za Tokeni

Hizi ni kazi zinazotoa taarifa kuhusu tokeni, iwe ni jumla ya usambazaji au salio la akaunti.

    /**
     * @dev Tazama {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

Kazi ya totalSupply inarudisha jumla ya usambazaji wa tokeni.

 

    /**
     * @dev Tazama {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

Soma salio la akaunti. Kumbuka kwamba mtu yeyote anaruhusiwa kupata salio la akaunti ya mtu mwingine yeyote. Hakuna maana ya kujaribu kuficha taarifa hii, kwa sababu inapatikana kwenye kila nodi hata hivyo. Hakuna siri kwenye mnyororo wa vitalu.

Hamisha Tokeni

Kazi ya transfer inaitwa kuhamisha tokeni kutoka kwa akaunti ya mtumaji kwenda kwa nyingine. Kumbuka kwamba ingawa inarudisha thamani ya boolean, thamani hiyo daima ni kweli. Ikiwa hamisho litashindwa mkataba unatengua mwito.

 

        _transfer(_msgSender(), recipient, amount);
        return true;
    }

Kazi ya _transfer inafanya kazi halisi. Ni kazi ya kibinafsi ambayo inaweza tu kuitwa na kazi zingine za mkataba. Kwa kawaida kazi za kibinafsi hupewa jina _<something>, sawa na vigezo vya hali.

Kawaida katika Solidity tunatumia msg.sender kwa mtumaji wa ujumbe. Hata hivyo, hiyo inavunja OpenGSN (opens in a new tab). Ikiwa tunataka kuruhusu miamala isiyo na Etha na tokeni yetu, tunahitaji kutumia _msgSender(). Inarudisha msg.sender kwa miamala ya kawaida, lakini kwa ile isiyo na Etha inarudisha mtia saini wa asili na sio mkataba uliopitisha ujumbe.

Kazi za Kibali

Hizi ni kazi zinazotekeleza utendaji wa kibali: allowance, approve, transferFrom, na _approve. Zaidi ya hayo, utekelezaji wa OpenZeppelin unaenda zaidi ya kiwango cha msingi ili kujumuisha baadhi ya vipengele vinavyoboresha usalama: increaseAllowance, na decreaseAllowance.

Kazi ya kibali

    /**
     * @dev Tazama {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

Kazi ya allowance inaruhusu kila mtu kuangalia kibali chochote.

Kazi ya kuidhinisha

    /**
     * @dev Tazama {IERC20-approve}.
     *
     * Mahitaji:
     *
     * - `spender` haiwezi kuwa anwani sifuri.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {

Kazi hii inaitwa kuunda kibali. Inafanana na kazi ya transfer hapo juu:

  • Kazi inaita tu kazi ya ndani (katika kesi hii, _approve) ambayo inafanya kazi halisi.
  • Kazi inarudisha true (ikiwa imefanikiwa) au inatengua (ikiwa sivyo).

 

        _approve(_msgSender(), spender, amount);
        return true;
    }

Tunatumia kazi za ndani ili kupunguza idadi ya maeneo ambapo mabadiliko ya hali hutokea. Kazi yoyote inayobadilisha hali ni hatari inayowezekana ya usalama ambayo inahitaji kukaguliwa kwa usalama. Kwa njia hii tuna nafasi ndogo za kukosea.

Kazi ya transferFrom

Hii ni kazi ambayo mtumiaji anaita ili kutumia kibali. Hii inahitaji shughuli mbili: kuhamisha kiasi kinachotumiwa na kupunguza kibali kwa kiasi hicho.

 

Mwito wa kazi wa a.sub(b, "message") unafanya mambo mawili. Kwanza, inakokotoa a-b, ambayo ni kibali kipya. Pili, inaangalia kuwa matokeo haya sio hasi. Ikiwa ni hasi mwito unatengua na ujumbe uliotolewa. Kumbuka kwamba wakati mwito unatengua usindikaji wowote uliofanywa hapo awali wakati wa mwito huo unapuuzwa kwa hivyo hatuhitaji kutengua _transfer.

        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount,
             "ERC20: transfer amount exceeds allowance"));
        return true;
    }

Nyongeza za usalama za OpenZeppelin

Ni hatari kuweka kibali kisicho sifuri kwa thamani nyingine isiyo sifuri, kwa sababu unadhibiti tu mpangilio wa miamala yako mwenyewe, sio ya mtu mwingine yeyote. Fikiria una watumiaji wawili, Alice ambaye ni mjinga na Bill ambaye si mwaminifu. Alice anataka huduma fulani kutoka kwa Bill, ambayo anafikiri inagharimu tokeni tano - kwa hivyo anampa Bill kibali cha tokeni tano.

Kisha kitu kinabadilika na bei ya Bill inapanda hadi tokeni kumi. Alice, ambaye bado anataka huduma, anatuma muamala unaoweka kibali cha Bill kuwa kumi. Wakati Bill anapoona muamala huu mpya katika kusanyiko la miamala anatuma muamala unaotumia tokeni tano za Alice na una bei ya gesi ya juu zaidi ili uchimbwe haraka zaidi. Kwa njia hiyo Bill anaweza kutumia tokeni tano za kwanza na kisha, mara tu kibali kipya cha Alice kinapochimbwa, kutumia kumi zaidi kwa bei ya jumla ya tokeni kumi na tano, zaidi ya vile Alice alivyokusudia kuidhinisha. Mbinu hii inaitwa utangulizaji muamala (opens in a new tab)

Muamala wa AliceNonsi ya AliceMuamala wa BillNonsi ya BillKibali cha BillJumla ya Mapato ya Bill kutoka kwa Alice
approve(Bill, 5)1050
transferFrom(Alice, Bill, 5)10,12305
approve(Bill, 10)11105
transferFrom(Alice, Bill, 10)10,124015

Ili kuepuka tatizo hili, kazi hizi mbili (increaseAllowance na decreaseAllowance) zinakuruhusu kurekebisha kibali kwa kiasi maalum. Kwa hivyo ikiwa Bill alikuwa tayari ametumia tokeni tano, ataweza tu kutumia tano zaidi. Kulingana na muda, kuna njia mbili ambazo hii inaweza kufanya kazi, zote mbili zinaishia kwa Bill kupata tokeni kumi tu:

A:

Muamala wa AliceNonsi ya AliceMuamala wa BillNonsi ya BillKibali cha BillJumla ya Mapato ya Bill kutoka kwa Alice
approve(Bill, 5)1050
transferFrom(Alice, Bill, 5)10,12305
increaseAllowance(Bill, 5)110+5 = 55
transferFrom(Alice, Bill, 5)10,124010

B:

Muamala wa AliceNonsi ya AliceMuamala wa BillNonsi ya BillKibali cha BillJumla ya Mapato ya Bill kutoka kwa Alice
approve(Bill, 5)1050
increaseAllowance(Bill, 5)115+5 = 100
transferFrom(Alice, Bill, 10)10,124010

Kazi ya a.add(b) ni nyongeza salama. Katika hali isiyowezekana kwamba a+b>=2^256 haizunguki kwa njia ambayo nyongeza ya kawaida hufanya.

Kazi Zinazobadilisha Taarifa za Tokeni

Hizi ni kazi nne zinazofanya kazi halisi: _transfer, _mint, _burn, na _approve.

Kazi ya _transfer

Kazi hii, _transfer, inahamisha tokeni kutoka akaunti moja hadi nyingine. Inaitwa na zote mbili transfer (kwa uhamisho kutoka kwa akaunti ya mtumaji mwenyewe) na transferFrom (kwa kutumia vibali kuhamisha kutoka kwa akaunti ya mtu mwingine).

 

        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

Hakuna mtu anayemiliki anwani sifuri katika Ethereum (yaani, hakuna anayejua ufunguo wa siri ambao ufunguo wa umma unaolingana nao unabadilishwa kuwa anwani sifuri). Watu wanapotumia anwani hiyo, kwa kawaida ni hitilafu ya programu - kwa hivyo tunashindwa ikiwa anwani sifuri inatumiwa kama mtumaji au mpokeaji.

 

        _beforeTokenTransfer(sender, recipient, amount);

Kuna njia mbili za kutumia mkataba huu:

  1. Uitumie kama kiolezo kwa msimbo wako mwenyewe
  2. Urithi kutoka kwake (opens in a new tab), na ubatilishe tu kazi zile unazohitaji kurekebisha

Njia ya pili ni bora zaidi kwa sababu msimbo wa ERC-20 wa OpenZeppelin tayari umekaguliwa na kuonyeshwa kuwa salama. Unapotumia urithi inakuwa wazi ni kazi gani unazorekebisha, na ili kuamini mkataba wako watu wanahitaji tu kukagua kazi hizo maalum.

Mara nyingi ni muhimu kufanya kazi kila wakati tokeni zinapobadilisha mikono. Hata hivyo, _transfer ni kazi muhimu sana na inawezekana kuiandika kwa njia isiyo salama (tazama hapa chini), kwa hivyo ni bora kutoibatilisha. Suluhisho ni _beforeTokenTransfer, kazi ya ndoano (opens in a new tab). Unaweza kubatilisha kazi hii, na itaitwa kwenye kila hamisho.

 

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);

Hii ndio mistari inayofanya hamisho halisi. Kumbuka kwamba hakuna kitu kati yao, na kwamba tunatoa kiasi kilichohamishwa kutoka kwa mtumaji kabla ya kukiongeza kwa mpokeaji. Hii ni muhimu kwa sababu ikiwa kungekuwa na mwito kwa mkataba tofauti katikati, ingeweza kutumika kudanganya mkataba huu. Kwa njia hii hamisho ni la atomiki, hakuna kinachoweza kutokea katikati yake.

 

        emit Transfer(sender, recipient, amount);
    }

Hatimaye, toa tukio la Transfer. Matukio hayafikiki kwa mikataba mahiri, lakini msimbo unaoendeshwa nje ya mnyororo wa vitalu unaweza kusikiliza matukio na kuyajibu. Kwa mfano, mkoba unaweza kufuatilia wakati mmiliki anapata tokeni zaidi.

Kazi za _mint na _burn

Kazi hizi mbili (_mint na _burn) zinabadilisha jumla ya usambazaji wa tokeni. Ni za ndani na hakuna kazi inayozipiga katika mkataba huu, kwa hivyo zinafaa tu ikiwa unarithi kutoka kwa mkataba na kuongeza mantiki yako mwenyewe kuamua chini ya hali gani ya kufua tokeni mpya au kuteketeza zilizopo.

KUMBUKA: Kila tokeni ya ERC-20 ina mantiki yake ya biashara inayoamuru usimamizi wa tokeni. Kwa mfano, mkataba wa usambazaji uliowekwa unaweza tu kuita _mint katika konstrukta na usiwahi kuita _burn. Mkataba unaouza tokeni utaita _mint unapolipwa, na labda kuita _burn wakati fulani ili kuepuka mfumuko wa bei unaokimbia.

Hakikisha unasasisha _totalSupply wakati jumla ya idadi ya tokeni inabadilika.

 

Kazi ya _burn inakaribia kufanana na _mint, isipokuwa inaenda upande mwingine.

Kazi ya _approve

Hii ndio kazi ambayo inabainisha vibali. Kumbuka kwamba inaruhusu mmiliki kubainisha kibali ambacho ni cha juu kuliko salio la sasa la mmiliki. Hii ni Sawa kwa sababu salio linaangaliwa wakati wa hamisho, ambapo linaweza kuwa tofauti na salio wakati kibali kinaundwa.

 

Toa tukio la Approval. Kulingana na jinsi programu inavyoandikwa, mkataba wa mtumiaji unaweza kuambiwa kuhusu idhini iwe na mmiliki au na seva inayosikiliza matukio haya.

        emit Approval(owner, spender, amount);
    }

Rekebisha Kigezo cha Desimali

Kazi hii inarekebisha kigezo cha _decimals ambacho kinatumika kuambia violesura vya mtumiaji jinsi ya kutafsiri kiasi. Unapaswa kuiita kutoka kwa konstrukta. Ingekuwa si uaminifu kuiita katika hatua yoyote inayofuata, na programu hazijaundwa kushughulikia hilo.

Ndoano

Hii ni kazi ya ndoano itakayoitwa wakati wa uhamisho. Ni tupu hapa, lakini ikiwa unahitaji ifanye kitu unaibatilisha tu.

Hitimisho

Kwa ukaguzi, haya ni baadhi ya mawazo muhimu zaidi katika mkataba huu (kwa maoni yangu, yako yanaweza kutofautiana):

  • Hakuna siri kwenye mnyororo wa vitalu. Taarifa yoyote ambayo mkataba mahiri unaweza kufikia inapatikana kwa ulimwengu mzima.
  • Unaweza kudhibiti mpangilio wa miamala yako mwenyewe, lakini sio wakati muamala wa watu wengine unatokea. Hii ndiyo sababu kubadilisha kibali kunaweza kuwa hatari, kwa sababu inaruhusu mtumiaji kutumia jumla ya vibali vyote viwili.
  • Thamani za aina ya uint256 huzunguka. Kwa maneno mengine, 0-1=2^256-1. Ikiwa hiyo sio tabia inayotakiwa, lazima uiangalie (au utumie maktaba ya SafeMath inayokufanyia hivyo). Kumbuka kwamba hii ilibadilika katika Solidity 0.8.0 (opens in a new tab).
  • Fanya mabadiliko yote ya hali ya aina maalum katika eneo maalum, kwa sababu inafanya ukaguzi kuwa rahisi. Hii ndiyo sababu tunayo, kwa mfano, _approve, ambayo inaitwa na approve, transferFrom, increaseAllowance, na decreaseAllowance
  • Mabadiliko ya hali yanapaswa kuwa ya atomiki, bila kitendo kingine chochote katikati yao (kama unavyoweza kuona katika _transfer). Hii ni kwa sababu wakati wa mabadiliko ya hali unakuwa na hali isiyolingana. Kwa mfano, kati ya wakati unapotoa kutoka kwa salio la mtumaji na wakati unapoongeza kwenye salio la mpokeaji kuna tokeni chache zilizopo kuliko inavyopaswa kuwa. Hii inaweza kutumiwa vibaya ikiwa kuna shughuli kati yao, haswa miito kwa mkataba tofauti.

Sasa kwa kuwa umeona jinsi mkataba wa ERC-20 wa OpenZeppelin unavyoandikwa, na haswa jinsi unavyofanywa kuwa salama zaidi, nenda ukaandike mikataba na programu zako salama.

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