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

Solidity سے دوسرے معاہدوں کے ساتھ تعامل کریں

اسمارٹ معاہدات
solidity
remix
تعینات کرنا
مرکبیت
ترقی
jdourlens
5 اپریل، 2020
5 منٹ کی پڑھائی

پچھلے ٹیوٹوریلز میں ہم نے بہت کچھ سیکھا اپنا پہلا اسمارٹ معاہدہ کیسے تعینات کریں اور اس میں کچھ خصوصیات شامل کرنا جیسے موڈیفائرز کے ساتھ رسائی کو کنٹرول کرنا (opens in a new tab) یا Solidity میں غلطی سے نمٹنا (opens in a new tab)۔ اس ٹیوٹوریل میں ہم سیکھیں گے کہ ایک موجودہ معاہدے سے ایک اسمارٹ معاہدہ کیسے تعینات کیا جائے اور اس کے ساتھ تعامل کیا جائے۔

ہم ایک ایسا معاہدہ بنائیں گے جو کسی کو بھی اپنا Counter اسمارٹ معاہدہ رکھنے کے قابل بنائے گا اس کے لیے ایک فیکٹری بنا کر، اس کا نام CounterFactory ہوگا۔ سب سے پہلے یہاں ہمارے ابتدائی Counter اسمارٹ معاہدے کا کوڈ ہے:

1pragma solidity 0.5.17;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "You're not the owner of the contract");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "You need to use the factory");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
سب دکھائیں

نوٹ کریں کہ ہم نے فیکٹری کے ایڈریس اور معاہدے کے مالک کے ایڈریس کا ٹریک رکھنے کے لیے معاہدے کے کوڈ میں تھوڑی ترمیم کی ہے۔ جب آپ کسی دوسرے معاہدے سے کسی معاہدے کا کوڈ کال کرتے ہیں، تو 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}
5
6function 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;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "You're not the owner of the contract");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "You need to use the factory");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
34
35contract CounterFactory {
36
37 mapping(address => Counter) _counters;
38
39 function createCounter() public {
40 require (_counters[msg.sender] == Counter(0));
41 _counters[msg.sender] = new Counter(msg.sender);
42 }
43
44 function increment() public {
45 require (_counters[msg.sender] != Counter(0));
46 Counter(_counters[msg.sender]).increment(msg.sender);
47 }
48
49 function getCount(address account) public view returns (uint256) {
50 require (_counters[account] != Counter(0));
51 return (_counters[account].getCount());
52 }
53
54 function getMyCount() public view returns (uint256) {
55 return (getCount(msg.sender));
56 }
57
58}
سب دکھائیں

کمپائل کرنے کے بعد، Remix ڈیپلائے سیکشن میں آپ تعینات کی جانے والی فیکٹری کو منتخب کریں گے:

Remix میں تعینات کی جانے والی فیکٹری کا انتخاب

پھر آپ اپنی معاہدہ فیکٹری کے ساتھ کھیل سکتے ہیں اور بدلتی ہوئی قدر کو چیک کر سکتے ہیں۔ اگر آپ اسمارٹ معاہدے کو کسی مختلف ایڈریس سے کال کرنا چاہتے ہیں تو آپ کو Remix کے اکاؤنٹ سلیکٹ میں ایڈریس تبدیل کرنے کی ضرورت ہوگی۔

صفحہ کی آخری تازہ کاری: 15 اگست، 2023

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