Interface در قراردادهای هوشمند Solidity
اینترفیس در قرارداد هوشمند سالیدیتی چیست؟
وقتی کلید روشن و خاموش لامپ را میزنید، لامپ روشن میشود. برای شما مهم نیست “چگونه” کلید برق، لامپ را روشن میکند، شما فقط اهمیت میدهید که “چراغ را روشن میکند”.
تقریبا در تمام مقالات و نوشتهها در مورد رابط Interface در سالیدیتی (solidity interface) مثال بالا را خواهید دید، مثالی که به خوبی ایده پشت Interface در قراردادهای هوشمند Solidityو به طور کلی رابطها در هر زبان برنامهنویسی شیگرا دیگری را روشن میکند.
هدف رابطها را جداسازی تعریف تابع (در این مورد، یک تابع در سالیدیتی) از رفتار واقعی خود تابع میدانند. در مثال بالا برای ما مهم نیست که کلید برق از چه نوعی باشد یا عملکرد داخلی آن به چه روشی است، آنچه مهم است این است که کلید برق همیشه لامپ را روشن یا خاموش میکند و هدف نهایی این است.
رابط هم بر روی فرآیند یا رفتار متمرکز نیست و تمرکزش بر روی هدف نهایی واقعی است. برای اینکه بیشتر با این مفهوم، ویژگیها و محدودیتهای آن اشنا شوید با این مقاله در توکن خان همراه باشید.
قبل از مطالعه کامل مقاله “Interface در قراردادهای هوشمند Solidity” پیشنهاد میکنیم مقالات دیگر حوزه آموزش زبان سالیدیتی را هم مطالعه کنید.
عملگرها در برنامه نویسی سالیدیتی
آرایه ها (Array) در زبان برنامه نویسی Solidity
Struct در قراردادهای هوشمند سالیدیتی Solidity
وراثت در سالیدیتی Solidity Inheritance
مدیریت خطا در سالیدیتی Error Handling
کاربردهای برنامه نویسی سالیدیتی
اینترفیس در سالیدیتی چیست؟
بنابر مستندات سالیدیتی، رابطها به صورت زیر تعریف میشوند:
رابطها ها شبیه قراردادهای انتزاعی هستند، اما نمیتوانند هیچ عملکردی را اجرا کنند. رابط قرارداد، لیستی از تعاریف توابع بدون اجرا خواهد بود.
در تمام زبانهای برنامه نویسی شیگرا، رابط توصیفی از عملکردهای یک شی است که با داشتن آنها میتواند کاربرد داشته باشد و اگر آن عملکردها را نداشته باشد نمیتواند کار کند. هدف رابطها اعمال ویژگیهای تعریف شده و اجرای توابع خاص در یک شی دیگر است.
رابط Interface در سالیدیتی هم دقیقا مانند رابط در سایر زبانهای برنامه نویسی شیگرا است.
- آنها بیشتر در بالای قرارداد هوشمند و با کلمه کلیدی Interface به قرارداد اضافه میشوند.
- رابطها امضاهای تابع، بدون اجرای تعریف تابع هستند به این معنی که جزئیات پیادهسازی آنها اهمیت کمتری دارد.
- از یک رابط در یک قرارداد میتوان برای فراخوانی توابع در قرارداد دیگری نیز استفاده کرد.
در مثال زیر میتوانید یک قرارداد هوشمند با رابط IERC20 را مشاهده کنید.
امضاهای تابع رابط در این قرارداد لیست شده اند و با (;) پایان مییابند. همانطور که در این قرارداد میبینید، رابط IERC20 وارد شده است، این رابط توابع موجود را لیست کرده اما این توابع هیچ تعریفی ندارند. مثلا شما نمیدانید totalSupply، balanceOf و transfer چه کاری انجام میدهند چون هیچ تعریفی برای تابع یا پیادهسازی آن لیست نشده است. حال اینکه شما میدانید که این توابع برای استفاده در دسترس هستند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//import the IERC20 interface //the IERC20 interface lists functions available but no definitions //as an example you do not know what totalSupply, balanceOf and transfer do //because there is no function definition or function implementation listed //you do know that the functions are available to use pragma solidity ^0.8.7; interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient,uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract sampleContract{ // do something // do something } |
استفاده از رابطها در برنامهها یا قراردادهایی که نیاز به توسعه پذیری دارند اما میخواهید این توسعه پذیری را بدون ایجاد پیچیدگی بیشتر اجرا کنید، بسیار سودمند هستند، آنها از افزایش تکرار کد و سربار جلوگیری میکنند.
رابط های قراردادهای هوشمند چیست؟
رابطها اسکلت یا ستون فقرات قراردادهای هوشمند هستند و عملکردهای قرارداد و چگونگی راهاندازی آنها را مشخص می کند. به این طریق Dapps یا قراردادهای هوشمند دیگر، میتوانند آگاهی داشته باشند که چگونه با هر قرارداد هوشمندی که یک رابط خاص را اجرا یا پیاده سازی میکند تعامل داشته باشند چون که رابط شناخته شده است.
مناسبترین مثال مرتبط با این مفهوم، تا حد زیادی استاندارد توکن محبوب ERC20 است. این استاندارد رابط توابع استاندارد را برای یک قرارداد که یک توکن را نشان میدهد، تعریف میکند. کد سالیدیتی زیر، گرفته شده از OpenZeppelin به خوبی توضیح میدهد که این توابع قرار است چه کاری انجام دهند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); // ... more functions defined} |
تعداد زیادی توکن با استاندارد ERC20 وجود دارد و تعامل با همه آنها به یک شکل است.
- اگر میخواهید بدانید چند توکن X دارید، تابع balanceOf(…) را فراخوانی کنید.
- اگر میخواهید تعدادی توکن X را به کسی انتقال دهید، تابع transfer(…) را فراخوانی کنید.
آگاهی از اینکه قرارداد هوشمند مبتنی بر یک رابط خاص است، کار را آسان میکند:
- میدانید که قرارداد چه کاری میتواند انجام دهد.
- میدانید که چگونه با آن قرارداد تعامل کنید.
وجود رابطها نیاز به درک پیچیدگی که پشت عملکردهای واقعی وجود دارد را از بین می برد. قراردادهای رابط بر روی فرآیند یا نحوه رفتار و اینکه چگونه یک تابع، یک کار خاص را انجام میدهد، تمرکز نمیکنند. در عوض تمرکز آنها بر روی آن چیزی است که قرارداد میتواند انجام دهد.
ایده اصلی پشت استفاده از Interface در قراردادهای هوشمند Solidity، ارائه یک رویکرد قابل تنظیم و قابل استفاده مجدد برای قراردادهای شما است.
ویژگی های اینترفیس Interface
- برای ایجاد یک رابط باید از کلمه کلیدی Interface استفاده کنید.
- تعدادی از نامهای رابط با یک I آغاز میشوند تا کار شناسایی و تشخیص آنها در کد راحتتر شود.
- توابع رابط همگی به صورت ضمنی مجازی هستند.
- یک تابع رابط را میتوان لغو کرد.
- قراردادها به همان ترتیبی که میتوانند قراردادهای دیگر را به ارث ببرند، میتوانند رابطها را هم به ارث ببرند.
- رابطها بر اساس قوانین وراثت عادی، میتوانند از رابطهای دیگر نیز به ارث ببرند.
- توابع ارث گرفته از رابط، همگی باید اصلاح کننده override را روی هر تابعی که یک تابع رابط را لغو میکند، تنظیم کنند. اگر این کار انجام نگیرد کامپایلر خطا میدهد.
- امکان دسترسی به انواع دادههای تعریف شده در داخل رابط، از طریق قراردادهای دیگر ممکن است. به عنوان نمونه در مثال زیر قراردادی که از رابط استفاده کرده، میتواند به Iauto.carType و Iauto.vehicle دسترسی داشته باشد.
1 2 3 4 5 6 7 |
pragma solidity ^0.8.7; interface Iauto { enum carType { gas, electric} struct vehicle { string car; string truck; } function transfer(address recipient, uint amount) external; } |
محدودیت های اینترفیس Interface
- اینترفیس در سالیدیتی نمیتوانند از قراردادهای دیگر ارث ببرند، اما میتوانند از رابطهای دیگر ارث ببرند.
- توابع یک رابط Interface در سالیدیتی تنها میتوانند از نوع توابع خارجی (external) باشند.
- رابطها نمیتوانند سازنده (Constructor) را اعلان کنند.
- رابطها نمیتوانند متغیرهای حالت (State Variable) را اعلان کنند.
نمونه ای از ایجاد یک Interface در قراردادهای هوشمند Solidity
در مثال زیر یک قرارداد با نام thisContract، یک رابط InterfaceExample را پیاده سازی میکند و تمام توابع رابط را بر روی آن اجرا میکند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
// Solidity program to // demonstrate the working // of the interface pragma solidity 0.4.19; // A simple interface interface InterfaceExample{ // Functions having only // declaration not definition function getStr( ) public view returns(string memory); function setValue( uint _num1, uint _num2) public; function add( ) public view returns(uint); } // Contract that implements interface contract thisContract is InterfaceExample{ // Private variables uint private num1; uint private num2; // Function definitions of functions // declared inside an interface function getStr( ) public view returns(string memory){ return "GeeksForGeeks"; } // Function to set the values // of the private variables function setValue( uint _num1, uint _num2) public{ num1 = _num1; num2 = _num2; } // Function to add 2 numbers function add( ) public view returns(uint){ return num1 + num2; } } contract call{ //Creating an object InterfaceExample obj; function call() public{ obj = new thisContract(); } // Function to print string // value and the sum value function getValue( ) public returns(uint){ obj.getStr; obj.setValue(10, 16); return obj.add(); } } |
خروجی کدهای بالا مطابق با تصویر زیر است:
جمع بندی
رابط Interface در سالیدیتی همان قراردادهای انتزاعی هستند که از طریق یک کلمه کلیدی interface ایجاد میشوند، همچنین از آنها به عنوان یک قرارداد انتزاعی خالص نیز یاد میشود. رابطها در واقع هیچ تعریف یا هیچ متغیر حالت، هیچ سازنده یا هیچ تابعی با پیادهسازی ندارند. آنها تنها شامل اعلان تابع هستند، به بیان دیگر توابع در رابطها هیچ عبارتی ندارند.
شما میتوانید با اعلان یک Interface در قراردادهای هوشمند Solidity با قراردادهای دیگر تعامل داشته باشید. به طور کلی میتوان ویژگیهای زیر را برای رابطها عنوان کرد:
- نمیتواند هیچ عملکردی را اجرا کند.
- نمی تواند از سایر رابطها به ارث ببرد.
- همه توابع اعلام شده باید خارجی باشند.
- نمیتواند سازنده را اعلام کند.
- نمیتواند متغیرهای حالت را اعلام کند.
منابع معتبر مرتبط:
https://www.geeksforgeeks.org/solidity-basics-of-interface
https://medium.com/coinmonks/solidity-tutorial-all-about-interfaces-f547d2869499
مطالب زیر را حتما مطالعه کنید
بررسی رفتار توابع View و Pure در سالیدیتی Solidity
توابع Payable در قراردادهای هوشمند Solidity
سالیدیتی Solidity چیست؟
سطح دسترسی Visibility در سالیدیتی Solidity
توابع Function در سالیدیتی Solidity
انواع حافظه در قرارداد هوشمند سالیدیتی
8 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
خیلی دنبال این موضوع بودم
مطلب خوبی بود همکار گرامی
چه مطلب خوبی
مطلب خوبی بود
بازم درمورد این موضوع مطلب بزارین
من یکی از کاربران دائمی سایت شما هستم
سلام عالی بود
مطلبتون بسیار مفید بود