Solidity سے دوسرے معاہدوں کے ساتھ تعامل کریں
پچھلے ٹیوٹوریلز میں ہم نے بہت کچھ سیکھا اپنا پہلا اسمارٹ معاہدہ کیسے تعینات کریں اور اس میں کچھ خصوصیات شامل کرنا جیسے موڈیفائرز کے ساتھ رسائی کو کنٹرول کرنا (opens in a new tab) یا Solidity میں غلطی سے نمٹنا (opens in a new tab)۔ اس ٹیوٹوریل میں ہم سیکھیں گے کہ ایک موجودہ معاہدے سے ایک اسمارٹ معاہدہ کیسے تعینات کیا جائے اور اس کے ساتھ تعامل کیا جائے۔
ہم ایک ایسا معاہدہ بنائیں گے جو کسی کو بھی اپنا Counter اسمارٹ معاہدہ رکھنے کے قابل بنائے گا اس کے لیے ایک فیکٹری بنا کر، اس کا نام CounterFactory ہوگا۔ سب سے پہلے یہاں ہمارے ابتدائی Counter اسمارٹ معاہدے کا کوڈ ہے:
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "You're not the owner of the contract");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "You need to use the factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}سب دکھائیںنوٹ کریں کہ ہم نے فیکٹری کے ایڈریس اور معاہدے کے مالک کے ایڈریس کا ٹریک رکھنے کے لیے معاہدے کے کوڈ میں تھوڑی ترمیم کی ہے۔ جب آپ کسی دوسرے معاہدے سے کسی معاہدے کا کوڈ کال کرتے ہیں، تو msg.sender ہمارے معاہدے کی فیکٹری کے ایڈریس کا حوالہ دے گا۔ یہ سمجھنے کے لیے ایک بہت اہم نکتہ ہے کیونکہ دوسرے معاہدوں کے ساتھ تعامل کرنے کے لیے ایک معاہدے کا استعمال ایک عام رواج ہے۔ اس لیے آپ کو پیچیدہ معاملات میں اس بات کا خیال رکھنا چاہیے کہ بھیجنے والا کون ہے۔
اس کے لیے ہم نے ایک onlyFactory موڈیفائر بھی شامل کیا ہے جو اس بات کو یقینی بناتا ہے کہ اسٹیٹ کو تبدیل کرنے والے فنکشن کو صرف فیکٹری کے ذریعے ہی کال کیا جا سکتا ہے جو اصل کالر کو ایک پیرامیٹر کے طور پر پاس کرے گا۔
ہمارے نئے CounterFactory کے اندر جو دیگر تمام کاؤنٹروں کا نظم کرے گا، ہم ایک میپنگ شامل کریں گے جو ایک مالک کو اس کے کاؤنٹر معاہدے کے ایڈریس کے ساتھ منسلک کرے گا:
1mapping(address => Counter) _counters;Ethereum میں، میپنگ جاوا اسکرپٹ میں آبجیکٹس کے مساوی ہیں، وہ قسم A کی کلید کو قسم B کی قدر سے میپ کرنے کے قابل بناتے ہیں۔ اس صورت میں ہم ایک مالک کے ایڈریس کو اس کے کاؤنٹر کے انسٹنس کے ساتھ میپ کرتے ہیں۔
کسی کے لیے ایک نیا کاؤنٹر شروع کرنا اس طرح نظر آئے گا:
1 function createCounter() public {2 require (_counters[msg.sender] == Counter(0));3 _counters[msg.sender] = new Counter(msg.sender);4 }ہم پہلے چیک کرتے ہیں کہ آیا وہ شخص پہلے سے ہی ایک کاؤنٹر کا مالک ہے۔ اگر وہ کاؤنٹر کا مالک نہیں ہے تو ہم اس کا ایڈریس Counter کنسٹرکٹر کو پاس کر کے ایک نیا کاؤنٹر شروع کرتے ہیں اور نئے بنائے گئے انسٹنس کو میپنگ کو تفویض کرتے ہیں۔
ایک مخصوص کاؤنٹر کی گنتی حاصل کرنے کے لیے یہ اس طرح نظر آئے گا:
1function getCount(address account) public view returns (uint256) {2 require (_counters[account] != Counter(0));3 return (_counters[account].getCount());4}56function getMyCount() public view returns (uint256) {7 return (getCount(msg.sender));8}پہلا فنکشن یہ چیک کرتا ہے کہ آیا دیے گئے ایڈریس کے لیے کاؤنٹر معاہدہ موجود ہے اور پھر انسٹنس سے getCount میتھڈ کو کال کرتا ہے۔ دوسرا فنکشن: getMyCount صرف msg.sender کو براہ راست getCount فنکشن میں پاس کرنے کا ایک مختصر طریقہ ہے۔
increment فنکشن کافی ملتا جلتا ہے لیکن اصل ٹرانزیکشن بھیجنے والے کو Counter معاہدے میں پاس کرتا ہے:
1function increment() public {2 require (_counters[msg.sender] != Counter(0));3 Counter(_counters[msg.sender]).increment(msg.sender);4 }نوٹ کریں کہ اگر بہت زیادہ بار کال کیا گیا، تو ہمارا کاؤنٹر ممکنہ طور پر اوور فلو کا شکار ہو سکتا ہے۔ اس ممکنہ صورتحال سے بچانے کے لیے آپ کو جتنا ممکن ہو SafeMath لائبریری (opens in a new tab) کا استعمال کرنا چاہیے۔
ہمارے معاہدے کو تعینات کرنے کے لیے، آپ کو CounterFactory اور Counter دونوں کا کوڈ فراہم کرنا ہوگا۔ مثال کے طور پر Remix میں تعینات کرتے وقت آپ کو CounterFactory کو منتخب کرنے کی ضرورت ہوگی۔
مکمل کوڈ یہاں ہے:
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "You're not the owner of the contract");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "You need to use the factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}3435contract CounterFactory {3637 mapping(address => Counter) _counters;3839 function createCounter() public {40 require (_counters[msg.sender] == Counter(0));41 _counters[msg.sender] = new Counter(msg.sender);42 }4344 function increment() public {45 require (_counters[msg.sender] != Counter(0));46 Counter(_counters[msg.sender]).increment(msg.sender);47 }4849 function getCount(address account) public view returns (uint256) {50 require (_counters[account] != Counter(0));51 return (_counters[account].getCount());52 }5354 function getMyCount() public view returns (uint256) {55 return (getCount(msg.sender));56 }5758}سب دکھائیںکمپائل کرنے کے بعد، Remix ڈیپلائے سیکشن میں آپ تعینات کی جانے والی فیکٹری کو منتخب کریں گے:
پھر آپ اپنی معاہدہ فیکٹری کے ساتھ کھیل سکتے ہیں اور بدلتی ہوئی قدر کو چیک کر سکتے ہیں۔ اگر آپ اسمارٹ معاہدے کو کسی مختلف ایڈریس سے کال کرنا چاہتے ہیں تو آپ کو Remix کے اکاؤنٹ سلیکٹ میں ایڈریس تبدیل کرنے کی ضرورت ہوگی۔
صفحہ کی آخری تازہ کاری: 15 اگست، 2023
