mapping در قرارداد هوشمند Solidity
mapping در قرارداد هوشمند Solidity مانند یک dictionary در پایتون یا map در جاوا اسکریپت است. mapping به شما امکان میدهد دادههایی را که میخواهید بازیابی کنید در یک تابع با استفاده از رابطه جفت کلید به ارزش ذخیره کنید. نگاشت ها برای ایجاد ارتباط بین انواع داده های مختلف (به عنوان مثال: address و amount یا uint و bool) بسیار مفید هستند. چند نکته در مورد mapping ها قابل توجه است:
- آنها برای جستجوی سریع عالی هستند.
- mappingها طول ندارد.
- بهطور پیشفرض نمیتوانید یک mpping را تکرار کنید.
- به منظور تکرار یک mapping، باید از ترکیبی از mappingهااستفاده کنید و کلیدها را در یک آرایه ذخیره کنید.
- شما نمی توانید اندازه یک mpping را تعیین یا بدست آورید.
- از mpping فقط می توان برای متغیرهای حالتی که به عنوان انواع مرجع ذخیره سازی عمل می کنند استفاده کرد.
نقشه ها با سینتکس “mapping(keyType => valueType)” ایجاد می شوند و مانند هر نوع متغیر دیگری در Solidity تعریف می شوند.
مثال زیر را ببینید.
Mapping (key => value) public myMapNAME;
انواع کلیدهای معتبر (Valid Key) می تواند string یا byte باشد که به uint، bool یا address ترجمه می شود. انواع ارزش معتبر (Valid value) می تواند هر نوع باشد. این باعث می شود که نگاشت ها بسیار منعطف و برای استفاده راحت باشند.
نمونه استفاده از mapping
اجازه دهید یک قرارداد نمونه ایجاد کنیم که از mapping استفاده می کند. قرارداد زیر یک قرارداد ساده است که چیزی در آن تعریف نشده است. ما این قرارداد را برای نشان دادن نحوه ساخت و عملکرد یک mapping گسترش خواهیم داد.
pragma solidity ^0.8.0;
//Sample contract is an example
contract SampleContract {
//nothing is defined in this contract
}
بیایید کد بالا را گسترش دهیم و یک mapping به قراردادمان اضافه کنیم. این mapping یک عدد “مقدار” را در یک “کلید” آدرس مربوطه ذخیره می کند و داده ها را در بلاکچین ذخیره می کند. در کد زیر mapping را تعریف می کنیم و تابعی ایجاد می کنیم که داده ها را روی mapping تنظیم می کند.
pragma solidity ^0.8.0;
//Sample contract
contract SampleContract {
//state variable
//added a map that takes an address "key" and a number "value"
//the name of the map is called myMap
mapping (address => uint) public myMap;
//this function sets a value to a specific address
//the data is saved to myMap on the block chain
function set(address _addr, uint _i) public {
myMap[_addr] = _i;
}
}
خواندن یک item در mapping
برای خواندن یک آیتم در mapping از تابع get استفاده می شود. این شبیه به نحوه دسترسی ما به داده ها در یک آرایه است.
pragma solidity ^0.8.0;
//Sample contract
contract SampleContract {
//state variable
//added a map that takes an address "key" and a number "value"
//the name of the map is called myMap
mapping (address => uint) public myMap;
//this function sets a value to a specific address
//the data is saved to myMap on the block chain
function set(address _addr, uint _i) public {
// Update the value at this address
myMap[_addr] = _i;
}
//this function gets a value from a specific address in the map
//If a value was not set the function will return the default value of 0.
function get(address _addr) public view returns (uint) {
return myMap[_addr];
}
}
حذف یک item از mapping
اجازه دهید یک تابع حذف به قرارداد اضافه کنیم تا بتوانیم موارد موجود در mapping را حذف کنیم. اکنون قرارداد زیر شامل:
- یک mapping است که به عنوان myMap تعریف شده است که یک متغیر حالت ذخیره شده در بلاکچین می باشد.
- یک تابع برای تنظیم یک مقدار به یک آدرس خاص.
- یک تابع برای دریافت مقدار ذخیره شده برای یک آدرس.
- و در نهایت تابعی برای حذف مقداری که برای یک آدرس تعیین کرده اید.
pragma solidity ^0.8.0;
//Sample contract
contract SampleContract {
//state variable
//added a map that takes an address "key" and a number "value"
//the name of the map is called myMap
mapping (address => uint) public myMap;
//this function sets a value to a specific address
//the data is saved to myMap on the block chain
function set(address _addr, uint _i) public {
myMap[_addr] = _i;
}
//this function gets a value from a specific address from the map
//If a value was not set the function will return the default value of 0.
function get(address _addr) public view returns (uint) {
return myMap[_addr];
}
//this function deletes a value from the map and sets it to the default value of 0
function remove(address _addr) public {
delete myMap[_addr];
}
}
در قرارداد زیر، نوع مقدار را از uint به bool تغییر دادیم. این نمونه ای از نحوه پیگیری آدرسی است که به یک عبارت درست یا نادرست پاسخ می دهد. به عنوان مثال: آیا این آدرس مجوز دارد؟ آیا این آدرس مالک است؟ و غیره
pragma solidity ^0.8.0;
//Sample contract
contract SampleContract {
//state variables
//added a map that takes an address "key" and a number "value"
//the name of the map is called myMap
mapping (address => bool) public myMap;
//this function sets a value to a specific address
//the data is saved to myMap on the block chain
function set(address _addr, bool _i) public {
myMap[_addr] = _i;
}
//this function gets a value from a specific address from the map
//If a value was not set the function will return the default value of 0.
function get(address _addr) public view returns (bool) {
return myMap[_addr];
}
//this function deletes a value from the map and sets it to the default value of 0
function remove(address _addr) public {
delete myMap[_addr];
}
}
mapping های تو در تو
حال اجازه دهید این تمرین mapping را یک قدم جلوتر ببریم و یک mapping تودرتو ایجاد کنیم. mapping تو در تو جایی است که یک کلید به یک نوع مقدار از mapping دیگر مرتبط می شود.
کد زیر را ببینید.
mapping (address => mapping (address => uint256)) public myMap;
موارد استفاده زیادی وجود دارد که نیاز به mapping تودرتو دارند، بنابراین برای نشان دادن مفهوم، از مثال زیر استفاده می کنیم.
باب یک حساب کاربری حاوی 20 ETH دارد. او می خواهد به آلیس یک کمک هزینه 5 ETH و سیندی کمک هزینه 3 ETH بدهد. برای ردیابی این سناریو می توانید از یک mapping تو در تو استفاده کنید. در معماری پایگاه داده رابطهای، این رابطه یک به چند نامیده میشود: یک مالک میتواند به چندین مصرفکننده این امکان را بدهد که توکنها را از طرف مالکان خرج کنند.
این مثال از نگاشت تو در تو را می توان در قرارداد استاندارد ERC20 در تابع کمک هزینه یافت. این یک مورد استفاده بسیار رایج است.
در زیر نمونه ای از نقشه تو در تو در قرارداد کمک هزینه آورده شده است.
pragma solidity ^0.7.6;
contract allowance {
//mapping an address to another mapping. This is a one to many relationship
mapping(address => mapping(address => uint)) public allowance;
//this function returns the allowance/amount that the owner permissioned to the spender
function get(address _addrOwner, address _addrSpender) public view returns (uint) {
return allowance[_addrOwner][_addrSpender];
}
//this function sets the amount of allowance the owner gives to the spender
function set(address _addrOwner, address _addrSpender, uint _amt) public {
allowance[_addrOwner][_addrSpender] = _amt;
}
//this function removes the spenders allowance
function remove(address _addrOwner, address _addrSpender) public {
delete allowance[_addrOwner][_addrSpender];
}
}
بهترین راه برای یادگیری نحوه عملکرد mapping، آزمایش و ایجاد یک قرارداد هوشمند در Remix است.این کد فقط برای اهداف آموزشی است. کد Audit نشده است و با مسئولیت خود استفاده کنید. به یاد داشته باشید که قراردادهای هوشمند آزمایشی هستند و ممکن است حاوی اشکال باشند.
در صورتی که تجربه خاصی در خصوص برنامهنویسی ندارید میتوانید از دورههای رایگان سایت ما “فرازمان“، استفاده کنید. همچنین اگر به دورههای پیشرفتهتری در این خصوص نیاز داشته باشید، ما با آموزش های حرفه ای که در سایتمان قرار دادیم می توانید به سطح دلخواهتان با تلاش و پشتکار برسید.
نقشه راه
راهنما آکادمی فرازمان
برای یادگیری برنامه نویسی بلاکچین…
در این باره بیشتر بخوانید
دیدگاهتان را بنویسید