Uhamisho na uidhinishaji wa tokeni za ERC-20 kutoka kwa mkataba-erevu wa solidity
Katika somo lililopita tulijifunza anatomia ya tokeni ya ERC-20 katika Solidity kwenye mnyororo wa bloku wa Ethereum. Katika makala hii tutaona jinsi tunavyoweza kutumia mkataba-erevu kuingiliana na tokeni kwa kutumia lugha ya Solidity.
Kwa ajili ya mkataba-erevu huu, tutaunda mfumo halisi wa majaribio wa kubadilishana uliogatuliwa ambapo mtumiaji anaweza kubadilisha ether kwa tokeni yetu mpya ya ERC-20 iliyotumwa.
Kwa somo hili tutatumia msimbo tuliouandika katika somo lililopita kama msingi. DEX yetu itaanzisha mfano wa mkataba katika kiunda chake na kufanya shughuli za:
- kubadilishana tokeni kwa ether
- kubadilishana ether kwa tokeni
Tutaanzisha msimbo wetu wa kubadilishana uliogatuliwa kwa kuongeza msimbo wetu rahisi wa 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}7475Onyesha yoteMkataba-erevu wetu mpya wa DEX utatumia ERC-20 na kupata yote yaliyotolewa:
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}Onyesha yoteKwa hiyo sasa tuna DEX yetu na ina hifadhi yote ya tokeni inayopatikana. Mkataba una vipengele viwili:
nunua: Mtumiaji anaweza kutuma ether na kupata tokeni badala yakeuza: Mtumiaji anaweza kuamua kutuma tokeni ili kurudishiwa ether
Kipengele cha kununua
Tuandike msimbo wa kipengele cha kununua. Kwanza tutahitaji kuangalia kiasi cha ether kilichomo kwenye ujumbe na kuthibitisha kuwa mikataba inamiliki tokeni za kutosha na kwamba ujumbe una kiasi fulani cha ether ndani yake. Ikiwa mkataba unamiliki tokeni za kutosha, utamtumia mtumiaji idadi ya tokeni na kutoa tukio la Bought.
Kumbuka kwamba tukiita kipengele cha require katika kisa cha kosa ether iliyotumwa itarejeshwa moja kwa moja na kurudishwa kwa mtumiaji.
Ili kurahisisha mambo, tunabadilishana tokeni 1 kwa Wei 1.
1function buy() payable public {2 uint256 amountTobuy = msg.value;3 uint256 dexBalance = token.balanceOf(address(this));4 require(amountTobuy > 0, "Unahitaji kutuma kiasi fulani cha ether");5 require(amountTobuy <= dexBalance, "Hakuna tokeni za kutosha katika hifadhi");6 token.transfer(msg.sender, amountTobuy);7 emit Bought(amountTobuy);8}Katika hali ambapo ununuzi unafanikiwa tunapaswa kuona matukio mawili katika muamala: Transfer ya tokeni na tukio la Bought.
Kipengele cha kuuza
Kipengele kinachohusika na uuzaji kwanza kitahitaji mtumiaji awe ameidhinisha kiasi kwa kuita kipengele cha approve kabla. Kuidhinisha uhamisho kunahitaji tokeni ya ERC20Basic iliyoanzishwa na DEX iitwe na mtumiaji. Hii inaweza kufikiwa kwa kwanza kuita kipengele cha token() cha mkataba wa DEX ili kupata anwani ambapo DEX ilituma mkataba wa ERC20Basic unaoitwa token. Kisha tunaunda mfano wa mkataba huo katika kipindi chetu na kuita kipengele chake cha approve. Kisha tunaweza kuita kipengele cha sell cha DEX na kubadilisha tokeni zetu na kupata ether. Kwa mfano, hivi ndivyo inavyoonekana katika kipindi cha maingiliano cha brownie:
1#### Python katika koni ya maingiliano ya brownie...23# tuma DEX4dex = DEX.deploy({'from':account1})56# ita kipengele cha kununua ili kubadilisha ether kwa tokeni7# 1e18 ni ether 1 katika wei8dex.buy({'from': account2, 1e18})910# pata anwani ya utumaji ya tokeni ya ERC2011# ambayo ilitumwa wakati wa uundaji wa mkataba wa DEX12# dex.token() inarudisha anwani iliyotumwa ya tokeni13token = ERC20Basic.at(dex.token())1415# ita kipengele cha kuidhinisha cha tokeni16# idhinisha anwani ya dex kama mtumiaji17# na ni tokeni zako ngapi inaruhusiwa kutumia18token.approve(dex.address, 3e18, {'from':account2})19Onyesha yoteKisha kipengele cha sell kinapoitwa, tutaangalia kama uhamisho kutoka kwa anwani ya mpigaji kwenda kwa anwani ya mkataba ulifanikiwa na kisha tutatuma Ethers kurudi kwa anwani ya mpigaji.
1function sell(uint256 amount) public {2 require(amount > 0, "Unahitaji kuuza angalau tokeni kadhaa");3 uint256 allowance = token.allowance(msg.sender, address(this));4 require(allowance >= amount, "Angalia ruhusa ya tokeni");5 token.transferFrom(msg.sender, address(this), amount);6 payable(msg.sender).transfer(amount);7 emit Sold(amount);8}Ikiwa kila kitu kitafanya kazi unapaswa kuona matukio 2 (Transfer na Sold) katika muamala na salio lako la tokeni na salio la ether likisasishwa.
Kutoka kwa somo hili tumeona jinsi ya kuangalia salio na ruhusa ya tokeni ya ERC-20 na pia jinsi ya kuita Transfer na TransferFrom ya mkataba-erevu wa ERC20 kwa kutumia kiolesura.
Mara tu unapofanya muamala tuna somo la JavaScript la kusubiri na kupata maelezo kuhusu miamala (opens in a new tab) ambayo ilifanywa kwa mkataba wako na somo la kusimbua matukio yaliyotokana na uhamisho wa tokeni au matukio mengine yoyote (opens in a new tab) mradi tu una ABI.
Huu hapa msimbo kamili wa somo:
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, "Unahitaji kutuma kiasi fulani cha ether");92 require(amountTobuy <= dexBalance, "Hakuna tokeni za kutosha katika hifadhi");93 token.transfer(msg.sender, amountTobuy);94 emit Bought(amountTobuy);95 }9697 function sell(uint256 amount) public {98 require(amount > 0, "Unahitaji kuuza angalau tokeni kadhaa");99 uint256 allowance = token.allowance(msg.sender, address(this));100 require(allowance >= amount, "Angalia ruhusa ya tokeni");101 token.transferFrom(msg.sender, address(this), amount);102 payable(msg.sender).transfer(amount);103 emit Sold(amount);104 }105106}Onyesha yoteUkurasa ulihaririwa mwisho: 21 Agosti 2025

