اسمارٹ کانٹریکٹس کی ساخت
صفحہ کی آخری اپ ڈیٹ: 23 فروری، 2026
اسمارٹ کانٹریکٹ ایک پروگرام ہے جو ایتھیریم پر ایک ایڈریس پر چلتا ہے۔ یہ ڈیٹا اور فنکشنز پر مشتمل ہوتے ہیں جو ٹرانزیکشن موصول ہونے پر عمل میں آ سکتے ہیں۔ یہاں اسمارٹ کانٹریکٹ کے اجزاء کا ایک جائزہ دیا گیا ہے۔
بنیادی شرائط
یقینی بنائیں کہ آپ نے پہلے اسمارٹ کانٹریکٹس کے بارے میں پڑھ لیا ہے۔ یہ دستاویز فرض کرتی ہے کہ آپ پہلے ہی JavaScript یا Python جیسی پروگرامنگ زبانوں سے واقف ہیں۔
ڈیٹا
کسی بھی کانٹریکٹ کے ڈیٹا کو ایک مقام تفویض کیا جانا چاہیے: یا تو storage یا memory۔ اسمارٹ کانٹریکٹ میں اسٹوریج کو تبدیل کرنا مہنگا ہوتا ہے، اس لیے آپ کو غور کرنا چاہیے کہ آپ کا ڈیٹا کہاں رہنا چاہیے۔
اسٹوریج
مستقل ڈیٹا کو اسٹوریج کہا جاتا ہے اور اسے اسٹیٹ ویری ایبلز کے ذریعے ظاہر کیا جاتا ہے۔ یہ قدریں بلاک چین پر مستقل طور پر محفوظ ہو جاتی ہیں۔ آپ کو اس کی قسم (type) کا اعلان کرنے کی ضرورت ہوتی ہے تاکہ کانٹریکٹ مرتب (compile) ہوتے وقت یہ حساب رکھ سکے کہ اسے بلاک چین پر کتنی اسٹوریج درکار ہے۔
1// Solidity کی مثال2contract SimpleStorage {3 uint storedData; // اسٹیٹ ویری ایبل4 // ...5}1# Vyper کی مثال2storedData: int128اگر آپ نے پہلے ہی آبجیکٹ اورینٹڈ زبانوں میں پروگرامنگ کی ہے، تو آپ ممکنہ طور پر زیادہ تر اقسام سے واقف ہوں گے۔ تاہم، اگر آپ Ethereum ڈیولپمنٹ میں نئے ہیں تو address آپ کے لیے نیا ہونا چاہیے۔
ایک address ٹائپ ایتھیریم ایڈریس کو محفوظ کر سکتی ہے جو 20 بائٹس یا 160 بٹس کے برابر ہوتا ہے۔ یہ ہیکسا ڈیسیمل (hexadecimal) شکل میں واپس آتا ہے جس کے شروع میں 0x ہوتا ہے۔
دیگر اقسام میں شامل ہیں:
- boolean
- integer
- fixed point numbers
- fixed-size byte arrays
- dynamically sized byte arrays
- rational and integer literals
- string literals
- hexadecimal literals
- enums
مزید وضاحت کے لیے، دستاویزات دیکھیں:
میموری
وہ قدریں جو صرف کانٹریکٹ فنکشن کے چلنے کی مدت تک محفوظ رہتی ہیں، میموری ویری ایبلز کہلاتی ہیں۔ چونکہ یہ بلاک چین پر مستقل طور پر محفوظ نہیں ہوتیں، اس لیے ان کا استعمال بہت سستا ہوتا ہے۔
EVM ڈیٹا کو کیسے محفوظ کرتا ہے (اسٹوریج، میموری، اور اسٹیک) اس بارے میں مزید جاننے کے لیے Solidity کی دستاویزات (opens in a new tab) دیکھیں۔
انوائرنمنٹ ویری ایبلز
آپ کے کانٹریکٹ میں بیان کردہ ویری ایبلز کے علاوہ، کچھ خاص گلوبل ویری ایبلز بھی ہوتے ہیں۔ یہ بنیادی طور پر بلاک چین یا موجودہ ٹرانزیکشن کے بارے میں معلومات فراہم کرنے کے لیے استعمال ہوتے ہیں۔
مثالیں:
| پراپرٹی | اسٹیٹ ویری ایبل | تفصیل |
|---|---|---|
block.timestamp | uint256 | موجودہ بلاک کا ایپوک ٹائم اسٹیمپ |
msg.sender | address | پیغام بھیجنے والا (موجودہ کال) |
فنکشنز
آسان ترین الفاظ میں، فنکشنز آنے والی ٹرانزیکشنز کے جواب میں معلومات حاصل کر سکتے ہیں یا معلومات سیٹ کر سکتے ہیں۔
فنکشن کالز کی دو اقسام ہیں:
internal– یہ EVM کال نہیں بناتے- انٹرنل فنکشنز اور اسٹیٹ ویری ایبلز تک صرف اندرونی طور پر رسائی حاصل کی جا سکتی ہے (یعنی موجودہ کانٹریکٹ یا اس سے اخذ کردہ کانٹریکٹس کے اندر سے)
external– یہ EVM کال بناتے ہیں- ایکسٹرنل فنکشنز کانٹریکٹ انٹرفیس کا حصہ ہوتے ہیں، جس کا مطلب ہے کہ انہیں دوسرے کانٹریکٹس سے اور ٹرانزیکشنز کے ذریعے کال کیا جا سکتا ہے۔ ایک ایکسٹرنل فنکشن
fکو اندرونی طور پر کال نہیں کیا جا سکتا (یعنیf()کام نہیں کرتا، لیکنthis.f()کام کرتا ہے)۔
- ایکسٹرنل فنکشنز کانٹریکٹ انٹرفیس کا حصہ ہوتے ہیں، جس کا مطلب ہے کہ انہیں دوسرے کانٹریکٹس سے اور ٹرانزیکشنز کے ذریعے کال کیا جا سکتا ہے۔ ایک ایکسٹرنل فنکشن
یہ public یا private بھی ہو سکتے ہیں
publicفنکشنز کو کانٹریکٹ کے اندر سے اندرونی طور پر یا پیغامات کے ذریعے بیرونی طور پر کال کیا جا سکتا ہےprivateفنکشنز صرف اسی کانٹریکٹ کے لیے نظر آتے ہیں جس میں ان کی تعریف کی گئی ہو اور اخذ کردہ (derived) کانٹریکٹس میں نہیں
فنکشنز اور اسٹیٹ ویری ایبلز دونوں کو پبلک یا پرائیویٹ بنایا جا سکتا ہے
یہاں کانٹریکٹ پر اسٹیٹ ویری ایبل کو اپ ڈیٹ کرنے کے لیے ایک فنکشن دیا گیا ہے:
1// Solidity کی مثال2function update_name(string value) public {3 dapp_name = value;4}stringٹائپ کا پیرامیٹرvalueفنکشن میں پاس کیا جاتا ہے:update_name- اسے
publicقرار دیا گیا ہے، جس کا مطلب ہے کہ کوئی بھی اس تک رسائی حاصل کر سکتا ہے - اسے
viewقرار نہیں دیا گیا، اس لیے یہ کانٹریکٹ کی اسٹیٹ کو تبدیل کر سکتا ہے
ویو فنکشنز (View functions)
یہ فنکشنز کانٹریکٹ کے ڈیٹا کی اسٹیٹ کو تبدیل نہ کرنے کا وعدہ کرتے ہیں۔ عام مثالیں "getter" فنکشنز ہیں – مثال کے طور پر آپ اسے صارف کا بیلنس حاصل کرنے کے لیے استعمال کر سکتے ہیں۔
1// Solidity کی مثال2function balanceOf(address _owner) public view returns (uint256 _balance) {3 return ownerPizzaCount[_owner];4}1dappName: public(string)23@view4@public5def readName() -> string:6 return dappNameاسٹیٹ کو تبدیل کرنا کیا سمجھا جاتا ہے:
- اسٹیٹ ویری ایبلز میں لکھنا۔
- ایونٹس کا اخراج (Emitting events) (opens in a new tab)۔
- دوسرے کانٹریکٹس بنانا (opens in a new tab)۔
selfdestructکا استعمال۔- کالز کے ذریعے ایتھر (ether) بھیجنا۔
- کسی ایسے فنکشن کو کال کرنا جس پر
viewیاpureکا نشان نہ ہو۔ - لو-لیول (low-level) کالز کا استعمال۔
- ان لائن اسمبلی (inline assembly) کا استعمال جس میں مخصوص اوپ کوڈز (opcodes) شامل ہوں۔
کنسٹرکٹر فنکشنز (Constructor functions)
constructor فنکشنز صرف ایک بار چلتے ہیں جب کانٹریکٹ پہلی بار ڈیپلائے (deploy) ہوتا ہے۔ بہت سی کلاس پر مبنی پروگرامنگ زبانوں میں constructor کی طرح، یہ فنکشنز اکثر اسٹیٹ ویری ایبلز کو ان کی مخصوص قدروں کے ساتھ شروع (initialize) کرتے ہیں۔
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-properties9 owner = msg.sender;10}سب دکھائیں1# Vyper کی مثال23@external4def __init__(_beneficiary: address, _bidding_time: uint256):5 self.beneficiary = _beneficiary6 self.auctionStart = block.timestamp7 self.auctionEnd = self.auctionStart + _bidding_timeبلٹ ان فنکشنز (Built-in functions)
آپ کے کانٹریکٹ میں بیان کردہ ویری ایبلز اور فنکشنز کے علاوہ، کچھ خاص بلٹ ان فنکشنز بھی ہوتے ہیں۔ سب سے واضح مثال یہ ہے:
address.send()– Soliditysend(address)– Vyper
یہ کانٹریکٹس کو دوسرے اکاؤنٹس میں ETH بھیجنے کی اجازت دیتے ہیں۔
فنکشنز لکھنا
آپ کے فنکشن کو درج ذیل کی ضرورت ہوتی ہے:
- پیرامیٹر ویری ایبل اور ٹائپ (اگر یہ پیرامیٹرز قبول کرتا ہے)
- internal/external کا اعلان
- pure/view/payable کا اعلان
- ریٹرنز ٹائپ (اگر یہ کوئی قدر واپس کرتا ہے)
1pragma solidity >=0.4.0 <=0.6.0;23contract ExampleDapp {4 string dapp_name; // اسٹیٹ ویری ایبل56 // جب کانٹریکٹ ڈیپلائے ہوتا ہے تو اسے کال کیا جاتا ہے اور یہ ویلیو کو انیشلائز کرتا ہے7 constructor() public {8 dapp_name = "My Example dapp";9 }1011 // Get فنکشن12 function read_name() public view returns(string) {13 return dapp_name;14 }1516 // Set فنکشن17 function update_name(string value) public {18 dapp_name = value;19 }20}سب دکھائیںایک مکمل کانٹریکٹ کچھ اس طرح کا نظر آ سکتا ہے۔ یہاں constructor فنکشن dapp_name ویری ایبل کے لیے ابتدائی قدر فراہم کرتا ہے۔
ایونٹس اور لاگز
ایونٹس آپ کے اسمارٹ کانٹریکٹ کو آپ کے فرنٹ اینڈ یا دیگر سبسکرائب کرنے والی ایپلیکیشنز کے ساتھ بات چیت کرنے کے قابل بناتے ہیں۔ ایک بار جب ٹرانزیکشن کی توثیق ہو جاتی ہے اور اسے بلاک میں شامل کر دیا جاتا ہے، تو اسمارٹ کانٹریکٹس ایونٹس خارج کر سکتے ہیں اور معلومات لاگ کر سکتے ہیں، جنہیں پھر فرنٹ اینڈ پروسیس اور استعمال کر سکتا ہے۔
تشریح شدہ مثالیں
یہ Solidity میں لکھی گئی کچھ مثالیں ہیں۔ اگر آپ کوڈ کے ساتھ تجربہ کرنا چاہتے ہیں، تو آپ Remix (opens in a new tab) میں ان کے ساتھ تعامل کر سکتے ہیں۔
Hello world
1// سیمینٹک ورژننگ کا استعمال کرتے ہوئے، Solidity کا ورژن متعین کرتا ہے۔2// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity ^0.5.10;45// `HelloWorld` نامی کانٹریکٹ کی وضاحت کرتا ہے۔6// کانٹریکٹ فنکشنز اور ڈیٹا (اس کی اسٹیٹ) کا مجموعہ ہوتا ہے۔7// ایک بار ڈیپلائے ہونے کے بعد، کانٹریکٹ ایتھیریم بلاک چین پر ایک مخصوص ایڈریس پر موجود ہوتا ہے۔8// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {1011 // `string` ٹائپ کا ایک اسٹیٹ ویری ایبل `message` ڈکلیئر کرتا ہے۔12 // اسٹیٹ ویری ایبلز وہ ویری ایبلز ہوتے ہیں جن کی ویلیوز کانٹریکٹ کی اسٹوریج میں مستقل طور پر محفوظ ہوتی ہیں۔13 // `public` کی ورڈ ویری ایبلز کو کانٹریکٹ کے باہر سے قابل رسائی بناتا ہے14 // اور ایک ایسا فنکشن بناتا ہے جسے دوسرے کانٹریکٹس یا کلائنٹس ویلیو تک رسائی کے لیے کال کر سکتے ہیں۔15 string public message;1617 // بہت سی کلاس پر مبنی آبجیکٹ اورینٹڈ زبانوں کی طرح، کنسٹرکٹر ایک18 // خاص فنکشن ہوتا ہے جو صرف کانٹریکٹ بننے پر ہی ایگزیکیوٹ ہوتا ہے۔19 // کنسٹرکٹرز کانٹریکٹ کے ڈیٹا کو انیشلائز کرنے کے لیے استعمال ہوتے ہیں۔20 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) public {22 // ایک سٹرنگ آرگیومنٹ `initMessage` قبول کرتا ہے اور ویلیو کو23 // کانٹریکٹ کے `message` اسٹوریج ویری ایبل میں سیٹ کرتا ہے)۔24 message = initMessage;25 }2627 // ایک پبلک فنکشن جو سٹرنگ آرگیومنٹ قبول کرتا ہے28 // اور `message` اسٹوریج ویری ایبل کو اپ ڈیٹ کرتا ہے۔29 function update(string memory newMessage) public {30 message = newMessage;31 }32}سب دکھائیںToken
1pragma solidity ^0.5.10;23contract Token {4 // ایک `address` ای میل ایڈریس کے مترادف ہے - یہ ایتھیریم پر اکاؤنٹ کی شناخت کے لیے استعمال ہوتا ہے۔5 // ایڈریسز کسی سمارٹ کانٹریکٹ یا بیرونی (صارف) اکاؤنٹس کی نمائندگی کر سکتے ہیں۔6 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#address7 address public owner;89 // ایک `mapping` بنیادی طور پر ایک ہیش ٹیبل ڈیٹا سٹرکچر ہے۔10 // یہ `mapping` ایک ان سائنڈ انٹیجر (ٹوکن بیلنس) کو ایک ایڈریس (ٹوکن ہولڈر) کے ساتھ تفویض کرتی ہے۔11 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types12 mapping (address => uint) public balances;1314 // ایونٹس بلاک چین پر سرگرمیوں کی لاگنگ کی اجازت دیتے ہیں۔15 // ایتھیریم کلائنٹس کانٹریکٹ کی اسٹیٹ میں تبدیلیوں پر ردعمل ظاہر کرنے کے لیے ایونٹس کو سن سکتے ہیں۔16 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events17 event Transfer(address from, address to, uint amount);1819 // کانٹریکٹ کا ڈیٹا انیشلائز کرتا ہے، `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-properties26 owner = msg.sender;27 }2829 // نئے ٹوکنز کی ایک مقدار بناتا ہے اور انہیں ایک ایڈریس پر بھیجتا ہے۔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-exceptions3536 // صرف کانٹریکٹ کا مالک ہی اس فنکشن کو کال کر سکتا ہے37 require(msg.sender == owner, "You are not the owner.");3839 // ٹوکنز کی زیادہ سے زیادہ مقدار کو نافذ کرتا ہے40 require(amount < 1e60, "Maximum issuance exceeded");4142 // `receiver` کے بیلنس میں `amount` کا اضافہ کرتا ہے43 balances[receiver] += amount;44 }4546 // کسی بھی کالر سے موجودہ ٹوکنز کی ایک مقدار کسی ایڈریس پر بھیجتا ہے۔47 function transfer(address receiver, uint amount) public {48 // بھیجنے والے کے پاس بھیجنے کے لیے کافی ٹوکنز ہونے چاہئیں49 require(amount <= balances[msg.sender], "Insufficient balance.");5051 // دونوں ایڈریسز کے ٹوکن بیلنس کو ایڈجسٹ کرتا ہے52 balances[msg.sender] -= amount;53 balances[receiver] += amount;5455 // پہلے سے بیان کردہ ایونٹ کو ایمٹ (emit) کرتا ہے56 emit Transfer(msg.sender, receiver, amount);57 }58}سب دکھائیںUnique digital asset
1pragma solidity ^0.5.10;23// دوسری فائلوں سے سمبلز کو موجودہ کانٹریکٹ میں امپورٹ کرتا ہے۔4// اس صورت میں، OpenZeppelin سے ہیلپر کانٹریکٹس کا ایک سلسلہ۔5// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files67import "../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";1112// `is` کی ورڈ بیرونی کانٹریکٹس سے فنکشنز اور کی ورڈز کو وراثت (inherit) میں لینے کے لیے استعمال ہوتا ہے۔13// اس صورت میں، `CryptoPizza` کو `IERC721` اور `ERC165` کانٹریکٹس سے وراثت ملتی ہے۔14// مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance15contract CryptoPizza is IERC721, ERC165 {16 // ریاضی کے آپریشنز کو محفوظ طریقے سے انجام دینے کے لیے OpenZeppelin کی SafeMath لائبریری کا استعمال کرتا ہے۔17 // مزید جانیں: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath18 using SafeMath for uint256;1920 // Solidity میں کانسٹنٹ اسٹیٹ ویری ایبلز دوسری زبانوں کی طرح ہی ہوتے ہیں21 // لیکن آپ کو ایک ایسے ایکسپریشن سے تفویض کرنا ہوگا جو کمپائل ٹائم پر کانسٹنٹ ہو۔22 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables23 uint256 constant dnaDigits = 10;24 uint256 constant dnaModulus = 10 ** dnaDigits;25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;2627 // Struct ٹائپس آپ کو اپنی ٹائپ خود بیان کرنے کی اجازت دیتی ہیں28 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs29 struct Pizza {30 string name;31 uint256 dna;32 }3334 // Pizza اسٹرکٹس کی ایک خالی ایرے (array) بناتا ہے35 Pizza[] public pizzas;3637 // پیزا ID سے اس کے مالک کے ایڈریس تک میپنگ38 mapping(uint256 => address) public pizzaToOwner;3940 // مالک کے ایڈریس سے ملکیتی ٹوکنز کی تعداد تک میپنگ41 mapping(address => uint256) public ownerPizzaCount;4243 // ٹوکن ID سے منظور شدہ ایڈریس تک میپنگ44 mapping(uint256 => address) pizzaApprovals;4546 // آپ میپنگز کو نیسٹ (nest) کر سکتے ہیں، یہ مثال مالک کو آپریٹر کی منظوریوں سے میپ کرتی ہے47 mapping(address => mapping(address => bool)) private operatorApprovals;4849 // سٹرنگ (نام) اور DNA سے ایک رینڈم پیزا بنانے کے لیے انٹرنل فنکشن50 function _createPizza(string memory _name, uint256 _dna)51 // `internal` کی ورڈ کا مطلب ہے کہ یہ فنکشن صرف نظر آتا ہے52 // اس کانٹریکٹ اور ان کانٹریکٹس کے اندر جو اس کانٹریکٹ سے اخذ (derive) کیے گئے ہیں53 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters54 internal55 // `isUnique` ایک فنکشن موڈیفائر ہے جو چیک کرتا ہے کہ آیا پیزا پہلے سے موجود ہے56 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers57 isUnique(_name, _dna)58 {59 // پیزا کو پیزا کی ایرے میں شامل کرتا ہے اور id حاصل کرتا ہے60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);6162 // چیک کرتا ہے کہ پیزا کا مالک وہی ہے جو موجودہ صارف ہے63 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions6465 // نوٹ کریں کہ address(0) زیرو ایڈریس ہے،66 // جو ظاہر کرتا ہے کہ pizza[id] ابھی تک کسی خاص صارف کو الاٹ نہیں کیا گیا ہے۔6768 assert(pizzaToOwner[id] == address(0));6970 // پیزا کو مالک سے میپ کرتا ہے71 pizzaToOwner[id] = msg.sender;72 ownerPizzaCount[msg.sender] = SafeMath.add(73 ownerPizzaCount[msg.sender],74 175 );76 }7778 // سٹرنگ (نام) سے ایک رینڈم پیزا بناتا ہے79 function createRandomPizza(string memory _name) public {80 uint256 randDna = generateRandomDna(_name, msg.sender);81 _createPizza(_name, randDna);82 }8384 // سٹرنگ (نام) اور مالک (بنانے والے) کے ایڈریس سے رینڈم DNA تیار کرتا ہے85 function generateRandomDna(string memory _str, address _owner)86 public87 // `pure` کے طور پر مارک کیے گئے فنکشنز اسٹیٹ کو نہ پڑھنے اور نہ ہی تبدیل کرنے کا وعدہ کرتے ہیں88 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions89 pure90 returns (uint256)91 {92 // سٹرنگ (نام) + ایڈریس (مالک) سے رینڈم uint تیار کرتا ہے93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +94 uint256(_owner);95 rand = rand % dnaModulus;96 return rand;97 }9899 // مالک کے پائے گئے پیزا کی ایرے واپس کرتا ہے100 function getPizzasByOwner(address _owner)101 public102 // `view` کے طور پر مارک کیے گئے فنکشنز اسٹیٹ کو تبدیل نہ کرنے کا وعدہ کرتے ہیں103 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions104 view105 returns (uint256[] memory)106 {107 // `memory` اسٹوریج لوکیشن کا استعمال کرتا ہے تاکہ ویلیوز کو صرف108 // اس فنکشن کال کے لائف سائیکل کے لیے اسٹور کیا جا سکے۔109 // مزید جانیں: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack110 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);111 uint256 counter = 0;112 for (uint256 i = 0; i < pizzas.length; i++) {113 if (pizzaToOwner[i] == _owner) {114 result[counter] = i;115 counter++;116 }117 }118 return result;119 }120121 // پیزا اور ملکیت کو دوسرے ایڈریس پر منتقل کرتا ہے122 function transferFrom(address _from, address _to, uint256 _pizzaId) public {123 require(_from != address(0) && _to != address(0), "Invalid address.");124 require(_exists(_pizzaId), "Pizza does not exist.");125 require(_from != _to, "Cannot transfer to the same address.");126 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");127128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);130 pizzaToOwner[_pizzaId] = _to;131132 // امپورٹ کیے گئے IERC721 کانٹریکٹ میں بیان کردہ ایونٹ کو ایمٹ کرتا ہے133 emit Transfer(_from, _to, _pizzaId);134 _clearApproval(_to, _pizzaId);135 }136137 /* *138 * دیے گئے ٹوکن ID کی ملکیت کو محفوظ طریقے سے دوسرے ایڈریس پر منتقل کرتا ہے139 * اگر ٹارگٹ ایڈریس ایک کانٹریکٹ ہے، تو اسے `onERC721Received` کو لاگو کرنا چاہیے،140 * جسے محفوظ منتقلی پر کال کیا جاتا ہے، اور میجک ویلیو واپس کرنی چاہیے141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;142 * بصورت دیگر، منتقلی ریورٹ ہو جاتی ہے۔ */143 function safeTransferFrom(address from, address to, uint256 pizzaId)144 public145 {146 // solium-disable-next-line arg-overflow147 this.safeTransferFrom(from, to, pizzaId, "");148 }149150 /* *151 * دیے گئے ٹوکن ID کی ملکیت کو محفوظ طریقے سے دوسرے ایڈریس پر منتقل کرتا ہے152 * اگر ٹارگٹ ایڈریس ایک کانٹریکٹ ہے، تو اسے `onERC721Received` کو لاگو کرنا چاہیے،153 * جسے محفوظ منتقلی پر کال کیا جاتا ہے، اور میجک ویلیو واپس کرنی چاہیے154 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;155 * بصورت دیگر، منتقلی ریورٹ ہو جاتی ہے۔ */156 function safeTransferFrom(157 address from,158 address to,159 uint256 pizzaId,160 bytes memory _data161 ) public {162 this.transferFrom(from, to, pizzaId);163 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");164 }165166 /* *167 * ٹارگٹ ایڈریس پر `onERC721Received` کو کال کرنے کے لیے انٹرنل فنکشن168 * اگر ٹارگٹ ایڈریس کانٹریکٹ نہیں ہے تو کال ایگزیکیوٹ نہیں ہوتی */169 function _checkOnERC721Received(170 address from,171 address to,172 uint256 pizzaId,173 bytes memory _data174 ) internal returns (bool) {175 if (!isContract(to)) {176 return true;177 }178179 bytes4 retval = IERC721Receiver(to).onERC721Received(180 msg.sender,181 from,182 pizzaId,183 _data184 );185 return (retval == _ERC721_RECEIVED);186 }187188 // پیزا کو برن (burn) کرتا ہے - ٹوکن کو مکمل طور پر تباہ کر دیتا ہے189 // `external` فنکشن موڈیفائر کا مطلب ہے کہ یہ فنکشن190 // کانٹریکٹ انٹرفیس کا حصہ ہے اور دوسرے کانٹریکٹس اسے کال کر سکتے ہیں191 function burn(uint256 _pizzaId) external {192 require(msg.sender != address(0), "Invalid address.");193 require(_exists(_pizzaId), "Pizza does not exist.");194 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");195196 ownerPizzaCount[msg.sender] = SafeMath.sub(197 ownerPizzaCount[msg.sender],198 1199 );200 pizzaToOwner[_pizzaId] = address(0);201 }202203 // ایڈریس کے لحاظ سے پیزا کی تعداد واپس کرتا ہے204 function balanceOf(address _owner) public view returns (uint256 _balance) {205 return ownerPizzaCount[_owner];206 }207208 // id کے ذریعے پائے گئے پیزا کا مالک واپس کرتا ہے209 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {210 address owner = pizzaToOwner[_pizzaId];211 require(owner != address(0), "Invalid Pizza ID.");212 return owner;213 }214215 // پیزا کی ملکیت منتقل کرنے کے لیے دوسرے ایڈریس کو منظور کرتا ہے216 function approve(address _to, uint256 _pizzaId) public {217 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");218 pizzaApprovals[_pizzaId] = _to;219 emit Approval(msg.sender, _to, _pizzaId);220 }221222 // مخصوص پیزا کے لیے منظور شدہ ایڈریس واپس کرتا ہے223 function getApproved(uint256 _pizzaId)224 public225 view226 returns (address operator)227 {228 require(_exists(_pizzaId), "Pizza does not exist.");229 return pizzaApprovals[_pizzaId];230 }231232 /* *233 * دیے گئے ٹوکن ID کی موجودہ منظوری کو کلیئر کرنے کے لیے پرائیویٹ فنکشن234 * اگر دیا گیا ایڈریس واقعی ٹوکن کا مالک نہیں ہے تو ریورٹ کر دیتا ہے */235 function _clearApproval(address owner, uint256 _pizzaId) private {236 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");237 require(_exists(_pizzaId), "Pizza does not exist.");238 if (pizzaApprovals[_pizzaId] != address(0)) {239 pizzaApprovals[_pizzaId] = address(0);240 }241 }242243 /* * کسی دیے گئے آپریٹر کی منظوری کو سیٹ یا ان سیٹ کرتا ہے244 * ایک آپریٹر کو بھیجنے والے کی جانب سے اس کے تمام ٹوکنز منتقل کرنے کی اجازت ہوتی ہے */245 function setApprovalForAll(address to, bool approved) public {246 require(to != msg.sender, "Cannot approve own address");247 operatorApprovals[msg.sender][to] = approved;248 emit ApprovalForAll(msg.sender, to, approved);249 }250251 // بتاتا ہے کہ آیا کسی آپریٹر کو دیے گئے مالک کی طرف سے منظور کیا گیا ہے252 function isApprovedForAll(address owner, address operator)253 public254 view255 returns (bool)256 {257 return operatorApprovals[owner][operator];258 }259260 // پیزا کی ملکیت لیتا ہے - صرف منظور شدہ صارفین کے لیے261 function takeOwnership(uint256 _pizzaId) public {262 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");263 address owner = this.ownerOf(_pizzaId);264 this.transferFrom(owner, msg.sender, _pizzaId);265 }266267 // چیک کرتا ہے کہ آیا پیزا موجود ہے268 function _exists(uint256 pizzaId) internal view returns (bool) {269 address owner = pizzaToOwner[pizzaId];270 return owner != address(0);271 }272273 // چیک کرتا ہے کہ آیا ایڈریس مالک ہے یا پیزا منتقل کرنے کے لیے منظور شدہ ہے274 function _isApprovedOrOwner(address spender, uint256 pizzaId)275 internal276 view277 returns (bool)278 {279 address owner = pizzaToOwner[pizzaId];280 // solium چیک کو غیر فعال کریں کیونکہ281 // https://github.com/duaraghav8/Solium/issues/175282 // solium-disable-next-line operator-whitespace283 return (spender == owner ||284 this.getApproved(pizzaId) == spender ||285 this.isApprovedForAll(owner, spender));286 }287288 // چیک کریں کہ آیا پیزا منفرد ہے اور ابھی تک موجود نہیں ہے289 modifier isUnique(string memory _name, uint256 _dna) {290 bool result = true;291 for (uint256 i = 0; i < pizzas.length; i++) {292 if (293 keccak256(abi.encodePacked(pizzas[i].name)) ==294 keccak256(abi.encodePacked(_name)) &&295 pizzas[i].dna == _dna296 ) {297 result = false;298 }299 }300 require(result, "Pizza with such name already exists.");301 _;302 }303304 // واپس کرتا ہے کہ آیا ٹارگٹ ایڈریس ایک کانٹریکٹ ہے305 function isContract(address account) internal view returns (bool) {306 uint256 size;307 // فی الحال یہ چیک کرنے کا کوئی بہتر طریقہ نہیں ہے کہ آیا کسی ایڈریس میں کوئی کانٹریکٹ موجود ہے308 // سوائے اس کے کہ اس ایڈریس پر کوڈ کا سائز چیک کیا جائے۔309 // دیکھیں https://ethereum.stackexchange.com/a/14016/36603310 // اس بارے میں مزید تفصیلات کے لیے کہ یہ کیسے کام کرتا ہے۔311 // TODO Serenity ریلیز سے پہلے اسے دوبارہ چیک کریں، کیونکہ تب تمام ایڈریسز312 // کانٹریکٹس ہوں گے۔313 // solium-disable-next-line security/no-inline-assembly314 assembly {315 size := extcodesize(account)316 }317 return size > 0;318 }319}سب دکھائیںمزید مطالعہ
اسمارٹ کانٹریکٹس کے مزید مکمل جائزے کے لیے Solidity اور Vyper کی دستاویزات دیکھیں:
متعلقہ موضوعات
متعلقہ ٹیوٹوریلز
- کانٹریکٹ کے سائز کی حد سے نمٹنے کے لیے کانٹریکٹس کو چھوٹا کرنا – آپ کے اسمارٹ کانٹریکٹ کا سائز کم کرنے کے لیے کچھ عملی تجاویز۔
- ایونٹس کے ساتھ اسمارٹ کانٹریکٹس سے ڈیٹا لاگ کرنا – اسمارٹ کانٹریکٹ ایونٹس کا تعارف اور آپ انہیں ڈیٹا لاگ کرنے کے لیے کیسے استعمال کر سکتے ہیں۔
- Solidity سے دوسرے کانٹریکٹس کے ساتھ تعامل کریں – موجودہ کانٹریکٹ سے اسمارٹ کانٹریکٹ کو کیسے ڈیپلائے کریں اور اس کے ساتھ تعامل کریں۔