---
title: "⁦ERC-20⁩ کنٹریکٹ کا تفصیلی جائزہ"
description: "اوپن زیپلن ⁦ERC-20⁩ کنٹریکٹ میں کیا ہے اور یہ وہاں کیوں ہے؟"
author: "اوری پومرانٹز"
lang: ur
tags:
  - solidity
  - erc-20
skill: beginner
breadcrumb: "⁦ERC-20⁩ کا تفصیلی جائزہ"
published: 2021-03-09
---

## تعارف {#introduction}

ایتھیریم کے سب سے عام استعمالات میں سے ایک کسی گروپ کے لیے قابلِ تجارت ٹوکن بنانا ہے، جو ایک لحاظ سے ان کی اپنی کرنسی ہوتی ہے۔ یہ ٹوکنز عام طور پر ایک معیار کی پیروی کرتے ہیں، [<span dir="ltr">ERC-20</span>](/developers/docs/standards/tokens/erc-20/)۔ یہ معیار ایسے ٹولز لکھنا ممکن بناتا ہے، جیسے سیالیت کا پول اور والیٹ، جو تمام <span dir="ltr">ERC-20</span> ٹوکنز کے ساتھ کام کرتے ہیں۔ اس مضمون میں ہم [اوپن زیپلن Solidity ERC20 کے نفاذ](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) کے ساتھ ساتھ [انٹرفیس کی تعریف](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) کا تجزیہ کریں گے۔

یہ تشریح شدہ سورس کوڈ ہے۔ اگر آپ <span dir="ltr">ERC-20</span> کو نافذ کرنا چاہتے ہیں، تو [یہ ٹیوٹوریل پڑھیں](https://docs.openzeppelin.com/contracts/2.x/erc20-supply)۔

## انٹرفیس {#the-interface}

<span dir="ltr">ERC-20</span> جیسے معیار کا مقصد بہت سے ٹوکنز کے نفاذ کی اجازت دینا ہے جو ایپلی کیشنز، جیسے والیٹس اور لامركزی ایکسچینجز میں قابلِ باہمی عمل ہوں۔ اسے حاصل کرنے کے لیے، ہم ایک [انٹرفیس](https://www.geeksforgeeks.org/solidity/solidity-basics-of-interface/) بناتے ہیں۔ کوئی بھی کوڈ جسے ٹوکن کنٹریکٹ استعمال کرنے کی ضرورت ہو وہ انٹرفیس میں انہی تعریفوں کا استعمال کر سکتا ہے اور ان تمام ٹوکن کنٹریکٹس کے ساتھ مطابقت رکھ سکتا ہے جو اسے استعمال کرتے ہیں، چاہے وہ میٹاماسک جیسا والیٹ ہو، etherscan.io جیسی غیر مرکزی ایپلی کیشن (dapp) ہو، یا سیالیت کا پول جیسا کوئی مختلف کنٹریکٹ ہو۔

![Illustration of the <span dir="ltr">ERC-20</span> interface](erc20_interface.png)

اگر آپ ایک تجربہ کار پروگرامر ہیں، تو آپ کو شاید [Java](https://www.w3schools.com/java/java_interface.asp) یا یہاں تک کہ [C ہیڈر فائلوں](https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html) میں اسی طرح کی ساختیں دیکھنا یاد ہوگا۔

یہ اوپن زیپلن کی جانب سے [<span dir="ltr">ERC-20</span> انٹرفیس](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) کی ایک تعریف ہے۔ یہ [انسان کے پڑھنے کے قابل معیار](https://eips.ethereum.org/EIPS/eip-20) کا Solidity کوڈ میں ترجمہ ہے۔ یقیناً، انٹرفیس بذات خود یہ واضح نہیں کرتا کہ کوئی کام _کیسے_ کرنا ہے۔ اس کی وضاحت ذیل میں کنٹریکٹ کے سورس کوڈ میں کی گئی ہے۔

&nbsp;

```solidity
// SPDX-License-Identifier: MIT
```

Solidity فائلوں میں لائسنس شناخت کنندہ شامل ہونا چاہیے۔ [آپ یہاں لائسنسز کی فہرست دیکھ سکتے ہیں](https://spdx.org/licenses/)۔ اگر آپ کو کوئی مختلف لائسنس درکار ہے، تو بس اسے تبصروں (comments) میں واضح کر دیں۔

&nbsp;

```solidity
pragma solidity >=0.6.0 <0.8.0;
```

Solidity زبان اب بھی تیزی سے ترقی کر رہی ہے، اور نئے ورژنز پرانے کوڈ کے ساتھ مطابقت نہیں رکھ سکتے ([یہاں دیکھیں](https://docs.soliditylang.org/en/v0.7.0/070-breaking-changes.html))۔ لہذا، یہ ایک اچھا خیال ہے کہ نہ صرف زبان کا کم از کم ورژن متعین کیا جائے، بلکہ زیادہ سے زیادہ ورژن بھی، یعنی وہ تازہ ترین ورژن جس کے ساتھ آپ نے کوڈ کا تجربہ کیا ہے۔

&nbsp;

```solidity
/**
 * @dev EIP میں بیان کردہ ERC-20 معیار کا انٹرفیس۔
 */
```

تبصرے میں موجود `@dev` [NatSpec فارمیٹ](https://docs.soliditylang.org/en/develop/natspec-format.html) کا حصہ ہے، جو سورس کوڈ سے دستاویزات تیار کرنے کے لیے استعمال ہوتا ہے۔

&nbsp;

```solidity
interface IERC20 {
```

روایت کے مطابق، انٹرفیس کے نام `I` سے شروع ہوتے ہیں۔

&nbsp;

```solidity
    /**
     * @dev موجود ٹوکنز کی مقدار واپس کرتا ہے۔
     */
    function totalSupply() external view returns (uint256);
```

یہ فنکشن `external` ہے، جس کا مطلب ہے کہ [اسے صرف کنٹریکٹ کے باہر سے کال کیا جا سکتا ہے](https://docs.soliditylang.org/en/v0.7.0/cheatsheet.html#index-2)۔ یہ کنٹریکٹ میں ٹوکنز کی کل سپلائی واپس کرتا ہے۔ یہ قدر ایتھیریم میں سب سے عام قسم، یعنی <span dir="ltr">unsigned 256 bits</span> کا استعمال کرتے ہوئے واپس کی جاتی ہے (<span dir="ltr">256 bits</span> EVM کا مقامی ورڈ سائز ہے)۔ یہ فنکشن ایک `view` بھی ہے، جس کا مطلب ہے کہ یہ حالت کو تبدیل نہیں کرتا، لہذا اسے بلاک چین میں موجود ہر نوڈ پر چلانے کے بجائے ایک ہی نوڈ پر عمل میں لایا جا سکتا ہے۔ اس قسم کا فنکشن کوئی ٹرانزیکشن پیدا نہیں کرتا اور اس پر [گیس](/developers/docs/gas/) خرچ نہیں ہوتی۔

**نوٹ:** نظریاتی طور پر ایسا لگ سکتا ہے کہ کنٹریکٹ بنانے والا اصل قدر سے کم کل سپلائی واپس کر کے دھوکہ دے سکتا ہے، جس سے ہر ٹوکن اپنی اصل قدر سے زیادہ قیمتی معلوم ہو۔ تاہم، یہ خوف بلاک چین کی اصل نوعیت کو نظر انداز کرتا ہے۔ بلاک چین پر ہونے والی ہر چیز کی تصدیق ہر نوڈ کے ذریعے کی جا سکتی ہے۔ اسے حاصل کرنے کے لیے، ہر کنٹریکٹ کا مشین لینگویج کوڈ اور اسٹوریج ہر نوڈ پر دستیاب ہوتا ہے۔ اگرچہ آپ کے لیے اپنے کنٹریکٹ کا Solidity کوڈ شائع کرنا لازمی نہیں ہے، لیکن کوئی بھی آپ کو اس وقت تک سنجیدگی سے نہیں لے گا جب تک کہ آپ سورس کوڈ اور Solidity کا وہ ورژن شائع نہ کریں جس کے ساتھ اسے مرتب (compile) کیا گیا تھا، تاکہ آپ کے فراہم کردہ مشین لینگویج کوڈ سے اس کی تصدیق کی جا سکے۔
مثال کے طور پر، [یہ کنٹریکٹ دیکھیں](https://eth.blockscout.com/address/0xa530F85085C6FE2f866E7FdB716849714a89f4CD?tab=contract)۔

&nbsp;

```solidity
    /**
     * @dev `account` کی ملکیت میں موجود ٹوکنز کی مقدار واپس کرتا ہے۔
     */
    function balanceOf(address account) external view returns (uint256);
```

جیسا کہ نام سے ظاہر ہے، `balanceOf` کسی اکاؤنٹ کا بیلنس واپس کرتا ہے۔ ایتھیریم اکاؤنٹس کی شناخت Solidity میں `address` قسم کا استعمال کرتے ہوئے کی جاتی ہے، جو <span dir="ltr">160 bits</span> پر مشتمل ہوتی ہے۔ یہ بھی `external` اور `view` ہے۔

&nbsp;

```solidity
    /**
     * @dev کالر کے اکاؤنٹ سے `recipient` کو `amount` ٹوکنز منتقل کرتا ہے۔
     *
     * ایک بولین ویلیو واپس کرتا ہے جو بتاتی ہے کہ آیا آپریشن کامیاب ہوا۔
     *
     * ایک {Transfer} ایونٹ خارج کرتا ہے۔
     */
    function transfer(address recipient, uint256 amount) external returns (bool);
```

`transfer` فنکشن کال کرنے والے سے ٹوکنز کو کسی مختلف پتہ پر منتقل کرتا ہے۔ اس میں حالت کی تبدیلی شامل ہے، لہذا یہ `view` نہیں ہے۔ جب کوئی صارف اس فنکشن کو کال کرتا ہے تو یہ ایک ٹرانزیکشن بناتا ہے اور اس پر گیس خرچ ہوتی ہے۔ یہ ایک ایونٹ، `Transfer` بھی خارج کرتا ہے، تاکہ بلاک چین پر موجود ہر شخص کو اس ایونٹ کی اطلاع مل سکے۔

اس فنکشن میں دو مختلف قسم کے کال کرنے والوں کے لیے دو قسم کے آؤٹ پٹ ہوتے ہیں:

- وہ صارفین جو یوزر انٹرفیس سے براہ راست فنکشن کو کال کرتے ہیں۔ عام طور پر صارف ایک ٹرانزیکشن جمع کراتا ہے اور جواب کا انتظار نہیں کرتا، جس میں غیر معینہ وقت لگ سکتا ہے۔ صارف ٹرانزیکشن کی رسید (جس کی شناخت ٹرانزیکشن ہیش سے ہوتی ہے) یا `Transfer` ایونٹ کو دیکھ کر جان سکتا ہے کہ کیا ہوا۔
- دوسرے کنٹریکٹس، جو مجموعی ٹرانزیکشن کے حصے کے طور پر فنکشن کو کال کرتے ہیں۔ ان کنٹریکٹس کو فوری طور پر نتیجہ مل جاتا ہے، کیونکہ وہ اسی ٹرانزیکشن میں چلتے ہیں، لہذا وہ فنکشن کی ریٹرن ویلیو استعمال کر سکتے ہیں۔

اسی قسم کا آؤٹ پٹ ان دیگر فنکشنز کے ذریعے بھی بنایا جاتا ہے جو کنٹریکٹ کی حالت کو تبدیل کرتے ہیں۔

&nbsp;

الاؤنسز کسی اکاؤنٹ کو کچھ ایسے ٹوکنز خرچ کرنے کی اجازت دیتے ہیں جو کسی دوسرے مالک کے ہوتے ہیں۔ یہ مفید ہے، مثال کے طور پر، ان کنٹریکٹس کے لیے جو بیچنے والے کے طور پر کام کرتے ہیں۔ کنٹریکٹس ایونٹس کی نگرانی نہیں کر سکتے، لہذا اگر کوئی خریدار براہ راست بیچنے والے کے کنٹریکٹ میں ٹوکنز منتقل کرے تو اس کنٹریکٹ کو معلوم نہیں ہوگا کہ اسے ادائیگی کی گئی ہے۔ اس کے بجائے، خریدار بیچنے والے کے کنٹریکٹ کو ایک مخصوص رقم خرچ کرنے کی اجازت دیتا ہے، اور بیچنے والا وہ رقم منتقل کر لیتا ہے۔ یہ ایک ایسے فنکشن کے ذریعے کیا جاتا ہے جسے بیچنے والے کا کنٹریکٹ کال کرتا ہے، تاکہ بیچنے والے کا کنٹریکٹ جان سکے کہ آیا یہ کامیاب رہا۔

```solidity
    /**
     * @dev ٹوکنز کی وہ بقیہ تعداد واپس کرتا ہے جو `spender` کو {transferFrom} کے ذریعے `owner` کی جانب سے خرچ کرنے کی اجازت ہوگی۔ یہ ڈیفالٹ کے طور پر صفر ہے۔
     *
     * یہ ویلیو تب تبدیل ہوتی ہے جب {approve} یا {transferFrom} کو کال کیا جاتا ہے۔
     */
    function allowance(address owner, address spender) external view returns (uint256);
```

`allowance` فنکشن کسی کو بھی یہ جاننے کی اجازت دیتا ہے کہ ایک پتہ (`owner`) دوسرے پتہ (`spender`) کو کتنا الاؤنس خرچ کرنے دیتا ہے۔

&nbsp;

```solidity
    /**
     * @dev کالر کے ٹوکنز پر `spender` کے الاؤنس کے طور پر `amount` سیٹ کرتا ہے۔
     *
     * ایک بولین ویلیو واپس کرتا ہے جو بتاتی ہے کہ آیا آپریشن کامیاب ہوا۔
     *
     * اہم: ہوشیار رہیں کہ اس طریقے سے الاؤنس کو تبدیل کرنے سے یہ خطرہ پیدا ہوتا ہے کہ کوئی بدقسمت ٹرانزیکشن کی ترتیب کی وجہ سے پرانے اور نئے دونوں الاؤنس استعمال کر سکتا ہے۔ اس ریس کنڈیشن کو کم کرنے کا ایک ممکنہ حل یہ ہے کہ پہلے خرچ کرنے والے کا الاؤنس 0 کر دیا جائے اور اس کے بعد مطلوبہ ویلیو سیٹ کی جائے:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * ایک {Approval} ایونٹ خارج کرتا ہے۔
     */
    function approve(address spender, uint256 amount) external returns (bool);
```

`approve` فنکشن ایک الاؤنس بناتا ہے۔ اس بارے میں پیغام ضرور پڑھیں کہ اس کا غلط استعمال کیسے کیا جا سکتا ہے۔ ایتھیریم میں آپ اپنی ٹرانزیکشنز کی ترتیب کو کنٹرول کرتے ہیں، لیکن آپ اس ترتیب کو کنٹرول نہیں کر سکتے جس میں دوسرے لوگوں کی ٹرانزیکشنز پر عمل درآمد ہوگا، جب تک کہ آپ اپنی ٹرانزیکشن اس وقت تک جمع نہ کرائیں جب تک کہ آپ یہ نہ دیکھ لیں کہ دوسرے فریق کی ٹرانزیکشن ہو چکی ہے۔

&nbsp;

```solidity
    /**
     * @dev الاؤنس کے طریقہ کار کا استعمال کرتے ہوئے `sender` سے `recipient` کو `amount` ٹوکنز منتقل کرتا ہے۔ پھر کالر کے الاؤنس سے `amount` کی کٹوتی کی جاتی ہے۔
     *
     * ایک بولین ویلیو واپس کرتا ہے جو بتاتی ہے کہ آیا آپریشن کامیاب ہوا۔
     *
     * ایک {Transfer} ایونٹ خارج کرتا ہے۔
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
```

آخر میں، `transferFrom` خرچ کرنے والے کے ذریعے الاؤنس کو درحقیقت خرچ کرنے کے لیے استعمال کیا جاتا ہے۔

&nbsp;

```solidity

    /**
     * @dev تب خارج ہوتا ہے جب `value` ٹوکنز ایک اکاؤنٹ (`from`) سے دوسرے (`to`) میں منتقل کیے جاتے ہیں۔
     *
     * نوٹ کریں کہ `value` صفر ہو سکتی ہے۔
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev تب خارج ہوتا ہے جب {approve} کی کال کے ذریعے کسی `owner` کے لیے `spender` کا الاؤنس سیٹ کیا جاتا ہے۔ `value` نیا الاؤنس ہے۔
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
```

یہ ایونٹس اس وقت خارج ہوتے ہیں جب <span dir="ltr">ERC-20</span> کنٹریکٹ کی حالت تبدیل ہوتی ہے۔

## اصل کنٹریکٹ {#the-actual-contract}

یہ وہ اصل کنٹریکٹ ہے جو <span dir="ltr">ERC-20</span> معیار کو نافذ کرتا ہے، جسے [یہاں سے لیا گیا ہے](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)۔ اسے جوں کا توں استعمال کرنے کا ارادہ نہیں ہے، لیکن آپ اسے قابل استعمال بنانے کے لیے اس سے [وراثت (inherit)](https://www.tutorialspoint.com/solidity/solidity_inheritance.htm) لے سکتے ہیں۔

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

&nbsp;

### امپورٹ اسٹیٹمنٹس {#import-statements}

اوپر دی گئی انٹرفیس کی تعریفوں کے علاوہ، کنٹریکٹ کی تعریف دو دیگر فائلوں کو امپورٹ کرتی ہے:

```solidity

import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
```

- `GSN/Context.sol` وہ تعریفیں ہیں جو [OpenGSN](https://opengsn.org/) استعمال کرنے کے لیے درکار ہیں، یہ ایک ایسا نظام ہے جو ایتھر کے بغیر صارفین کو بلاک چین استعمال کرنے کی اجازت دیتا ہے۔ نوٹ کریں کہ یہ ایک پرانا ورژن ہے، اگر آپ OpenGSN کے ساتھ انضمام کرنا چاہتے ہیں تو [یہ ٹیوٹوریل استعمال کریں](https://docs.opengsn.org/javascript-client/tutorial.html)۔
- [SafeMath لائبریری](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/)، جو Solidity کے **<span dir="ltr">&lt;0.8.0</span>** ورژنز کے لیے حسابی اوور فلو/انڈر فلو کو روکتی ہے۔ Solidity <span dir="ltr">≥0.8.0</span> میں، حسابی کارروائیاں اوور فلو/انڈر فلو پر خود بخود ریورٹ ہو جاتی ہیں، جس سے SafeMath غیر ضروری ہو جاتا ہے۔ یہ کنٹریکٹ پرانے کمپائلر ورژنز کے ساتھ پچھلی مطابقت (backward compatibility) کے لیے SafeMath کا استعمال کرتا ہے۔

&nbsp;

یہ تبصرہ کنٹریکٹ کے مقصد کی وضاحت کرتا ہے۔

```solidity
/**
 * @dev {IERC20} انٹرفیس کا نفاذ۔
 *
 * یہ نفاذ اس بات سے لاپرواہ ہے کہ ٹوکنز کیسے بنائے جاتے ہیں۔ اس کا مطلب ہے کہ {_mint} کا استعمال کرتے ہوئے اخذ کردہ کنٹریکٹ میں سپلائی کا طریقہ کار شامل کرنا ہوگا۔
 * عمومی طریقہ کار کے لیے {ERC20PresetMinterPauser} دیکھیں۔
 *
 * ٹپ: تفصیلی تحریر کے لیے ہماری گائیڈ دیکھیں
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * ہم نے اوپن زیپلن کی عمومی ہدایات کی پیروی کی ہے: فنکشنز ناکامی پر `false` واپس کرنے کے بجائے ریورٹ (revert) ہو جاتے ہیں۔ یہ رویہ بہرحال روایتی ہے اور ERC-20 ایپلی کیشنز کی توقعات سے متصادم نہیں ہے۔
 *
 * مزید برآں، {transferFrom} کی کالز پر ایک {Approval} ایونٹ خارج ہوتا ہے۔
 * یہ ایپلی کیشنز کو صرف مذکورہ ایونٹس کو سن کر تمام اکاؤنٹس کے لیے الاؤنس کو دوبارہ بنانے کی اجازت دیتا ہے۔ EIP کے دیگر نفاذ شاید ان ایونٹس کو خارج نہ کریں، کیونکہ یہ تصریح کے ذریعہ درکار نہیں ہے۔
 *
 * آخر میں، الاؤنسز سیٹ کرنے کے حوالے سے معروف مسائل کو کم کرنے کے لیے غیر معیاری {decreaseAllowance} اور {increaseAllowance}
 * فنکشنز شامل کیے گئے ہیں۔ {IERC20-approve} دیکھیں۔
 */

```

### کنٹریکٹ کی تعریف {#contract-definition}

```solidity
contract ERC20 is Context, IERC20 {
```

یہ لائن وراثت کی وضاحت کرتی ہے، اس صورت میں اوپر سے `IERC20` اور OpenGSN کے لیے `Context` سے۔

&nbsp;

```solidity

    using SafeMath for uint256;

```

یہ لائن `SafeMath` لائبریری کو `uint256` قسم کے ساتھ منسلک کرتی ہے۔ آپ یہ لائبریری [یہاں](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol) تلاش کر سکتے ہیں۔

### متغیرات کی تعریفیں {#variable-definitions}

یہ تعریفیں کنٹریکٹ کے حالت کے متغیرات (state variables) کی وضاحت کرتی ہیں۔ ان متغیرات کو `private` قرار دیا گیا ہے، لیکن اس کا مطلب صرف یہ ہے کہ بلاک چین پر موجود دیگر کنٹریکٹس انہیں پڑھ نہیں سکتے۔ _بلاک چین پر کوئی راز نہیں ہوتے_، ہر نوڈ پر موجود سافٹ ویئر کے پاس ہر بلاک پر ہر کنٹریکٹ کی حالت ہوتی ہے۔ روایت کے مطابق، حالت کے متغیرات کا نام `_<something>` رکھا جاتا ہے۔

پہلے دو متغیرات [میپنگز (mappings)](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) ہیں، جس کا مطلب ہے کہ وہ تقریباً [ایسوسی ایٹو اریز (associative arrays)](https://wikipedia.org/wiki/Associative_array) کی طرح برتاؤ کرتے ہیں، سوائے اس کے کہ کیز (keys) عددی قدریں ہوتی ہیں۔ اسٹوریج صرف ان اندراجات کے لیے مختص کی جاتی ہے جن کی قدریں ڈیفالٹ (صفر) سے مختلف ہوتی ہیں۔

```solidity
    mapping (address => uint256) private _balances;
```

پہلی میپنگ، `_balances`، پتے اور اس ٹوکن کے ان کے متعلقہ بیلنس ہیں۔ بیلنس تک رسائی کے لیے، یہ نحو (syntax) استعمال کریں: `_balances[<address>]`۔

&nbsp;

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

یہ متغیر، `_allowances`، ان الاؤنسز کو اسٹور کرتا ہے جن کی وضاحت پہلے کی گئی تھی۔ پہلا اشاریہ ٹوکنز کا مالک ہے، اور دوسرا الاؤنس والا کنٹریکٹ ہے۔ اس رقم تک رسائی حاصل کرنے کے لیے جو پتہ A پتہ B کے اکاؤنٹ سے خرچ کر سکتا ہے، `_allowances[B][A]` استعمال کریں۔

&nbsp;

```solidity
    uint256 private _totalSupply;
```

جیسا کہ نام سے ظاہر ہے، یہ متغیر ٹوکنز کی کل سپلائی کا ریکارڈ رکھتا ہے۔

&nbsp;

```solidity
    string private _name;
    string private _symbol;
    uint8 private _decimals;
```

یہ تین متغیرات پڑھنے کی اہلیت کو بہتر بنانے کے لیے استعمال ہوتے ہیں۔ پہلے دو خود وضاحتی ہیں، لیکن `_decimals` نہیں ہے۔

ایک طرف، ایتھیریم میں فلوٹنگ پوائنٹ یا کسر والے متغیرات نہیں ہوتے ہیں۔ دوسری طرف، انسان ٹوکنز کو تقسیم کرنے کے قابل ہونا پسند کرتے ہیں۔ لوگوں کے کرنسی کے طور پر سونے پر متفق ہونے کی ایک وجہ یہ تھی کہ جب کوئی بطخ کی قیمت کے برابر گائے خریدنا چاہتا تھا تو ریزگاری (change) بنانا مشکل تھا۔

اس کا حل یہ ہے کہ انٹیجرز (integers) کا ریکارڈ رکھا جائے، لیکن اصلی ٹوکن کے بجائے ایک کسر والے ٹوکن کو گنا جائے جو تقریباً بے وقعت ہو۔ ایتھر کے معاملے میں، کسر والے ٹوکن کو Wei کہا جاتا ہے، اور <span dir="ltr">10^18 Wei</span> ایک ETH کے برابر ہے۔ لکھتے وقت، <span dir="ltr">10,000,000,000,000 Wei</span> تقریباً ایک امریکی یا یورو سینٹ کے برابر ہے۔

ایپلی کیشنز کو یہ جاننے کی ضرورت ہوتی ہے کہ ٹوکن کا بیلنس کیسے دکھایا جائے۔ اگر کسی صارف کے پاس <span dir="ltr">3,141,000,000,000,000,000 Wei</span> ہیں، تو کیا یہ <span dir="ltr">3.14 ETH</span> ہے؟ <span dir="ltr">31.41 ETH</span>؟ <span dir="ltr">3,141 ETH</span>؟ ایتھر کے معاملے میں یہ <span dir="ltr">10^18 Wei</span> فی ETH بیان کیا گیا ہے، لیکن اپنے ٹوکن کے لیے آپ ایک مختلف قدر منتخب کر سکتے ہیں۔ اگر ٹوکن کو تقسیم کرنے کا کوئی مطلب نہیں بنتا، تو آپ `_decimals` کی قدر صفر استعمال کر سکتے ہیں۔ اگر آپ ETH جیسا ہی معیار استعمال کرنا چاہتے ہیں، تو قدر **18** استعمال کریں۔

### کنسٹرکٹر {#the-constructor}

```solidity
    /**
     * @dev {name} اور {symbol} کے لیے ویلیوز سیٹ کرتا ہے، {decimals} کو 18 کی ڈیفالٹ ویلیو کے ساتھ شروع کرتا ہے۔
     *
     * {decimals} کے لیے مختلف ویلیو منتخب کرنے کے لیے، {_setupDecimals} استعمال کریں۔
     *
     * یہ تینوں ویلیوز ناقابلِ تغیر ہیں: انہیں کنسٹرکشن کے دوران صرف ایک بار سیٹ کیا جا سکتا ہے۔
     */
    constructor (string memory name_, string memory symbol_) public {
        // Solidity ≥0.7.0 میں، 'public' مضمر ہے اور اسے چھوڑا جا سکتا ہے۔

        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }
```

کنسٹرکٹر کو اس وقت کال کیا جاتا ہے جب کنٹریکٹ پہلی بار بنایا جاتا ہے۔ روایت کے مطابق، فنکشن کے پیرامیٹرز کا نام `<something>_` رکھا جاتا ہے۔

### یوزر انٹرفیس فنکشنز {#user-interface-functions}

```solidity
    /**
     * @dev ٹوکن کا نام واپس کرتا ہے۔
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev ٹوکن کی علامت واپس کرتا ہے، جو عام طور پر نام کا ایک چھوٹا ورژن ہوتا ہے۔
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev اس کی صارف کی نمائندگی حاصل کرنے کے لیے استعمال ہونے والے اعشاریوں کی تعداد واپس کرتا ہے۔
     * مثال کے طور پر، اگر `decimals` کی ویلیو `2` ہے، تو `505` ٹوکنز کا بیلنس
     * صارف کو `5,05` (`505 / 10 ** 2`) کے طور پر دکھایا جانا چاہیے۔
     *
     * ٹوکنز عام طور پر 18 کی ویلیو کا انتخاب کرتے ہیں، جو ایتھر اور Wei کے درمیان تعلق کی نقل کرتا ہے۔ یہ وہ ویلیو ہے جو {ERC20} استعمال کرتا ہے، جب تک کہ {_setupDecimals} کو
     * کال نہ کیا جائے۔
     *
     * نوٹ: یہ معلومات صرف _دکھانے_ کے مقاصد کے لیے استعمال ہوتی ہے: یہ
     * کسی بھی طرح کنٹریکٹ کے حساب کتاب کو متاثر نہیں کرتی، بشمول
     * {IERC20-balanceOf} اور {IERC20-transfer}۔
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
```

یہ فنکشنز، `name`، `symbol`، اور `decimals` یوزر انٹرفیسز کو آپ کے کنٹریکٹ کے بارے میں جاننے میں مدد کرتے ہیں تاکہ وہ اسے صحیح طریقے سے دکھا سکیں۔

ریٹرن ٹائپ `string memory` ہے، جس کا مطلب ہے کہ ایک سٹرنگ واپس کریں جو میموری میں اسٹور ہو۔ متغیرات، جیسے سٹرنگز، کو تین مقامات پر اسٹور کیا جا سکتا ہے:

| | لائف ٹائم | کنٹریکٹ تک رسائی | گیس کی قیمت |
| -------- | ------------- | --------------- | -------------------------------------------------------------- |
| میموری | فنکشن کال | پڑھنا/لکھنا | دسیوں یا سینکڑوں (اعلی مقامات کے لیے زیادہ) |
| کال ڈیٹا | فنکشن کال | صرف پڑھنے کے لیے | ریٹرن ٹائپ کے طور پر استعمال نہیں کیا جا سکتا، صرف فنکشن پیرامیٹر ٹائپ کے طور پر |
| اسٹوریج | تبدیل ہونے تک | پڑھنا/لکھنا | زیادہ (پڑھنے کے لیے 800، لکھنے کے لیے 20k) |

اس صورت میں، `memory` بہترین انتخاب ہے۔

### ٹوکن کی معلومات پڑھیں {#read-token-information}

یہ وہ فنکشنز ہیں جو ٹوکن کے بارے میں معلومات فراہم کرتے ہیں، یا تو کل سپلائی یا کسی اکاؤنٹ کا بیلنس۔

```solidity
    /**
     * @dev {IERC20-totalSupply} دیکھیں۔
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }
```

`totalSupply` فنکشن ٹوکنز کی کل سپلائی واپس کرتا ہے۔

&nbsp;

```solidity
    /**
     * @dev {IERC20-balanceOf} دیکھیں۔
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }
```

کسی اکاؤنٹ کا بیلنس پڑھیں۔ نوٹ کریں کہ کسی کو بھی کسی دوسرے کے اکاؤنٹ کا بیلنس حاصل کرنے کی اجازت ہے۔ اس معلومات کو چھپانے کی کوشش کرنے کا کوئی فائدہ نہیں ہے، کیونکہ یہ ویسے بھی ہر نوڈ پر دستیاب ہے۔ _بلاک چین پر کوئی راز نہیں ہوتے۔_

### ٹوکنز کی منتقلی {#transfer-tokens}

```solidity
    /**
     * @dev {IERC20-transfer} دیکھیں۔
     *
     * تقاضے:
     *
     * - `recipient` صفر ایڈریس نہیں ہو سکتا۔
     * - کالر کے پاس کم از کم `amount` کا بیلنس ہونا چاہیے۔
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
```

`transfer` فنکشن بھیجنے والے کے اکاؤنٹ سے کسی دوسرے اکاؤنٹ میں ٹوکنز کی منتقلی کے لیے کال کیا جاتا ہے۔ نوٹ کریں کہ اگرچہ یہ ایک بولین (boolean) قدر واپس کرتا ہے، لیکن وہ قدر ہمیشہ **true** ہوتی ہے۔ اگر منتقلی ناکام ہو جاتی ہے تو کنٹریکٹ کال کو ریورٹ کر دیتا ہے۔

&nbsp;

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

`_transfer` فنکشن اصل کام کرتا ہے۔ یہ ایک پرائیویٹ فنکشن ہے جسے صرف کنٹریکٹ کے دیگر فنکشنز ہی کال کر سکتے ہیں۔ روایت کے مطابق پرائیویٹ فنکشنز کا نام `_<something>` رکھا جاتا ہے، بالکل حالت کے متغیرات کی طرح۔

عام طور پر Solidity میں ہم پیغام بھیجنے والے کے لیے `msg.sender` استعمال کرتے ہیں۔ تاہم، اس سے [OpenGSN](https://opengsn.org/) ٹوٹ جاتا ہے۔ اگر ہم اپنے ٹوکن کے ساتھ ایتھر کے بغیر ٹرانزیکشنز کی اجازت دینا چاہتے ہیں، تو ہمیں `_msgSender()` استعمال کرنے کی ضرورت ہے۔ یہ عام ٹرانزیکشنز کے لیے `msg.sender` واپس کرتا ہے، لیکن ایتھر کے بغیر ٹرانزیکشنز کے لیے اصل دستخط کنندہ کو واپس کرتا ہے نہ کہ اس کنٹریکٹ کو جس نے پیغام کو ریلے کیا تھا۔

### الاؤنس فنکشنز {#allowance-functions}

یہ وہ فنکشنز ہیں جو الاؤنس کی فعالیت کو نافذ کرتے ہیں: `allowance`، `approve`، `transferFrom`، اور `_approve`۔ مزید برآں، اوپن زیپلن کا نفاذ بنیادی معیار سے آگے بڑھ کر کچھ ایسی خصوصیات شامل کرتا ہے جو سیکیورٹی کو بہتر بناتی ہیں: `increaseAllowance`، اور `decreaseAllowance`۔

#### الاؤنس فنکشن {#allowance}

```solidity
    /**
     * @dev {IERC20-allowance} دیکھیں۔
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }
```

`allowance` فنکشن ہر کسی کو کسی بھی الاؤنس کو چیک کرنے کی اجازت دیتا ہے۔

#### منظور کرنے کا فنکشن {#approve}

```solidity
    /**
     * @dev {IERC20-approve} دیکھیں۔
     *
     * تقاضے:
     *
     * - `spender` صفر ایڈریس نہیں ہو سکتا۔
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
```

یہ فنکشن الاؤنس بنانے کے لیے کال کیا جاتا ہے۔ یہ اوپر دیے گئے `transfer` فنکشن سے ملتا جلتا ہے:

- یہ فنکشن صرف ایک اندرونی فنکشن (اس صورت میں، `_approve`) کو کال کرتا ہے جو اصل کام کرتا ہے۔
- یہ فنکشن یا تو `true` واپس کرتا ہے (اگر کامیاب ہو) یا ریورٹ کر دیتا ہے (اگر نہ ہو)۔

&nbsp;

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

ہم اندرونی فنکشنز کا استعمال کرتے ہیں تاکہ ان جگہوں کی تعداد کو کم کیا جا سکے جہاں حالت میں تبدیلیاں ہوتی ہیں۔ _کوئی بھی_ فنکشن جو حالت کو تبدیل کرتا ہے وہ ایک ممکنہ سیکیورٹی خطرہ ہے جس کا سیکیورٹی کے لیے آڈٹ ہونا ضروری ہے۔ اس طرح ہمارے پاس غلطی کرنے کے امکانات کم ہوتے ہیں۔

#### transferFrom فنکشن {#transferfrom}

یہ وہ فنکشن ہے جسے خرچ کرنے والا الاؤنس خرچ کرنے کے لیے کال کرتا ہے۔ اس کے لیے دو کارروائیوں کی ضرورت ہوتی ہے: خرچ کی جانے والی رقم کو منتقل کرنا اور الاؤنس کو اس رقم سے کم کرنا۔

```solidity
    /**
     * @dev {IERC20-transferFrom} دیکھیں۔
     *
     * اپ ڈیٹ شدہ الاؤنس کی نشاندہی کرنے والا ایک {Approval} ایونٹ خارج کرتا ہے۔ یہ EIP کے ذریعہ
     * درکار نہیں ہے۔ {ERC20} کے شروع میں نوٹ دیکھیں۔
     *
     * تقاضے:
     *
     * - `sender` اور `recipient` صفر ایڈریس نہیں ہو سکتے۔
     * - `sender` کے پاس کم از کم `amount` کا بیلنس ہونا چاہیے۔
     * - کالر کے پاس ``sender`` کے ٹوکنز کے لیے کم از کم
     * `amount` کا الاؤنس ہونا چاہیے۔
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual
                                                override returns (bool) {
        _transfer(sender, recipient, amount);
```

&nbsp;

`a.sub(b, "message")` فنکشن کال دو کام کرتی ہے۔ پہلا، یہ `a-b` کا حساب لگاتی ہے، جو نیا الاؤنس ہے۔ دوسرا، یہ چیک کرتی ہے کہ یہ نتیجہ منفی تو نہیں ہے۔ اگر یہ منفی ہے تو کال فراہم کردہ پیغام کے ساتھ ریورٹ ہو جاتی ہے۔ نوٹ کریں کہ جب کوئی کال ریورٹ ہوتی ہے تو اس کال کے دوران پہلے کی گئی کسی بھی پروسیسنگ کو نظر انداز کر دیا جاتا ہے لہذا ہمیں `_transfer` کو ان ڈو (undo) کرنے کی ضرورت نہیں ہے۔

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

#### اوپن زیپلن کے حفاظتی اضافے {#openzeppelin-safety-additions}

کسی غیر صفر الاؤنس کو دوسری غیر صفر قدر پر سیٹ کرنا خطرناک ہے، کیونکہ آپ صرف اپنی ٹرانزیکشنز کی ترتیب کو کنٹرول کرتے ہیں، کسی اور کی نہیں۔ تصور کریں کہ آپ کے پاس دو صارفین ہیں، ایلس جو سادہ لوح ہے اور بل جو بے ایمان ہے۔ ایلس بل سے کچھ سروس چاہتی ہے، جس کی قیمت اس کے خیال میں پانچ ٹوکنز ہے - لہذا وہ بل کو پانچ ٹوکنز کا الاؤنس دیتی ہے۔

پھر کچھ تبدیل ہوتا ہے اور بل کی قیمت بڑھ کر دس ٹوکنز ہو جاتی ہے۔ ایلس، جو اب بھی سروس چاہتی ہے، ایک ٹرانزیکشن بھیجتی ہے جو بل کا الاؤنس دس پر سیٹ کر دیتی ہے۔ جس لمحے بل ٹرانزیکشن پول میں اس نئی ٹرانزیکشن کو دیکھتا ہے وہ ایک ٹرانزیکشن بھیجتا ہے جو ایلس کے پانچ ٹوکنز خرچ کرتی ہے اور اس کی گیس کی قیمت بہت زیادہ ہوتی ہے تاکہ اسے تیزی سے مائن کیا جا سکے۔ اس طرح بل پہلے پانچ ٹوکنز خرچ کر سکتا ہے اور پھر، جب ایلس کا نیا الاؤنس مائن ہو جاتا ہے، تو مزید دس خرچ کر سکتا ہے جس کی کل قیمت پندرہ ٹوکنز بنتی ہے، جو کہ ایلس کی اجازت سے زیادہ ہے۔ اس تکنیک کو [فرنٹ رننگ](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/#front-running) کہا جاتا ہے۔

| ایلس کی ٹرانزیکشن | ایلس کا نانس | بل کی ٹرانزیکشن | بل کا نانس | بل کا الاؤنس | ایلس سے بل کی کل آمدنی |
| ----------------- | ----------- | ----------------------------- | ---------- | ---------------- | ---------------------------- |
| approve(Bill, 5) | 10 | | | 5 | 0 |
| | | transferFrom(Alice, Bill, 5) | <span dir="ltr">10,123</span> | 0 | 5 |
| approve(Bill, 10) | 11 | | | 10 | 5 |
| | | transferFrom(Alice, Bill, 10) | <span dir="ltr">10,124</span> | 0 | 15 |

اس مسئلے سے بچنے کے لیے، یہ دو فنکشنز (`increaseAllowance` اور `decreaseAllowance`) آپ کو الاؤنس میں ایک مخصوص رقم سے ترمیم کرنے کی اجازت دیتے ہیں۔ لہذا اگر بل پہلے ہی پانچ ٹوکنز خرچ کر چکا ہے، تو وہ صرف مزید پانچ خرچ کر سکے گا۔ وقت کے لحاظ سے، اس کے کام کرنے کے دو طریقے ہیں، اور دونوں صورتوں میں بل کو صرف دس ٹوکنز ہی ملیں گے:

A:

| ایلس کی ٹرانزیکشن | ایلس کا نانس | بل کی ٹرانزیکشن | بل کا نانس | بل کا الاؤنس | ایلس سے بل کی کل آمدنی |
| -------------------------- | ----------: | ---------------------------- | ---------: | ---------------: | ---------------------------- |
| approve(Bill, 5) | 10 | | | 5 | 0 |
| | | transferFrom(Alice, Bill, 5) | <span dir="ltr">10,123</span> | 0 | 5 |
| increaseAllowance(Bill, 5) | 11 | | | <span dir="ltr">0+5 = 5</span> | 5 |
| | | transferFrom(Alice, Bill, 5) | <span dir="ltr">10,124</span> | 0 | 10 |

B:

| ایلس کی ٹرانزیکشن | ایلس کا نانس | بل کی ٹرانزیکشن | بل کا نانس | بل کا الاؤنس | ایلس سے بل کی کل آمدنی |
| -------------------------- | ----------: | ----------------------------- | ---------: | ---------------: | ---------------------------: |
| approve(Bill, 5) | 10 | | | 5 | 0 |
| increaseAllowance(Bill, 5) | 11 | | | <span dir="ltr">5+5 = 10</span> | 0 |
| | | transferFrom(Alice, Bill, 10) | <span dir="ltr">10,124</span> | 0 | 10 |

```solidity
    /**
     * @dev کالر کی طرف سے `spender` کو دیے گئے الاؤنس میں ایٹمی طور پر اضافہ کرتا ہے۔
     *
     * یہ {approve} کا متبادل ہے جسے {IERC20-approve} میں بیان کردہ
     * مسائل کو کم کرنے کے لیے استعمال کیا جا سکتا ہے۔
     *
     * اپ ڈیٹ شدہ الاؤنس کی نشاندہی کرنے والا ایک {Approval} ایونٹ خارج کرتا ہے۔
     *
     * تقاضے:
     *
     * - `spender` صفر ایڈریس نہیں ہو سکتا۔
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }
```

`a.add(b)` فنکشن ایک محفوظ اضافہ (safe add) ہے۔ اس غیر امکانی صورت میں کہ `a`+`b`>=`2^256` ہو، یہ اس طرح ریپ اراؤنڈ (wrap around) نہیں کرتا جیسے عام اضافہ کرتا ہے۔

```solidity

    /**
     * @dev کالر کی طرف سے `spender` کو دیے گئے الاؤنس میں ایٹمی طور پر کمی کرتا ہے۔
     *
     * یہ {approve} کا متبادل ہے جسے {IERC20-approve} میں بیان کردہ
     * مسائل کو کم کرنے کے لیے استعمال کیا جا سکتا ہے۔
     *
     * اپ ڈیٹ شدہ الاؤنس کی نشاندہی کرنے والا ایک {Approval} ایونٹ خارج کرتا ہے۔
     *
     * تقاضے:
     *
     * - `spender` صفر ایڈریس نہیں ہو سکتا۔
     * - `spender` کے پاس کالر کے لیے کم از کم
     * `subtractedValue` کا الاؤنس ہونا چاہیے۔
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue,
                "ERC20: decreased allowance below zero"));
        return true;
    }
```

### ٹوکن کی معلومات میں ترمیم کرنے والے فنکشنز {#functions-that-modify-token-information}

یہ وہ چار فنکشنز ہیں جو اصل کام کرتے ہیں: `_transfer`، `_mint`، `_burn`، اور `_approve`۔

#### _transfer فنکشن {#transfer}

```solidity
    /**
     * @dev `sender` سے `recipient` کو `amount` ٹوکنز منتقل کرتا ہے۔
     *
     * یہ اندرونی فنکشن {transfer} کے مساوی ہے، اور اسے استعمال کیا جا سکتا ہے
     * مثال کے طور پر، خودکار ٹوکن فیس، سلیشنگ کے طریقہ کار وغیرہ کو نافذ کرنے کے لیے۔
     *
     * ایک {Transfer} ایونٹ خارج کرتا ہے۔
     *
     * تقاضے:
     *
     * - `sender` صفر ایڈریس نہیں ہو سکتا۔
     * - `recipient` صفر ایڈریس نہیں ہو سکتا۔
     * - `sender` کے پاس کم از کم `amount` کا بیلنس ہونا چاہیے۔
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
```

یہ فنکشن، `_transfer`، ایک اکاؤنٹ سے دوسرے اکاؤنٹ میں ٹوکنز منتقل کرتا ہے۔ اسے `transfer` (بھیجنے والے کے اپنے اکاؤنٹ سے منتقلی کے لیے) اور `transferFrom` (کسی اور کے اکاؤنٹ سے منتقل کرنے کے لیے الاؤنسز کا استعمال کرتے ہوئے) دونوں کے ذریعے کال کیا جاتا ہے۔

&nbsp;

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

ایتھیریم میں درحقیقت کوئی بھی صفر ایڈریس کا مالک نہیں ہے (یعنی، کوئی بھی ایسی نجی کلید نہیں جانتا جس کی مماثل عوامی کلید صفر ایڈریس میں تبدیل ہو جائے)۔ جب لوگ اس پتہ کا استعمال کرتے ہیں، تو یہ عام طور پر ایک سافٹ ویئر بگ ہوتا ہے - لہذا اگر صفر ایڈریس کو بھیجنے والے یا وصول کنندہ کے طور پر استعمال کیا جائے تو ہم اسے ناکام کر دیتے ہیں۔

&nbsp;

```solidity
        _beforeTokenTransfer(sender, recipient, amount);

```

اس کنٹریکٹ کو استعمال کرنے کے دو طریقے ہیں:

1. اسے اپنے کوڈ کے لیے ٹیمپلیٹ کے طور پر استعمال کریں
1. [اس سے وراثت لیں](https://www.bitdegree.org/learn/solidity-inheritance)، اور صرف ان فنکشنز کو اوور رائیڈ (override) کریں جن میں آپ کو ترمیم کرنے کی ضرورت ہے

دوسرا طریقہ بہت بہتر ہے کیونکہ اوپن زیپلن <span dir="ltr">ERC-20</span> کوڈ کا پہلے ہی آڈٹ کیا جا چکا ہے اور اسے محفوظ دکھایا گیا ہے۔ جب آپ وراثت کا استعمال کرتے ہیں تو یہ واضح ہوتا ہے کہ آپ کن فنکشنز میں ترمیم کرتے ہیں، اور آپ کے کنٹریکٹ پر بھروسہ کرنے کے لیے لوگوں کو صرف ان مخصوص فنکشنز کا آڈٹ کرنے کی ضرورت ہوتی ہے۔

ہر بار جب ٹوکنز ہاتھ بدلتے ہیں تو کوئی فنکشن انجام دینا اکثر مفید ہوتا ہے۔ تاہم، `_transfer` ایک بہت اہم فنکشن ہے اور اسے غیر محفوظ طریقے سے لکھنا ممکن ہے (نیچے دیکھیں)، لہذا بہتر ہے کہ اسے اوور رائیڈ نہ کیا جائے۔ اس کا حل `_beforeTokenTransfer` ہے، جو ایک [ہک فنکشن (hook function)](https://wikipedia.org/wiki/Hooking) ہے۔ آپ اس فنکشن کو اوور رائیڈ کر سکتے ہیں، اور اسے ہر منتقلی پر کال کیا جائے گا۔

&nbsp;

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

یہ وہ لائنیں ہیں جو دراصل منتقلی کرتی ہیں۔ نوٹ کریں کہ ان کے درمیان **کچھ نہیں** ہے، اور یہ کہ ہم وصول کنندہ میں شامل کرنے سے پہلے بھیجنے والے سے منتقل شدہ رقم کو گھٹا دیتے ہیں۔ یہ اہم ہے کیونکہ اگر درمیان میں کسی مختلف کنٹریکٹ کو کال کی جاتی، تو اسے اس کنٹریکٹ کو دھوکہ دینے کے لیے استعمال کیا جا سکتا تھا۔ اس طرح منتقلی ایٹمی (atomic) ہوتی ہے، اس کے درمیان کچھ نہیں ہو سکتا۔

&nbsp;

```solidity
        emit Transfer(sender, recipient, amount);
    }
```

آخر میں، ایک `Transfer` ایونٹ خارج کریں۔ ایونٹس سمارٹ کنٹریکٹس کے لیے قابل رسائی نہیں ہیں، لیکن بلاک چین کے باہر چلنے والا کوڈ ایونٹس کو سن سکتا ہے اور ان پر ردعمل ظاہر کر سکتا ہے۔ مثال کے طور پر، ایک والیٹ اس بات کا ریکارڈ رکھ سکتا ہے کہ مالک کو کب مزید ٹوکنز ملتے ہیں۔

#### _mint اور _burn فنکشنز {#mint-and-burn}

یہ دو فنکشنز (`_mint` اور `_burn`) ٹوکنز کی کل سپلائی میں ترمیم کرتے ہیں۔ یہ اندرونی ہیں اور اس کنٹریکٹ میں کوئی ایسا فنکشن نہیں ہے جو انہیں کال کرتا ہو، لہذا یہ صرف اس صورت میں مفید ہیں جب آپ کنٹریکٹ سے وراثت لیں اور اپنی منطق شامل کریں تاکہ یہ فیصلہ کیا جا سکے کہ کن حالات میں نئے ٹوکنز ڈھالنا ہیں یا موجودہ ٹوکنز کو جلانا ہے۔

**نوٹ:** ہر <span dir="ltr">ERC-20</span> ٹوکن کی اپنی کاروباری منطق ہوتی ہے جو ٹوکن کے انتظام کا تعین کرتی ہے۔ مثال کے طور پر، ایک مقررہ سپلائی والا کنٹریکٹ صرف کنسٹرکٹر میں `_mint` کو کال کر سکتا ہے اور کبھی بھی `_burn` کو کال نہیں کر سکتا۔ ایک کنٹریکٹ جو ٹوکنز بیچتا ہے وہ ادائیگی ہونے پر `_mint` کو کال کرے گا، اور ممکنہ طور پر بے قابو افراط زر سے بچنے کے لیے کسی موقع پر `_burn` کو کال کرے گا۔

```solidity
    /** @dev `amount` ٹوکنز بناتا ہے اور انہیں `account` کو تفویض کرتا ہے، جس سے
     * کل سپلائی میں اضافہ ہوتا ہے۔
     *
     * ایک {Transfer} ایونٹ خارج کرتا ہے جس میں `from` کو صفر ایڈریس پر سیٹ کیا گیا ہو۔
     *
     * تقاضے:
     *
     * - `to` صفر ایڈریس نہیں ہو سکتا۔
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");
        _beforeTokenTransfer(address(0), account, amount);
        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }
```

جب ٹوکنز کی کل تعداد تبدیل ہو تو `_totalSupply` کو اپ ڈیٹ کرنا یقینی بنائیں۔

&nbsp;

```solidity
    /**
     * @dev `account` سے `amount` ٹوکنز کو تباہ کرتا ہے، جس سے
     * کل سپلائی کم ہو جاتی ہے۔
     *
     * ایک {Transfer} ایونٹ خارج کرتا ہے جس میں `to` کو صفر ایڈریس پر سیٹ کیا گیا ہو۔
     *
     * تقاضے:
     *
     * - `account` صفر ایڈریس نہیں ہو سکتا۔
     * - `account` کے پاس کم از کم `amount` ٹوکنز ہونے چاہئیں۔
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }
```

`_burn` فنکشن تقریباً `_mint` جیسا ہی ہے، سوائے اس کے کہ یہ دوسری سمت میں جاتا ہے۔

#### _approve فنکشن {#approve-2}

یہ وہ فنکشن ہے جو دراصل الاؤنسز کی وضاحت کرتا ہے۔ نوٹ کریں کہ یہ مالک کو ایسا الاؤنس بتانے کی اجازت دیتا ہے جو مالک کے موجودہ بیلنس سے زیادہ ہو۔ یہ ٹھیک ہے کیونکہ بیلنس منتقلی کے وقت چیک کیا جاتا ہے، جب یہ اس بیلنس سے مختلف ہو سکتا ہے جو الاؤنس بناتے وقت تھا۔

```solidity
    /**
     * @dev `owner` کے ٹوکنز پر `spender` کے الاؤنس کے طور پر `amount` سیٹ کرتا ہے۔
     *
     * یہ اندرونی فنکشن `approve` کے مساوی ہے، اور اسے استعمال کیا جا سکتا ہے
     * مثال کے طور پر، کچھ ذیلی سسٹمز کے لیے خودکار الاؤنسز سیٹ کرنے کے لیے، وغیرہ۔
     *
     * ایک {Approval} ایونٹ خارج کرتا ہے۔
     *
     * تقاضے:
     *
     * - `owner` صفر ایڈریس نہیں ہو سکتا۔
     * - `spender` صفر ایڈریس نہیں ہو سکتا۔
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
```

&nbsp;

ایک `Approval` ایونٹ خارج کریں۔ ایپلی کیشن کے لکھے جانے کے طریقے پر منحصر ہے، خرچ کرنے والے کنٹریکٹ کو منظوری کے بارے میں یا تو مالک کے ذریعے بتایا جا سکتا ہے یا کسی ایسے سرور کے ذریعے جو ان ایونٹس کو سنتا ہے۔

```solidity
        emit Approval(owner, spender, amount);
    }

```

### Decimals متغیر میں ترمیم کریں {#modify-the-decimals-variable}

```solidity


    /**
     * @dev {decimals} کو 18 کی ڈیفالٹ ویلیو کے علاوہ کسی اور ویلیو پر سیٹ کرتا ہے۔
     *
     * انتباہ: اس فنکشن کو صرف کنسٹرکٹر سے کال کیا جانا چاہیے۔ زیادہ تر
     * ایپلی کیشنز جو ٹوکن کنٹریکٹس کے ساتھ تعامل کرتی ہیں وہ یہ توقع نہیں کریں گی کہ
     * {decimals} کبھی تبدیل ہوں گے، اور اگر ایسا ہوتا ہے تو وہ غلط طریقے سے کام کر سکتی ہیں۔
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }
```

یہ فنکشن `_decimals` متغیر میں ترمیم کرتا ہے جو یوزر انٹرفیسز کو یہ بتانے کے لیے استعمال ہوتا ہے کہ رقم کی تشریح کیسے کی جائے۔ آپ کو اسے کنسٹرکٹر سے کال کرنا چاہیے۔ اسے کسی بھی بعد کے موقع پر کال کرنا بے ایمانی ہوگی، اور ایپلی کیشنز کو اسے سنبھالنے کے لیے ڈیزائن نہیں کیا گیا ہے۔

### ہکس (Hooks) {#hooks}

```solidity

    /**
     * @dev ہک (Hook) جسے ٹوکنز کی کسی بھی منتقلی سے پہلے کال کیا جاتا ہے۔ اس میں
     * منٹنگ اور برننگ شامل ہیں۔
     *
     * کال کرنے کی شرائط:
     *
     * - جب `from` اور `to` دونوں غیر صفر ہوں، تو ``from`` کے `amount` ٹوکنز
     * `to` کو منتقل کیے جائیں گے۔
     * - جب `from` صفر ہو، تو `to` کے لیے `amount` ٹوکنز منٹ کیے جائیں گے۔
     * - جب `to` صفر ہو، تو ``from`` کے `amount` ٹوکنز برن کیے جائیں گے۔
     * - `from` اور `to` کبھی بھی دونوں صفر نہیں ہوتے۔
     *
     * ہکس کے بارے میں مزید جاننے کے لیے، xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks] پر جائیں۔
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
```

یہ وہ ہک فنکشن ہے جسے منتقلی کے دوران کال کیا جانا ہے۔ یہ یہاں خالی ہے، لیکن اگر آپ کو اس سے کچھ کروانے کی ضرورت ہے تو آپ بس اسے اوور رائیڈ کر دیں۔

## نتیجہ {#conclusion}

جائزہ لینے کے لیے، اس کنٹریکٹ میں کچھ اہم ترین خیالات یہ ہیں (میری رائے میں، آپ کی رائے مختلف ہو سکتی ہے):

- _بلاک چین پر کوئی راز نہیں ہوتے_۔ کوئی بھی معلومات جس تک سمارٹ کنٹریکٹ رسائی حاصل کر سکتا ہے وہ پوری دنیا کے لیے دستیاب ہے۔
- آپ اپنی ٹرانزیکشنز کی ترتیب کو کنٹرول کر سکتے ہیں، لیکن یہ نہیں کہ دوسرے لوگوں کی ٹرانزیکشنز کب ہوتی ہیں۔ یہی وجہ ہے کہ الاؤنس کو تبدیل کرنا خطرناک ہو سکتا ہے، کیونکہ یہ خرچ کرنے والے کو دونوں الاؤنسز کا مجموعہ خرچ کرنے دیتا ہے۔
- `uint256` قسم کی قدریں ریپ اراؤنڈ (wrap around) ہوتی ہیں۔ دوسرے الفاظ میں، <span dir="ltr">_0-1=2^256-1_</span>۔ اگر یہ مطلوبہ رویہ نہیں ہے، تو آپ کو اسے چیک کرنا ہوگا (یا SafeMath لائبریری استعمال کریں جو آپ کے لیے یہ کرتی ہے)۔ نوٹ کریں کہ یہ [Solidity 0.8.0](https://docs.soliditylang.org/en/breaking/080-breaking-changes.html) میں تبدیل ہو گیا ہے۔
- ایک مخصوص قسم کی تمام حالت کی تبدیلیاں ایک مخصوص جگہ پر کریں، کیونکہ اس سے آڈٹ کرنا آسان ہو جاتا ہے۔ یہی وجہ ہے کہ ہمارے پاس، مثال کے طور پر، `_approve` ہے، جسے `approve`، `transferFrom`، `increaseAllowance`، اور `decreaseAllowance` کے ذریعے کال کیا جاتا ہے۔
- حالت کی تبدیلیاں ایٹمی (atomic) ہونی چاہئیں، ان کے درمیان کسی اور کارروائی کے بغیر (جیسا کہ آپ `_transfer` میں دیکھ سکتے ہیں)۔ اس کی وجہ یہ ہے کہ حالت کی تبدیلی کے دوران آپ کے پاس ایک غیر مستقل حالت ہوتی ہے۔ مثال کے طور پر، اس وقت کے درمیان جب آپ بھیجنے والے کے بیلنس سے کٹوتی کرتے ہیں اور اس وقت کے درمیان جب آپ وصول کنندہ کے بیلنس میں اضافہ کرتے ہیں، وجود میں آنے والے ٹوکنز کی تعداد اس سے کم ہوتی ہے جتنی ہونی چاہیے۔ اگر ان کے درمیان کارروائیاں ہوں، خاص طور پر کسی مختلف کنٹریکٹ کو کالز، تو اس کا ممکنہ طور پر غلط استعمال کیا جا سکتا ہے۔

اب جب کہ آپ نے دیکھ لیا ہے کہ اوپن زیپلن <span dir="ltr">ERC-20</span> کنٹریکٹ کیسے لکھا جاتا ہے، اور خاص طور پر اسے کیسے زیادہ محفوظ بنایا جاتا ہے، تو جائیں اور اپنے محفوظ کنٹریکٹس اور ایپلی کیشنز لکھیں۔

[میرے مزید کام کے لیے یہاں دیکھیں](https://cryptodocguy.pro/)۔
