زبان برنامهنویسی Solidity یک زبان سطح بالا، شیء گرا و قرارداد محور (Contract-Oriented) است که بهطور ویژه برای نوشتن قرارداد های هوشمند (Smart Contracts) روی پلتفرم های مبتنی بر بلاکچین، به ویژه Ethereum Virtual Machine یا به اختصار EVM طراحی شده است. این زبان تحت تأثیر زبان های محبوب نظیر C++، Python و JavaScript قرار دارد و به توسعه دهندگان اجازه میدهد تا برنامه های غیرمتمرکز (DApps) را با منطق های تجاری خود تسهیلگر و بدون نیاز به واسطه ها پیاده سازی کنند.
۱. معماری و نحوه کارکرد Solidity در EVM
قرارداد های نوشته شده به زبان Solidity بهطور مستقیم توسط بلاک چین اجرا نمیشوند. فرآیند اجرای یک قرارداد هوشمند به شرح زیر است:
- کامپایل (Compilation): کد منبع
Solidityتوسط کامپایلر رسمی آن یعنیsolcبه بایتکد (Bytecode) کامپایل میشود. - تولید ABI: هم زمان با بایت کد، رابط کاربری باینری قرارداد یا
Application Binary Interfaceکه به اختصارABIنامیده میشود، تولید میگردد.ABIبه برنامه های خارج از بلاکچین (مانند فرانت اند برنامه ها با کتابخانه هایethers.jsیاweb3.js) اجازه میدهد تا با توابع قرارداد تعامل داشته باشند. - استقرار (Deployment): بایت کد تولید شده در قالب یک تراکنش به شبکه بلاک چین ارسال و روی یک آدرس مشخص ذخیره میشود.
- اجرا در EVM: هر زمان که تراکنشی برای فراخوانی توابع قرارداد ارسال شود، این بایت کد توسط ماشین مجازی اتریوم (
EVM) که یک ماشین حالت تورینگ کامل (Turing-Complete) است، اجرا میگردد.
۲. ویژگیهای کلیدی زبان Solidity
سیستم تایپ ایستا (Statically Typed)
در Solidity نوع داده هر متغیر باید در زمان کامپایل مشخص باشد. این ویژگی به امنیت بیشتر و جلوگیری از خطاهای زمان اجرا (Runtime) کمک میکند.
قراردادمحوری (Contract-Oriented)
مفهوم Contract در این زبان مشابه Class در زبانهای شیءگرا مانند C# یا C++ است. قراردادها میتوانند شامل متغیرهای حالت (State Variables)، توابع (Functions)، رویدادها (Events) و اصلاحکنندهها (Modifiers) باشند و از ارثبری چندگانه (Multiple Inheritance) پشتیبانی میکنند.
مدیریت گاز (Gas Control)
هر دستورالعمل در EVM هزینه اجرایی مشخصی دارد که با واحد Gas اندازهگیری میشود. توسعهدهنده Solidity باید کد خود را به گونهای بنویسد که کمترین میزان مصرف Gas را داشته باشد تا هزینه تراکنش کاربران کاهش یابد.
۳. بررسی ساختار و سینتکس Solidity
یک فایل ساده Solidity معمولاً ساختاری به شکل زیر دارد:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract SimpleStorage {
uint256 private storedData;
event DataChanged(address indexed user, uint256 newValue);
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not the contract owner");
_;
}
constructor() {
owner = msg.sender;
}
function set(uint256 x) public onlyOwner {
storedData = x;
emit DataChanged(msg.sender, x);
}
function get() public view returns (uint256) {
return storedData;
}
}
اجزای اصلی کد بالا:
SPDX-License-Identifier: مشخص کردن لایسنس کد برای شفافیت و کپیرایت.pragma solidity: تعیین نسخه کامپایلر سازگار با کد.State Variables: متغیرهایی که دادهها را بهطور دائم در ذخیرهساز بلاکچین (Storage) نگه میدارند.Functions: بلوکهای اجرایی کد که میتوانند وضعیت شبکه را تغییر دهند یا صرفاً آن را بخوانند.Modifiers: برای تغییر رفتار توابع.Events: ساختاری برای نوشتن لاگ در بلاکچین.
۴. انواع متغیرها و مدیریت حافظه
در Solidity دادهها بر اساس محل ذخیرهسازی و نوع دسترسی دستهبندی میشوند:
انواع دادههای پایه (Value Types)
uint/int: اعداد صحیح.address: نماینده یک حساب کاربری یا قرارداد.bool: مقادیر منطقی.bytes: آرایهای از بایتها.
نواحی حافظه (Data Locations)
storage: دادههای دائمی روی بلاکچین (هزینه بالا).memory: حافظه موقت و ارزان.calldata: حافظه غیرقابل تغییر و موقت برای آرگومانهای ورودی (بهینهترین گزینه).
۵. امنیت در Solidity (آسیبپذیریهای متداول)
امنیت در توسعه قراردادهای هوشمند حیاتی است.
۱. حمله بازگشتی (Reentrancy Attack)
زمانی رخ میدهد که یک قرارداد قبل از بروزرسانی وضعیت، اقدام به ارسال وجه به قرارداد دیگری کند.
- راه حل: استفاده از الگوی Checks-Effects-Interactions یا کتابخانه
ReentrancyGuard.
۲. سرریز محاسباتی (Integer Overflow / Underflow)
در نسخههای قبل از 0.8.0 متغیرها دچار سرریز میشدند.
- راه حل: استفاده از نسخه
0.8.0به بعد که بهصورت خودکار خطاها را هندل میکند.
۳. وابستگی به زمان بلاک
استفاده از block.timestamp برای منطقهای حساس به دلیل امکان دستکاری توسط ولیدیتورها ناامن است.
۶. بهینهسازی گاز (Gas Optimization Techniques)
- Variable Packing: چیدمان متغیرهای کوچک در کنار هم برای اشغال یک اسلات ۳۲ بایتی.
unchecked: حذف بررسی سرریز برای محاسبات امن جهت کاهش هزینه.externalvspublic: استفاده ازexternalبرای کاهش هزینه کپی دادهها.constant/immutable: استفاده از این کلمات کلیدی برای دادههای ثابت.
۷. اکوسیستم و ابزارهای توسعه
Hardhat: محیط توسعه قدرتمند مبتنی بر Node.js.Foundry: فریمورک سریع مبتنی بر Rust با قابلیت تستنویسی با خودِ Solidity.Remix IDE: محیط وب برای تستهای سریع.OpenZeppelin: مرجع استانداردهای امن (ERC-20, ERC-721).
دیدگاه کاربران