ایک solidity اسمارٹ کنٹریکٹ سے ERC-20 ٹوکنز کی منتقلی اور منظوری
پچھلے ٹیوٹوریل میں ہم نے Ethereum بلاک چین پر Solidity میں ERC-20 ٹوکن کی ساخت کا مطالعہ کیا تھا۔ اس مضمون میں ہم دیکھیں گے کہ ہم Solidity زبان کا استعمال کرتے ہوئے ٹوکن کے ساتھ تعامل کرنے کے لیے اسمارٹ کنٹریکٹ کا استعمال کیسے کر سکتے ہیں۔
اس اسمارٹ کنٹریکٹ کے لیے، ہم ایک حقیقی ڈمی غیر مرکزی تبادلہ بنائیں گے جہاں ایک صارف ہمارے نئے ڈیپلائے کیے گئے ERC-20 ٹوکن کے لیے ایتھر کی تجارت کر سکتا ہے۔
اس ٹیوٹوریل کے لیے ہم اس کوڈ کا استعمال کریں گے جسے ہم نے پچھلے ٹیوٹوریل میں ایک بنیاد کے طور پر لکھا تھا۔ ہمارا DEX اپنے کنسٹرکٹر میں کنٹریکٹ کا ایک انسٹینس بنائے گا اور درج ذیل آپریشنز انجام دے گا:
- ٹوکنز کو ایتھر میں تبدیل کرنا
- ایتھر کو ٹوکنز میں تبدیل کرنا
ہم اپنا سادہ ERC20 کوڈ بیس شامل کرکے اپنا غیر مرکزی تبادلے کا کوڈ شروع کریں گے:
1pragma solidity ^0.8.0;23interface IERC20 {45 function totalSupply() external view returns (uint256);6 function balanceOf(address account) external view returns (uint256);7 function allowance(address owner, address spender) external view returns (uint256);89 function transfer(address recipient, uint256 amount) external returns (bool);10 function approve(address spender, uint256 amount) external returns (bool);11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);121314 event Transfer(address indexed from, address indexed to, uint256 value);15 event Approval(address indexed owner, address indexed spender, uint256 value);16}171819contract ERC20Basic is IERC20 {2021 string public constant name = "ERC20Basic";22 string public constant symbol = "ERC";23 uint8 public constant decimals = 18;242526 mapping(address => uint256) balances;2728 mapping(address => mapping (address => uint256)) allowed;2930 uint256 totalSupply_ = 10 ether;313233 constructor() {34 balances[msg.sender] = totalSupply_;35 }3637 function totalSupply() public override view returns (uint256) {38 return totalSupply_;39 }4041 function balanceOf(address tokenOwner) public override view returns (uint256) {42 return balances[tokenOwner];43 }4445 function transfer(address receiver, uint256 numTokens) public override returns (bool) {46 require(numTokens <= balances[msg.sender]);47 balances[msg.sender] = balances[msg.sender]-numTokens;48 balances[receiver] = balances[receiver]+numTokens;49 emit Transfer(msg.sender, receiver, numTokens);50 return true;51 }5253 function approve(address delegate, uint256 numTokens) public override returns (bool) {54 allowed[msg.sender][delegate] = numTokens;55 emit Approval(msg.sender, delegate, numTokens);56 return true;57 }5859 function allowance(address owner, address delegate) public override view returns (uint) {60 return allowed[owner][delegate];61 }6263 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {64 require(numTokens <= balances[owner]);65 require(numTokens <= allowed[owner][msg.sender]);6667 balances[owner] = balances[owner]-numTokens;68 allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens;69 balances[buyer] = balances[buyer]+numTokens;70 emit Transfer(owner, buyer, numTokens);71 return true;72 }73}7475سب دکھائیںہمارا نیا DEX اسمارٹ کنٹریکٹ ERC-20 کو ڈیپلائے کرے گا اور فراہم کردہ تمام چیزیں حاصل کرے گا:
1contract DEX {23 IERC20 public token;45 event Bought(uint256 amount);6 event Sold(uint256 amount);78 constructor() {9 token = new ERC20Basic();10 }1112 function buy() payable public {13 // TODO14 }1516 function sell(uint256 amount) public {17 // TODO18 }1920}سب دکھائیںتو اب ہمارے پاس اپنا DEX ہے اور اس میں تمام ٹوکن ریزرو دستیاب ہیں۔ کنٹریکٹ میں دو فنکشنز ہیں:
buy: صارف ایتھر بھیج سکتا ہے اور بدلے میں ٹوکن حاصل کر سکتا ہےsell: صارف ایتھر واپس حاصل کرنے کے لیے ٹوکن بھیجنے کا فیصلہ کر سکتا ہے
خریدنے کا فنکشن
آئیے خریدنے کا فنکشن کوڈ کریں۔ ہمیں پہلے یہ چیک کرنے کی ضرورت ہوگی کہ پیغام میں ایتھر کی کتنی مقدار ہے اور اس بات کی تصدیق کرنی ہوگی کہ کنٹریکٹس کے پاس کافی ٹوکنز ہیں اور یہ کہ پیغام میں کچھ ایتھر موجود ہے۔ اگر کنٹریکٹ کے پاس کافی ٹوکنز ہیں تو وہ صارف کو ٹوکنز کی تعداد بھیجے گا اور Bought ایونٹ کو ایمٹ کرے گا۔
نوٹ کریں کہ اگر ہم خرابی کی صورت میں require فنکشن کو کال کرتے ہیں تو بھیجا گیا ایتھر براہ راست ریورٹ ہو جائے گا اور صارف کو واپس کر دیا جائے گا۔
چیزوں کو آسان رکھنے کے لیے، ہم صرف 1 Wei کے بدلے 1 ٹوکن کا تبادلہ کرتے ہیں۔
1function buy() payable public {2 uint256 amountTobuy = msg.value;3 uint256 dexBalance = token.balanceOf(address(this));4 require(amountTobuy > 0, "You need to send some ether");5 require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");6 token.transfer(msg.sender, amountTobuy);7 emit Bought(amountTobuy);8}اس صورت میں جہاں خرید کامیاب ہوتی ہے ہمیں ٹرانزیکشن میں دو ایونٹس نظر آنے چاہئیں: ٹوکن Transfer اور Bought ایونٹ۔
فروخت کا فنکشن
فروخت کے لیے ذمہ دار فنکشن کے لیے پہلے یہ ضروری ہوگا کہ صارف نے پہلے سے approve فنکشن کو کال کرکے رقم کی منظوری دی ہو۔ ٹرانسفر کی منظوری کے لیے ضروری ہے کہ DEX کے ذریعے انسٹینشیئٹ کردہ ERC20Basic ٹوکن کو صارف کے ذریعے کال کیا جائے۔ یہ پہلے DEX کنٹریکٹ کے token() فنکشن کو کال کرکے اس ایڈریس کو حاصل کرکے کیا جا سکتا ہے جہاں DEX نے token نامی ERC20Basic کنٹریکٹ ڈیپلائے کیا تھا۔ پھر ہم اپنے سیشن میں اس کنٹریکٹ کا ایک انسٹینس بناتے ہیں اور اس کے approve فنکشن کو کال کرتے ہیں۔ پھر ہم DEX کے sell فنکشن کو کال کرنے اور اپنے ٹوکنز کو واپس ایتھر کے لیے سواپ کرنے کے قابل ہوتے ہیں۔ مثال کے طور پر، ایک انٹرایکٹو براؤنی سیشن میں یہ اس طرح نظر آتا ہے:
1#### Python in interactive brownie console...23# deploy the DEX4dex = DEX.deploy({'from':account1})56# call the buy function to swap ether for token7# 1e18 is 1 ether denominated in wei8dex.buy({'from': account2, 1e18})910# get the deployment address for the ERC20 token11# that was deployed during DEX contract creation12# dex.token() returns the deployed address for token13token = ERC20Basic.at(dex.token())1415# call the token's approve function16# approve the dex address as spender17# and how many of your tokens it is allowed to spend18token.approve(dex.address, 3e18, {'from':account2})19سب دکھائیںپھر جب sell فنکشن کو کال کیا جاتا ہے، تو ہم چیک کریں گے کہ کالر کے ایڈریس سے کنٹریکٹ ایڈریس پر منتقلی کامیاب تھی یا نہیں اور پھر ایتھرز کو کالر کے ایڈریس پر واپس بھیج دیں گے۔
1function sell(uint256 amount) public {2 require(amount > 0, "You need to sell at least some tokens");3 uint256 allowance = token.allowance(msg.sender, address(this));4 require(allowance >= amount, "Check the token allowance");5 token.transferFrom(msg.sender, address(this), amount);6 payable(msg.sender).transfer(amount);7 emit Sold(amount);8}اگر سب کچھ کام کرتا ہے تو آپ کو ٹرانزیکشن میں 2 ایونٹس (Transfer اور Sold) نظر آنے چاہئیں اور آپ کا ٹوکن بیلنس اور ایتھر بیلنس اپ ڈیٹ ہونا چاہیے۔
اس ٹیوٹوریل سے ہم نے دیکھا کہ ERC-20 ٹوکن کا بیلنس اور الاؤنس کیسے چیک کیا جائے اور انٹرفیس کا استعمال کرتے ہوئے ERC20 اسمارٹ کنٹریکٹ کے Transfer اور TransferFrom کو کیسے کال کیا جائے۔
ایک بار جب آپ کوئی ٹرانزیکشن کرتے ہیں تو ہمارے پاس ایک JavaScript ٹیوٹوریل ہے ٹرانزیکشنز کے بارے میں تفصیلات کا انتظار کرنے اور حاصل کرنے کے لیےopens in a new tab جو آپ کے کنٹریکٹ میں کی گئی تھیں اور ایک ٹیوٹوریل ہے جو ٹوکن ٹرانسفرز یا کسی دوسرے ایونٹس کے ذریعے پیدا ہونے والے ایونٹس کو ڈی کوڈ کرنے کے لیے ہےopens in a new tab جب تک کہ آپ کے پاس ABI ہو۔
ٹیوٹوریل کے لیے مکمل کوڈ یہ ہے:
1pragma solidity ^0.8.0;23interface IERC20 {45 function totalSupply() external view returns (uint256);6 function balanceOf(address account) external view returns (uint256);7 function allowance(address owner, address spender) external view returns (uint256);89 function transfer(address recipient, uint256 amount) external returns (bool);10 function approve(address spender, uint256 amount) external returns (bool);11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);121314 event Transfer(address indexed from, address indexed to, uint256 value);15 event Approval(address indexed owner, address indexed spender, uint256 value);16}171819contract ERC20Basic is IERC20 {2021 string public constant name = "ERC20Basic";22 string public constant symbol = "ERC";23 uint8 public constant decimals = 18;242526 mapping(address => uint256) balances;2728 mapping(address => mapping (address => uint256)) allowed;2930 uint256 totalSupply_ = 10 ether;313233 constructor() {34 balances[msg.sender] = totalSupply_;35 }3637 function totalSupply() public override view returns (uint256) {38 return totalSupply_;39 }4041 function balanceOf(address tokenOwner) public override view returns (uint256) {42 return balances[tokenOwner];43 }4445 function transfer(address receiver, uint256 numTokens) public override returns (bool) {46 require(numTokens <= balances[msg.sender]);47 balances[msg.sender] = balances[msg.sender]-numTokens;48 balances[receiver] = balances[receiver]+numTokens;49 emit Transfer(msg.sender, receiver, numTokens);50 return true;51 }5253 function approve(address delegate, uint256 numTokens) public override returns (bool) {54 allowed[msg.sender][delegate] = numTokens;55 emit Approval(msg.sender, delegate, numTokens);56 return true;57 }5859 function allowance(address owner, address delegate) public override view returns (uint) {60 return allowed[owner][delegate];61 }6263 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {64 require(numTokens <= balances[owner]);65 require(numTokens <= allowed[owner][msg.sender]);6667 balances[owner] = balances[owner]-numTokens;68 allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens;69 balances[buyer] = balances[buyer]+numTokens;70 emit Transfer(owner, buyer, numTokens);71 return true;72 }73}747576contract DEX {7778 event Bought(uint256 amount);79 event Sold(uint256 amount);808182 IERC20 public token;8384 constructor() {85 token = new ERC20Basic();86 }8788 function buy() payable public {89 uint256 amountTobuy = msg.value;90 uint256 dexBalance = token.balanceOf(address(this));91 require(amountTobuy > 0, "You need to send some ether");92 require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");93 token.transfer(msg.sender, amountTobuy);94 emit Bought(amountTobuy);95 }9697 function sell(uint256 amount) public {98 require(amount > 0, "You need to sell at least some tokens");99 uint256 allowance = token.allowance(msg.sender, address(this));100 require(allowance >= amount, "Check the token allowance");101 token.transferFrom(msg.sender, address(this), amount);102 payable(msg.sender).transfer(amount);103 emit Sold(amount);104 }105106}سب دکھائیںصفحہ کی آخری تازہ کاری: 15 فروری، 2026

