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 کے اندر جو دیگر تمام Counters کا انتظام کرے گی، ہم ایک میپنگ شامل کریں گے جو ایک مالک کو اس کے کاؤنٹر کنٹریکٹ کے ایڈریس سے منسلک کرے گی:
1mapping(address => Counter) _counters;Ethereum میں، میپنگ javascript میں آبجیکٹس کے مساوی ہیں، وہ ٹائپ A کی کلید کو ٹائپ B کی ویلیو سے میپ کرنے کے قابل بناتے ہیں۔ اس صورت میں ہم مالک کے ایڈریس کو اس کے Counter کی مثال (instance) کے ساتھ میپ کرتے ہیں۔
کسی کے لیے نیا Counter شروع کرنا کچھ اس طرح نظر آئے گا:
1 function createCounter() public {2 require (_counters[msg.sender] == Counter(0));3 _counters[msg.sender] = new Counter(msg.sender);4 }ہم سب سے پہلے چیک کرتے ہیں کہ آیا اس شخص کے پاس پہلے سے ہی کاؤنٹر ہے۔ اگر اس کے پاس کاؤنٹر نہیں ہے تو ہم اس کا ایڈریس Counter کنسٹرکٹر کو پاس کر کے ایک نیا کاؤنٹر شروع کرتے ہیں اور نئی بنائی گئی مثال کو میپنگ کے لیے تفویض کرتے ہیں۔
کسی مخصوص 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}پہلا فنکشن چیک کرتا ہے کہ آیا دیے گئے ایڈریس کے لیے Counter کنٹریکٹ موجود ہے اور پھر مثال سے 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}سب دکھائیںمرتب (compile) کرنے کے بعد، Remix ڈیپلائے سیکشن میں آپ ڈیپلائے کی جانے والی فیکٹری کو منتخب کریں گے:
پھر آپ اپنی کنٹریکٹ فیکٹری کے ساتھ کھیل سکتے ہیں اور تبدیل ہونے والی ویلیو کو چیک کر سکتے ہیں۔ اگر آپ سمارٹ کنٹریکٹ کو کسی مختلف ایڈریس سے کال کرنا چاہتے ہیں تو آپ کو Remix کے اکاؤنٹ سلیکٹ میں ایڈریس تبدیل کرنے کی ضرورت ہوگی۔
صفحہ کی آخری اپ ڈیٹ: 15 اگست، 2023
