Solidity چیست؟ آموزش کامل و جامع Solidity
فهرست مطالب
Solidity چیست؟
Solidity یک زبان برنامهنویسی قرارداد-محور، شیءگرا و سطح بالا است که برای پیادهسازی قراردادهای هوشمند روی پلتفرم Ethereum طراحی شده است. این زبان تحت تأثیر C++، Python و JavaScript بوده و برای ماشین مجازی اتریوم (EVM) طراحی شده است.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract HelloWorld {
string public message;
constructor() {
message = "سلام دنیا!";
}
function setMessage(string memory newMessage) public {
message = newMessage;
}
}
تاریخچه Solidity
Solidity در سال 2014 توسط Gavin Wood معرفی شد و از آن زمان به عنوان زبان اصلی توسعه قراردادهای هوشمند در اکوسیستم اتریوم شناخته میشود.
ساختار پایه Solidity
هر فایل Solidity از چندین بخش اصلی تشکیل شده است که درک آنها برای برنامهنویسی قراردادهای هوشمند ضروری است.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// وارد کردن سایر قراردادها
import "./OtherContract.sol";
// تعریف interface
interface IMyInterface {
function myFunction() external returns (uint256);
}
// تعریف قرارداد
contract MyContract {
// متغیرهای حالت
uint256 public myVariable;
// ساختارها
struct MyStruct {
string name;
uint256 value;
}
// رویدادها
event MyEvent(address indexed sender, uint256 value);
// سازنده
constructor() {
myVariable = 0;
}
// توابع
function setValue(uint256 _value) public {
myVariable = _value;
emit MyEvent(msg.sender, _value);
}
}
اجزای اصلی Solidity
متغیرهای حالت
متغیرهای حالت در بلاکچین ذخیره میشوند و وضعیت قرارداد را نگهداری میکنند.
contract Variables {
// متغیرهای حالت
uint256 public stateVariable;
address public owner;
mapping(address => uint256) public balances;
function example() public {
// متغیرهای محلی
uint256 localVar = 100;
// متغیرهای جهانی
uint256 blockNumber = block.number;
address sender = msg.sender;
}
}
قراردادهای هوشمند در Solidity
قراردادهای هوشمند، برنامههای خودکاری هستند که در بلاکچین اجرا میشوند و میتوانند داراییهای دیجیتال را مدیریت کنند.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleToken {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
decimals = 18;
totalSupply = 1000000 * 10**uint256(decimals);
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool) {
require(balanceOf[msg.sender] >= _value, "Insufficient balance");
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
}
انواع داده در Solidity
Solidity انواع داده متنوعی را پشتیبانی میکند که برای کاربردهای مختلف مناسب هستند.
انواع اصلی داده
contract DataTypes {
// اعداد صحیح
uint256 public positiveNumber;
int256 public wholeNumber;
// آدرس
address public userAddress;
// بولین
bool public isActive;
// رشته
string public text;
// بایت
bytes32 public data;
// آرایه
uint256[] public numbers;
// نگاشت
mapping(address => uint256) public balances;
// ساختار
struct User {
string name;
uint256 balance;
bool isActive;
}
}
توابع در Solidity
توابع، بلوکهای اصلی ساخت منطق قراردادهای هوشمند هستند.
contract Functions {
// تابع view
function getValue() public view returns (uint256) {
return storageVar;
}
// تابع pure
function calculate(uint256 x, uint256 y) public pure returns (uint256) {
return x + y;
}
// تابع payable
function deposit() public payable {
// دریافت اتر
}
// تابع private
function _internalOperation() private {
// عملیات داخلی
}
// modifier
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
}
وراثت و چندریختی
Solidity از وراثت چندگانه پشتیبانی میکند و امکان استفاده مجدد از کد را فراهم میکند.
// قرارداد پایه
contract Ownable {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
}
// قرارداد مشتق شده
contract MyToken is Ownable {
mapping(address => uint256) public balances;
function mint(address to, uint256 amount) public onlyOwner {
balances[to] += amount;
}
}
رویدادها و لاگها
رویدادها برای ثبت اتفاقات مهم در بلاکچین و اطلاعرسانی به برنامههای خارجی استفاده میشوند.
contract Events {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
mapping(address => uint256) public balances;
function transfer(address to, uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
}
}
بهترین شیوههای کدنویسی Solidity
رعایت اصول و بهترین شیوههای کدنویسی برای توسعه قراردادهای امن و کارآمد ضروری است:
۱. امنیت
– استفاده از الگوهای امنیتی استاندارد
– انجام تستهای جامع
– حسابرسی کد قبل از استقرار
۲. بهینهسازی گس
– کاهش تعداد عملیات ذخیرهسازی
– استفاده از متغیرهای memory به جای storage در صورت امکان
۳. خوانایی کد
– مستندسازی مناسب با نظرات NatSpec
– نامگذاری معنادار متغیرها و توابع
امنیت در Solidity
امنیت در قراردادهای هوشمند بسیار حیاتی است و باید به نکات زیر توجه ویژه شود:
contract SecureContract {
// جلوگیری از حمله reentrancy
mapping(address => uint256) private balances;
bool private locked;
modifier noReentrant() {
require(!locked, "Reentrant call");
locked = true;
_;
locked = false;
}
function withdraw() public noReentrant {
uint256 amount = balances[msg.sender];
require(amount > 0, "No balance");
balances[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
ابزارهای توسعه Solidity
محیطهای توسعه
– Remix IDE
– Truffle Suite
– Hardhat
– Visual Studio Code با افزونه Solidity
فریمورکهای تست
– Mocha
– Waffle
– Brownie
– OpenZeppelin Test Helpers
ابزارهای امنیتی
– Mythril
– Slither
– Echidna
– MythX
const { expect } = require("chai");
describe("Token", function() {
it("Should return the correct total supply", async function() {
const Token = await ethers.getContractFactory("Token");
const token = await Token.deploy();
await token.deployed();
const totalSupply = await token.totalSupply();
expect(totalSupply).to.equal(1000000);
});
});
استقرار و تعامل با قراردادهای هوشمند
پس از توسعه قرارداد هوشمند، باید آن را روی شبکه بلاکچین مستقر کرد.
async function main() {
const Token = await ethers.getContractFactory("Token");
console.log("Deploying Token...");
const token = await Token.deploy();
await token.deployed();
console.log("Token deployed to:", token.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
اکوسیستم Solidity و Web3
Solidity بخشی از اکوسیستم گسترده Web3 است که شامل موارد زیر میشود:
کتابخانههای پرکاربرد
- OpenZeppelin Contracts
- Chainlink Oracles
- Uniswap Libraries
تعامل با قراردادها
const Web3 = require('web3');
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR-PROJECT-ID');
const contract = new web3.eth.Contract(ABI, contractAddress);
async function getBalance(address) {
const balance = await contract.methods.balanceOf(address).call();
console.log(`Balance: ${web3.utils.fromWei(balance, 'ether')} tokens`);
}