اہم مواد پر جائیں
Change page

اسمارٹ کنٹریکٹس کا تجزیہ

صفحہ کی آخری تازہ کاری: 23 فروری، 2026

اسمارٹ کنٹریکٹ ایک پروگرام ہے جو Ethereum پر ایک ایڈریس پر چلتا ہے۔ یہ ڈیٹا اور فنکشنز سے بنے ہوتے ہیں جو ٹرانزیکشن ملنے پر عمل میں آسکتے ہیں۔ اسمارٹ کنٹریکٹ کن چیزوں سے مل کر بنتا ہے اس کا ایک جائزہ یہاں پیش ہے۔

شرائط

پہلے یہ یقینی بنائیں کہ آپ نے اسمارٹ کنٹریکٹس کے بارے میں پڑھا ہے۔ یہ دستاویز یہ مان کر چلتی ہے کہ آپ پہلے ہی JavaScript یا Python جیسی پروگرامنگ زبانوں سے واقف ہیں۔

ڈیٹا

کسی بھی کنٹریکٹ ڈیٹا کو ایک مقام پر تفویض کیا جانا چاہیے: یا تو storage میں یا memory میں۔ اسمارٹ کنٹریکٹ میں اسٹوریج میں ترمیم کرنا مہنگا ہے لہذا آپ کو یہ غور کرنے کی ضرورت ہے کہ آپ کا ڈیٹا کہاں رہنا چاہیے۔

اسٹوریج

مستقل ڈیٹا کو اسٹوریج کہا جاتا ہے اور اسے اسٹیٹ متغیرات سے ظاہر کیا جاتا ہے۔ یہ قدریں بلاک چین پر مستقل طور پر محفوظ ہو جاتی ہیں۔ آپ کو ٹائپ کا اعلان کرنے کی ضرورت ہے تاکہ کنٹریکٹ یہ ٹریک رکھ سکے کہ اسے کمپائل کرتے وقت بلاک چین پر کتنے اسٹوریج کی ضرورت ہے۔

1// Solidity کی مثال
2contract SimpleStorage {
3 uint storedData; // اسٹیٹ متغیر
4 // ...
5}
1# Vyper کی مثال
2storedData: int128

اگر آپ پہلے ہی آبجیکٹ اورینٹڈ زبانوں میں پروگرامنگ کر چکے ہیں، تو آپ شاید زیادہ تر ٹائپس سے واقف ہوں گے۔ تاہم، اگر آپ Ethereum ڈیولپمنٹ میں نئے ہیں تو address آپ کے لیے نیا ہونا چاہیے۔

ایک address ٹائپ ایک Ethereum ایڈریس رکھ سکتا ہے جو 20 بائٹس یا 160 بٹس کے برابر ہے۔ یہ ایک سرکردہ 0x کے ساتھ ہیکسا ڈیسیمل نوٹیشن میں واپس آتا ہے۔

دیگر ٹائپس میں شامل ہیں:

  • بولین
  • انٹیجر
  • فکسڈ پوائنٹ نمبرز
  • فکسڈ سائز بائٹ ایریز
  • متحرک سائز کے بائٹ ایریز
  • ریشنل اور انٹیجر لٹرلز
  • سٹرنگ لٹرلز
  • ہیکسا ڈیسیمل لٹرلز
  • اینمز

مزید وضاحت کے لیے، دستاویزات پر ایک نظر ڈالیں:

میموری

وہ قدریں جو صرف کنٹریکٹ فنکشن کے عمل کی مدت کے لیے محفوظ کی جاتی ہیں، میموری متغیرات کہلاتی ہیں۔ چونکہ یہ بلاک چین پر مستقل طور پر محفوظ نہیں ہوتے ہیں، اس لیے ان کا استعمال بہت سستا ہوتا ہے۔

Solidity دستاویزات (opens in a new tab) میں EVM ڈیٹا (اسٹوریج، میموری، اور اسٹیک) کو کیسے اسٹور کرتا ہے اس کے بارے میں مزید جانیں۔

انوائرمنٹ متغیرات

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

مثالیں:

پراپاسٹیٹ متغیرتفصیل
block.timestampuint256موجودہ بلاک ایپوک ٹائم اسٹیمپ
msg.senderایڈریسپیغام بھیجنے والا (موجودہ کال)

فنکشنز

آسان ترین الفاظ میں، فنکشنز آنے والے ٹرانزیکشنز کے جواب میں معلومات حاصل کر سکتے ہیں یا معلومات سیٹ کر سکتے ہیں۔

فنکشن کالز کی دو اقسام ہیں:

  • internal – یہ EVM کال نہیں بناتے
    • اندرونی فنکشنز اور اسٹیٹ متغیرات تک صرف اندرونی طور پر رسائی حاصل کی جا سکتی ہے (یعنی موجودہ کنٹریکٹ کے اندر سے یا اس سے ماخوذ کنٹریکٹس سے)
  • external – یہ EVM کال بناتے ہیں
    • ایکسٹرنل فنکشنز کنٹریکٹ انٹرفیس کا حصہ ہیں، جس کا مطلب ہے کہ انہیں دوسرے کنٹریکٹس سے اور ٹرانزیکشنز کے ذریعے کال کیا جا سکتا ہے۔ ایک بیرونی فنکشن f کو اندرونی طور پر کال نہیں کیا جا سکتا (یعنی، f() کام نہیں کرتا، لیکن this.f() کام کرتا ہے)۔

وہ public یا private بھی ہو سکتے ہیں

  • public فنکشنز کو کنٹریکٹ کے اندر سے اندرونی طور پر یا پیغامات کے ذریعے بیرونی طور پر کال کیا جا سکتا ہے۔
  • private فنکشنز صرف اس کنٹریکٹ کے لیے نظر آتے ہیں جس میں ان کی تعریف کی گئی ہے اور ماخوذ کنٹریکٹس میں نہیں۔

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

یہاں ایک کنٹریکٹ پر اسٹیٹ متغیر کو اپ ڈیٹ کرنے کے لیے ایک فنکشن ہے:

1// Solidity کی مثال
2function update_name(string value) public {
3 dapp_name = value;
4}
  • string ٹائپ کا پیرامیٹر value فنکشن میں پاس کیا جاتا ہے: update_name
  • اسے public قرار دیا گیا ہے، یعنی کوئی بھی اس تک رسائی حاصل کر سکتا ہے
  • اسے view قرار نہیں دیا گیا ہے، اس لیے یہ کنٹریکٹ اسٹیٹ میں ترمیم کر سکتا ہے

ویو فنکشنز

یہ فنکشنز کنٹریکٹ کے ڈیٹا کی اسٹیٹ میں ترمیم نہ کرنے کا وعدہ کرتے ہیں۔ عام مثالیں "گیٹر" فنکشنز ہیں – آپ اسے مثال کے طور پر صارف کا بیلنس حاصل کرنے کے لیے استعمال کر سکتے ہیں۔

1// Solidity کی مثال
2function balanceOf(address _owner) public view returns (uint256 _balance) {
3 return ownerPizzaCount[_owner];
4}
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName

اسٹیٹ میں ترمیم کرنا کیا سمجھا جاتا ہے:

  1. اسٹیٹ متغیرات میں لکھنا۔
  2. ایونٹس کا اخراج (opens in a new tab)۔
  3. دوسرے کنٹریکٹس بنانا (opens in a new tab)۔
  4. selfdestruct کا استعمال۔
  5. کالز کے ذریعے ایتھر بھیجنا۔
  6. کسی بھی ایسے فنکشن کو کال کرنا جس پر view یا pure کا نشان نہ ہو۔
  7. نچلی سطح کی کالز کا استعمال۔
  8. ان لائن اسمبلی کا استعمال جس میں کچھ آپ کوڈز ہوں۔

کنسٹرکٹر فنکشنز

constructor فنکشنز صرف ایک بار عمل میں آتے ہیں جب کنٹریکٹ پہلی بار تعینات ہوتا ہے۔ بہت سی کلاس پر مبنی پروگرامنگ زبانوں میں constructor کی طرح، یہ فنکشنز اکثر اسٹیٹ متغیرات کو ان کی مخصوص قدروں پر شروع کرتے ہیں۔

1// Solidity کی مثال
2// کنٹریکٹ کے ڈیٹا کو شروع کرتا ہے، `owner` کو
3// کنٹریکٹ بنانے والے کے ایڈریس پر سیٹ کرتا ہے۔
4constructor() public {
5 // تمام اسمارٹ کنٹریکٹس اپنے فنکشنز کو ٹرگر کرنے کے لیے بیرونی ٹرانزیکشنز پر انحصار کرتے ہیں۔
6 // `msg` ایک عالمی متغیر ہے جس میں دیے گئے ٹرانزیکشن پر متعلقہ ڈیٹا شامل ہے،
7 // جیسے بھیجنے والے کا ایڈریس اور ٹرانزیکشن میں شامل ETH کی قدر۔
8 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
سب دکھائیں
1# Vyper کی مثال
2
3@external
4def __init__(_beneficiary: address, _bidding_time: uint256):
5 self.beneficiary = _beneficiary
6 self.auctionStart = block.timestamp
7 self.auctionEnd = self.auctionStart + _bidding_time

بلٹ ان فنکشنز

آپ کے کنٹریکٹ پر آپ کے ذریعے بیان کردہ متغیرات اور فنکشنز کے علاوہ، کچھ خاص بلٹ ان فنکشنز بھی ہیں۔ سب سے واضح مثال ہے:

  • address.send() – Solidity
  • send(address) – Vyper

یہ کنٹریکٹس کو دوسرے اکاؤنٹس میں ETH بھیجنے کی اجازت دیتے ہیں۔

فنکشنز لکھنا

آپ کے فنکشن کو ضرورت ہے:

  • پیرامیٹر متغیر اور ٹائپ (اگر یہ پیرامیٹرز قبول کرتا ہے)
  • اندرونی/بیرونی کا اعلان
  • pure/view/payable کا اعلان
  • ریٹرنز ٹائپ (اگر یہ قدر واپس کرتا ہے)
1pragma solidity >=0.4.0 <=0.6.0;
2
3contract ExampleDapp {
4 string dapp_name; // اسٹیٹ متغیر
5
6 // جب کنٹریکٹ تعینات ہوتا ہے تو کال کیا جاتا ہے اور قدر کو شروع کرتا ہے
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // فنکشن حاصل کریں
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // فنکشن سیٹ کریں
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
سب دکھائیں

ایک مکمل کنٹریکٹ کچھ اس طرح نظر آ سکتا ہے۔ یہاں constructor فنکشن dapp_name متغیر کے لیے ایک ابتدائی قدر فراہم کرتا ہے۔

ایونٹس اور لاگز

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

تشریح شدہ مثالیں

یہ Solidity میں لکھی گئی کچھ مثالیں ہیں۔ اگر آپ کوڈ کے ساتھ کھیلنا چاہتے ہیں، تو آپ Remix (opens in a new tab) میں ان کے ساتھ بات چیت کر سکتے ہیں۔

ہیلو ورلڈ

1// سیمنٹک ورژننگ کا استعمال کرتے ہوئے، Solidity کا ورژن بیان کرتا ہے۔
2// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// `HelloWorld` نامی ایک کنٹریکٹ کی تعریف کرتا ہے۔
6// ایک کنٹریکٹ فنکشنز اور ڈیٹا (اس کی اسٹیٹ) کا مجموعہ ہوتا ہے۔
7// ایک بار تعینات ہونے کے بعد، ایک کنٹریکٹ Ethereum بلاک چین پر ایک مخصوص ایڈریس پر رہتا ہے۔
8// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // `string` ٹائپ کا ایک اسٹیٹ متغیر `message` کا اعلان کرتا ہے۔
12 // اسٹیٹ متغیرات وہ متغیرات ہیں جن کی قدریں مستقل طور پر کنٹریکٹ اسٹوریج میں محفوظ کی جاتی ہیں۔
13 // کلیدی لفظ `public` متغیرات کو کنٹریکٹ کے باہر سے قابل رسائی بناتا ہے
14 // اور ایک ایسا فنکشن بناتا ہے جسے دوسرے کنٹریکٹس یا کلائنٹس قدر تک رسائی کے لیے کال کر سکتے ہیں۔
15 string public message;
16
17 // بہت سی کلاس پر مبنی آبجیکٹ اورینٹڈ زبانوں کی طرح، ایک کنسٹرکٹر
18 // ایک خاص فنکشن ہے جو صرف کنٹریکٹ کی تخلیق پر عمل میں آتا ہے۔
19 // کنسٹرکٹرز کنٹریکٹ کے ڈیٹا کو شروع کرنے کے لیے استعمال ہوتے ہیں۔
20 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // ایک سٹرنگ آرگومنٹ `initMessage` کو قبول کرتا ہے اور قدر کو
23 // کنٹریکٹ کے `message` اسٹوریج متغیر میں سیٹ کرتا ہے)۔
24 message = initMessage;
25 }
26
27 // ایک پبلک فنکشن جو ایک سٹرنگ آرگومنٹ قبول کرتا ہے
28 // اور `message` اسٹوریج متغیر کو اپ ڈیٹ کرتا ہے۔
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
سب دکھائیں

ٹوکن

1pragma solidity ^0.5.10;
2
3contract Token {
4 // ایک `address` ای میل ایڈریس کے مترادف ہے - یہ Ethereum پر ایک اکاؤنٹ کی شناخت کے لیے استعمال ہوتا ہے۔
5 // ایڈریس ایک اسمارٹ کنٹریکٹ یا بیرونی (صارف) اکاؤنٹس کی نمائندگی کر سکتے ہیں۔
6 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // ایک `mapping` بنیادی طور پر ایک ہیش ٹیبل ڈیٹا اسٹرکچر ہے۔
10 // یہ `mapping` ایک غیر دستخط شدہ انٹیجر (ٹوکن بیلنس) کو ایک ایڈریس (ٹوکن ہولڈر) کو تفویض کرتا ہے۔
11 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // ایونٹس بلاک چین پر سرگرمی کی لاگنگ کی اجازت دیتے ہیں۔
15 // Ethereum کلائنٹس کنٹریکٹ اسٹیٹ کی تبدیلیوں پر ردعمل ظاہر کرنے کے لیے ایونٹس سن سکتے ہیں۔
16 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // کنٹریکٹ کے ڈیٹا کو شروع کرتا ہے، `owner` کو
20 // کنٹریکٹ بنانے والے کے ایڈریس پر سیٹ کرتا ہے۔
21 constructor() public {
22 // تمام اسمارٹ کنٹریکٹس اپنے فنکشنز کو ٹرگر کرنے کے لیے بیرونی ٹرانزیکشنز پر انحصار کرتے ہیں۔
23 // `msg` ایک عالمی متغیر ہے جس میں دیے گئے ٹرانزیکشن پر متعلقہ ڈیٹا شامل ہے،
24 // جیسے بھیجنے والے کا ایڈریس اور ٹرانزیکشن میں شامل ETH کی قدر۔
25 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // نئے ٹوکنز کی ایک مقدار بناتا ہے اور انہیں ایک ایڈریس پر بھیجتا ہے۔
30 function mint(address receiver, uint amount) public {
31 // `require` ایک کنٹرول اسٹرکچر ہے جو کچھ شرائط کو نافذ کرنے کے لیے استعمال ہوتا ہے۔
32 // اگر ایک `require` بیان `false` کا اندازہ لگاتا ہے، تو ایک استثنا ٹرگر ہوتا ہے،
33 // جو موجودہ کال کے دوران اسٹیٹ میں کی گئی تمام تبدیلیوں کو واپس کر دیتا ہے۔
34 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // صرف کنٹریکٹ کا مالک ہی اس فنکشن کو کال کر سکتا ہے
37 require(msg.sender == owner, "You are not the owner.");
38
39 // ٹوکنز کی زیادہ سے زیادہ مقدار نافذ کرتا ہے
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // `receiver` کے بیلنس کو `amount` سے بڑھاتا ہے
43 balances[receiver] += amount;
44 }
45
46 // کسی بھی کال کرنے والے سے ایک ایڈریس پر موجودہ ٹوکنز کی ایک مقدار بھیجتا ہے۔
47 function transfer(address receiver, uint amount) public {
48 // بھیجنے والے کے پاس بھیجنے کے لیے کافی ٹوکنز ہونے چاہئیں
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // دو ایڈریس کے ٹوکن بیلنس کو ایڈجسٹ کرتا ہے
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // پہلے بیان کردہ ایونٹ کو خارج کرتا ہے
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
سب دکھائیں

منفرد ڈیجیٹل اثاثہ

1pragma solidity ^0.5.10;
2
3// دیگر فائلوں سے علامتوں کو موجودہ کنٹریکٹ میں درآمد کرتا ہے۔
4// اس معاملے میں، OpenZeppelin سے مددگار کنٹریکٹس کا ایک سلسلہ۔
5// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files
6
7import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";
8import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
9import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol";
10import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol";
11
12// `is` کلیدی لفظ بیرونی کنٹریکٹس سے فنکشنز اور کلیدی الفاظ کو وراثت میں لینے کے لیے استعمال ہوتا ہے۔
13// اس معاملے میں، `CryptoPizza` `IERC721` اور `ERC165` کنٹریکٹس سے وراثت میں لیتا ہے۔
14// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // حسابی کارروائیوں کو محفوظ طریقے سے انجام دینے کے لیے OpenZeppelin کی SafeMath لائبریری کا استعمال کرتا ہے۔
17 // مزید جانیں: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Solidity میں مستقل اسٹیٹ متغیرات دیگر زبانوں کی طرح ہیں
21 // لیکن آپ کو ایک ایسے اظہار سے تفویض کرنا چاہیے جو کمپائل وقت پر مستقل ہو۔
22 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables
23 uint256 constant dnaDigits = 10;
24 uint256 constant dnaModulus = 10 ** dnaDigits;
25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
26
27 // Struct ٹائپس آپ کو اپنی قسم کی تعریف کرنے دیتے ہیں
28 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Pizza structs کا ایک خالی سرنی بناتا ہے
35 Pizza[] public pizzas;
36
37 // پیزا آئی ڈی سے اس کے مالک کے ایڈریس تک میپنگ
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // مالک کے ایڈریس سے ملکیت والے ٹوکن کی تعداد تک میپنگ
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // ٹوکن آئی ڈی سے منظور شدہ ایڈریس تک میپنگ
44 mapping(uint256 => address) pizzaApprovals;
45
46 // آپ میپنگس کو نیسٹ کر سکتے ہیں، یہ مثال مالک کو آپریٹر کی منظوریوں سے میپ کرتی ہے
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // سٹرنگ (نام) اور DNA سے ایک بے ترتیب پیزا بنانے کے لیے اندرونی فنکشن
50 function _createPizza(string memory _name, uint256 _dna)
51 // `internal` کلیدی لفظ کا مطلب ہے کہ یہ فنکشن صرف
52 // اس کنٹریکٹ اور اس کنٹریکٹ سے ماخوذ کنٹریکٹس کے اندر نظر آتا ہے
53 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` ایک فنکشن موڈیفائر ہے جو یہ چیک کرتا ہے کہ آیا پیزا پہلے سے موجود ہے
56 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // پیزا کو پیزا کی سرنی میں شامل کرتا ہے اور آئی ڈی حاصل کرتا ہے
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // چیک کرتا ہے کہ پیزا کا مالک موجودہ صارف کے جیسا ہی ہے
63 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // نوٹ کریں کہ ایڈریس(0) صفر ایڈریس ہے،
66 // جو اس بات کی نشاندہی کرتا ہے کہ pizza[id] ابھی تک کسی خاص صارف کو مختص نہیں کیا گیا ہے۔
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // پیزا کو مالک سے میپ کرتا ہے
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // سٹرنگ (نام) سے ایک بے ترتیب پیزا بناتا ہے
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // سٹرنگ (نام) اور مالک (بنانے والے) کے ایڈریس سے بے ترتیب DNA بناتا ہے
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // `pure` کے طور پر نشان زد فنکشنز اسٹیٹ سے پڑھنے یا اس میں ترمیم نہ کرنے کا وعدہ کرتے ہیں
88 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // سٹرنگ (نام) + ایڈریس (مالک) سے بے ترتیب uint بناتا ہے
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // مالک کے ذریعہ پائے گئے پیزا کی سرنی واپس کرتا ہے
100 function getPizzasByOwner(address _owner)
101 public
102 // `view` کے طور پر نشان زد فنکشنز اسٹیٹ میں ترمیم نہ کرنے کا وعدہ کرتے ہیں
103 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // صرف اس فنکشن کال کے لائف سائیکل کے لیے قدروں کو اسٹور کرنے کے لیے `memory` اسٹوریج مقام کا استعمال کرتا ہے۔
108 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
109 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
110 uint256 counter = 0;
111 for (uint256 i = 0; i < pizzas.length; i++) {
112 if (pizzaToOwner[i] == _owner) {
113 result[counter] = i;
114 counter++;
115 }
116 }
117 return result;
118 }
119
120 // پیزا اور ملکیت دوسرے ایڈریس پر منتقل کرتا ہے
121 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
122 require(_from != address(0) && _to != address(0), "Invalid address.");
123 require(_exists(_pizzaId), "Pizza does not exist.");
124 require(_from != _to, "Cannot transfer to the same address.");
125 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
126
127 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
128 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
129 pizzaToOwner[_pizzaId] = _to;
130
131 // درآمد شدہ IERC721 کنٹریکٹ میں بیان کردہ ایونٹ کو خارج کرتا ہے
132 emit Transfer(_from, _to, _pizzaId);
133 _clearApproval(_to, _pizzaId);
134 }
135
136 /**
137 * دیے گئے ٹوکن آئی ڈی کی ملکیت کو محفوظ طریقے سے دوسرے ایڈریس پر منتقل کرتا ہے
138 * اگر ہدف ایڈریس ایک کنٹریکٹ ہے، تو اسے `onERC721Received` کو نافذ کرنا ہوگا،
139 * جسے ایک محفوظ منتقلی پر کال کیا جاتا ہے، اور جادوئی قدر واپس کرنا ہوگا
140 * `bytes4(keccak256(\"onERC721Received(address,address,uint256,bytes)\"))`؛
141 * بصورت دیگر، منتقلی واپس کر دی جاتی ہے۔
142 */
143 function safeTransferFrom(address from, address to, uint256 pizzaId)
144 public
145 {
146 // solium-disable-next-line arg-overflow
147 this.safeTransferFrom(from, to, pizzaId, "");
148 }
149
150 /**
151 * دیے گئے ٹوکن آئی ڈی کی ملکیت کو محفوظ طریقے سے دوسرے ایڈریس پر منتقل کرتا ہے
152 * اگر ہدف ایڈریس ایک کنٹریکٹ ہے، تو اسے `onERC721Received` کو نافذ کرنا ہوگا،
153 * جسے ایک محفوظ منتقلی پر کال کیا جاتا ہے، اور جادوئی قدر واپس کرنا ہوگا
154 * `bytes4(keccak256(\"onERC721Received(address,address,uint256,bytes)\"))`؛
155 * بصورت دیگر، منتقلی واپس کر دی جاتی ہے۔
156 */
157 function safeTransferFrom(
158 address from,
159 address to,
160 uint256 pizzaId,
161 bytes memory _data
162 ) public {
163 this.transferFrom(from, to, pizzaId);
164 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");
165 }
166
167 /**
168 * ہدف ایڈریس پر `onERC721Received` کو کال کرنے کے لیے اندرونی فنکشن
169 * کال اس وقت عمل میں نہیں آتی جب ہدف ایڈریس ایک کنٹریکٹ نہ ہو
170 */
171 function _checkOnERC721Received(
172 address from,
173 address to,
174 uint256 pizzaId,
175 bytes memory _data
176 ) internal returns (bool) {
177 if (!isContract(to)) {
178 return true;
179 }
180
181 bytes4 retval = IERC721Receiver(to).onERC721Received(
182 msg.sender,
183 from,
184 pizzaId,
185 _data
186 );
187 return (retval == _ERC721_RECEIVED);
188 }
189
190 // ایک پیزا کو جلاتا ہے - ٹوکن کو مکمل طور پر تباہ کرتا ہے
191 // `external` فنکشن موڈیفائر کا مطلب ہے کہ یہ فنکشن
192 // کنٹریکٹ انٹرفیس کا حصہ ہے اور دوسرے کنٹریکٹس اسے کال کر سکتے ہیں
193 function burn(uint256 _pizzaId) external {
194 require(msg.sender != address(0), "Invalid address.");
195 require(_exists(_pizzaId), "Pizza does not exist.");
196 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
197
198 ownerPizzaCount[msg.sender] = SafeMath.sub(
199 ownerPizzaCount[msg.sender],
200 1
201 );
202 pizzaToOwner[_pizzaId] = address(0);
203 }
204
205 // ایڈریس کے لحاظ سے پیزا کی تعداد واپس کرتا ہے
206 function balanceOf(address _owner) public view returns (uint256 _balance) {
207 return ownerPizzaCount[_owner];
208 }
209
210 // آئی ڈی کے ذریعہ پائے گئے پیزا کا مالک واپس کرتا ہے
211 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
212 address owner = pizzaToOwner[_pizzaId];
213 require(owner != address(0), "Invalid Pizza ID.");
214 return owner;
215 }
216
217 // پیزا کی ملکیت منتقل کرنے کے لیے دوسرے ایڈریس کو منظور کرتا ہے
218 function approve(address _to, uint256 _pizzaId) public {
219 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");
220 pizzaApprovals[_pizzaId] = _to;
221 emit Approval(msg.sender, _to, _pizzaId);
222 }
223
224 // مخصوص پیزا کے لیے منظور شدہ ایڈریس واپس کرتا ہے
225 function getApproved(uint256 _pizzaId)
226 public
227 view
228 returns (address operator)
229 {
230 require(_exists(_pizzaId), "Pizza does not exist.");
231 return pizzaApprovals[_pizzaId];
232 }
233
234 /**
235 * دیے گئے ٹوکن آئی ڈی کی موجودہ منظوری کو صاف کرنے کے لیے نجی فنکشن
236 * اگر دیا گیا ایڈریس واقعی ٹوکن کا مالک نہیں ہے تو واپس کرتا ہے
237 */
238 function _clearApproval(address owner, uint256 _pizzaId) private {
239 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");
240 require(_exists(_pizzaId), "Pizza does not exist.");
241 if (pizzaApprovals[_pizzaId] != address(0)) {
242 pizzaApprovals[_pizzaId] = address(0);
243 }
244 }
245
246 /*
247 * دیے گئے آپریٹر کی منظوری کو سیٹ یا ان سیٹ کرتا ہے
248 * ایک آپریٹر کو ان کی طرف سے بھیجنے والے کے تمام ٹوکنز منتقل کرنے کی اجازت ہے
249 */
250 function setApprovalForAll(address to, bool approved) public {
251 require(to != msg.sender, "Cannot approve own address");
252 operatorApprovals[msg.sender][to] = approved;
253 emit ApprovalForAll(msg.sender, to, approved);
254 }
255
256 // بتاتا ہے کہ آیا کوئی آپریٹر دیے گئے مالک کے ذریعہ منظور شدہ ہے
257 function isApprovedForAll(address owner, address operator)
258 public
259 view
260 returns (bool)
261 {
262 return operatorApprovals[owner][operator];
263 }
264
265 // پیزا کی ملکیت لیتا ہے - صرف منظور شدہ صارفین کے لیے
266 function takeOwnership(uint256 _pizzaId) public {
267 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
268 address owner = this.ownerOf(_pizzaId);
269 this.transferFrom(owner, msg.sender, _pizzaId);
270 }
271
272 // چیک کرتا ہے کہ آیا پیزا موجود ہے
273 function _exists(uint256 pizzaId) internal view returns (bool) {
274 address owner = pizzaToOwner[pizzaId];
275 return owner != address(0);
276 }
277
278 // چیک کرتا ہے کہ آیا ایڈریس مالک ہے یا پیزا منتقل کرنے کے لیے منظور شدہ ہے
279 function _isApprovedOrOwner(address spender, uint256 pizzaId)
280 internal
281 view
282 returns (bool)
283 {
284 address owner = pizzaToOwner[pizzaId];
285 // Disable solium check because of
286 // https://github.com/duaraghav8/Solium/issues/175
287 // solium-disable-next-line operator-whitespace
288 return (spender == owner ||
289 this.getApproved(pizzaId) == spender ||
290 this.isApprovedForAll(owner, spender));
291 }
292
293 // چیک کریں کہ آیا پیزا منفرد ہے اور ابھی تک موجود نہیں ہے
294 modifier isUnique(string memory _name, uint256 _dna) {
295 bool result = true;
296 for (uint256 i = 0; i < pizzas.length; i++) {
297 if (
298 keccak256(abi.encodePacked(pizzas[i].name)) ==
299 keccak256(abi.encodePacked(_name)) &&
300 pizzas[i].dna == _dna
301 ) {
302 result = false;
303 }
304 }
305 require(result, "Pizza with such name already exists.");
306 _;
307 }
308
309 // واپس کرتا ہے کہ آیا ہدف ایڈریس ایک کنٹریکٹ ہے
310 function isContract(address account) internal view returns (bool) {
311 uint256 size;
312 // فی الحال کسی ایڈریس میں کنٹریکٹ ہے یا نہیں یہ چیک کرنے کا اس سے بہتر کوئی طریقہ نہیں ہے
313 // کہ اس ایڈریس پر کوڈ کا سائز چیک کیا جائے۔
314 // یہ کیسے کام کرتا ہے اس کے بارے میں مزید تفصیلات کے لیے https://ethereum.stackexchange.com/a/14016/36603
315 // دیکھیں۔
316 // TODO Serenity ریلیز سے پہلے اسے دوبارہ چیک کریں، کیونکہ تمام ایڈریس
317 // تب کنٹریکٹ ہوں گے۔
318 // solium-disable-next-line security/no-inline-assembly
319 assembly {
320 size := extcodesize(account)
321 }
322 return size > 0;
323 }
324}
سب دکھائیں

مزید پڑھیں

اسمارٹ کنٹریکٹس کے مزید مکمل جائزہ کے لیے Solidity اور Vyper کی دستاویزات دیکھیں۔

کیا یہ آرٹیکل کارآمد تھا؟