لغات العقود الذكية
من الجوانب الرائعة في إيثيريوم أنه يمكن برمجة العقود الذكية باستخدام لغات صديقة للمطورين نسبيًا. إذا كانت لديك خبرة في لغة Python أو أي لغة تستخدم الأقواس المعقوفة (opens in a new tab)، فيمكنك العثور على لغة ذات بنية مألوفة.
اللغتان الأكثر نشاطًا وصيانة هما:
- Solidity
- Vyper
توفر بيئة التطوير المتكاملة Remix بيئة تطوير شاملة لإنشاء واختبار العقود في كل من Solidity وVyper. جرب بيئة التطوير المتكاملة Remix في المتصفح (opens in a new tab) لبدء البرمجة.
قد يرغب المطورون الأكثر خبرة أيضًا في استخدام Yul، وهي لغة وسيطة لـ آلة إيثيريوم الافتراضية (EVM)، أو Yul+، وهي امتداد للغة Yul.
إذا كنت فضوليًا وترغب في المساعدة في اختبار لغات جديدة لا تزال قيد التطوير المكثف، فيمكنك تجربة Fe، وهي لغة عقود ذكية ناشئة لا تزال حاليًا في مهدها.
المتطلبات الأساسية
يمكن أن تساعدك المعرفة السابقة بلغات البرمجة، وخاصة JavaScript أو Python، في فهم الاختلافات في لغات العقود الذكية. نوصي أيضًا بفهم العقود الذكية كمفهوم قبل التعمق في مقارنات اللغات. مقدمة عن العقود الذكية.
Solidity
- لغة عالية المستوى وموجهة للكائنات لتنفيذ العقود الذكية.
- لغة تستخدم الأقواس المعقوفة وتأثرت بشدة بلغة C++.
- مكتوبة بشكل ثابت (يُعرف نوع المتغير في وقت الترجمة).
- تدعم:
- الوراثة (يمكنك توسيع عقود أخرى).
- المكتبات (يمكنك إنشاء كود قابل لإعادة الاستخدام يمكنك استدعاؤه من عقود مختلفة – مثل الدوال الثابتة في فئة ثابتة في لغات البرمجة الموجهة للكائنات الأخرى).
- أنواع معقدة يحددها المستخدم.
روابط مهمة
- التوثيق (opens in a new tab)
- بوابة لغة Solidity (opens in a new tab)
- Solidity بالأمثلة (opens in a new tab)
- GitHub (opens in a new tab)
- غرفة دردشة Solidity على Gitter (opens in a new tab) متصلة بـ غرفة دردشة Solidity على Matrix (opens in a new tab)
- ورقة مرجعية (Cheat Sheet) (opens in a new tab)
- مدونة Solidity (opens in a new tab)
- تويتر Solidity (opens in a new tab)
مثال على عقد
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.7.0;
contract Coin {
// تجعل الكلمة المفتاحية "public" المتغيرات
// قابلة للوصول من عقود أخرى
address public minter;
mapping (address => uint) public balances;
// تسمح الأحداث للعملاء بالتفاعل مع
// تغييرات محددة في العقد تعلن عنها
event Sent(address from, address to, uint amount);
// يتم تشغيل كود المُنشئ فقط عندما
// يتم إنشاء العقد
constructor() {
minter = msg.sender;
}
// يرسل كمية من العملات المنشأة حديثًا إلى عنوان
// يمكن استدعاؤه فقط من قبل منشئ العقد
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
// يرسل كمية من العملات الحالية
// من أي متصل إلى عنوان
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
يجب أن يمنحك هذا المثال فكرة عن شكل بنية عقد Solidity. للحصول على وصف أكثر تفصيلاً للدوال والمتغيرات، راجع التوثيق (opens in a new tab).
Vyper
- لغة برمجة مبنية على أسلوب Python
- كتابة قوية (Strong typing)
- كود مترجم (compiler) صغير ومفهوم
- توليد فعال لرمز البايت
- تحتوي عمدًا على ميزات أقل من Solidity بهدف جعل العقود أكثر أمانًا وأسهل في التدقيق. لا تدعم Vyper:
- المُعدِّلات (Modifiers)
- الوراثة
- لغة التجميع المضمنة (Inline assembly)
- التحميل الزائد للدوال (Function overloading)
- التحميل الزائد للعوامل (Operator overloading)
- الاستدعاء العودي (Recursive calling)
- الحلقات اللانهائية
- النقاط الثابتة الثنائية (Binary fixed points)
لمزيد من المعلومات، اقرأ الأساس المنطقي لـ Vyper (opens in a new tab).
روابط مهمة
- التوثيق (opens in a new tab)
- Vyper بالأمثلة (opens in a new tab)
- المزيد من Vyper بالأمثلة (opens in a new tab)
- GitHub (opens in a new tab)
- دردشة مجتمع Vyper على ديسكورد (opens in a new tab)
- ورقة مرجعية (Cheat Sheet) (opens in a new tab)
- أطر عمل وأدوات تطوير العقود الذكية لـ Vyper
- VyperPunk - تعلم كيفية تأمين واختراق العقود الذكية المكتوبة بـ Vyper (opens in a new tab)
- مركز Vyper للتطوير (opens in a new tab)
- أفضل أمثلة العقود الذكية المكتوبة بـ Vyper (opens in a new tab)
- موارد رائعة ومنسقة لـ Vyper (opens in a new tab)
مثال
# مزاد مفتوح
# معلمات المزاد
# يتلقى المستفيد الأموال من صاحب أعلى عطاء
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)
# الحالة الحالية للمزاد
highestBidder: public(address)
highestBid: public(uint256)
# يتم تعيينه إلى true في النهاية، ويمنع أي تغيير
ended: public(bool)
# تتبع العطاءات المستردة حتى نتمكن من اتباع نمط السحب
pendingReturns: public(HashMap[address, uint256])
# إنشاء مزاد بسيط بوقت مزايدة `_bidding_time`
# ثانية نيابة عن
# عنوان المستفيد `_beneficiary`.
@external
def __init__(_beneficiary: address, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = block.timestamp
self.auctionEnd = self.auctionStart + _bidding_time
# المزايدة في المزاد بالقيمة المرسلة
# مع هذه المعاملة.
# سيتم استرداد القيمة فقط إذا
# لم يتم الفوز بالمزاد.
@external
@payable
def bid():
# تحقق مما إذا كانت فترة المزايدة قد انتهت.
assert block.timestamp < self.auctionEnd
# تحقق مما إذا كان العطاء مرتفعًا بما يكفي
assert msg.value > self.highestBid
# تتبع الاسترداد لصاحب أعلى عطاء سابق
self.pendingReturns[self.highestBidder] += self.highestBid
# تتبع أعلى عطاء جديد
self.highestBidder = msg.sender
self.highestBid = msg.value
# سحب عطاء تم استرداده مسبقًا. يُستخدم نمط السحب
# هنا لتجنب مشكلة أمنية. إذا تم إرسال المبالغ المستردة مباشرة
# كجزء من bid()، يمكن لعقد مزايدة خبيث حظر
# تلك المبالغ المستردة وبالتالي منع دخول عطاءات جديدة أعلى.
@external
def withdraw():
pending_amount: uint256 = self.pendingReturns[msg.sender]
self.pendingReturns[msg.sender] = 0
send(msg.sender, pending_amount)
# إنهاء المزاد وإرسال أعلى عطاء
# إلى المستفيد.
@external
def endAuction():
# من الإرشادات الجيدة هيكلة الدوال التي تتفاعل
# مع عقود أخرى (أي أنها تستدعي دوال أو ترسل إيثر)
# إلى ثلاث مراحل:
# 1. التحقق من الشروط
# 2. تنفيذ الإجراءات (والتي قد تغير الشروط)
# 3. التفاعل مع عقود أخرى
# إذا تم خلط هذه المراحل، يمكن للعقد الآخر معاودة الاتصال
# بالعقد الحالي وتعديل الحالة أو التسبب في
# تنفيذ التأثيرات (دفع الإيثر) عدة مرات.
# إذا كانت الدوال المستدعاة داخليًا تتضمن تفاعلًا مع عقود
# خارجية، فيجب اعتبارها أيضًا تفاعلًا مع
# عقود خارجية.
# 1. الشروط
# تحقق مما إذا كان قد تم الوصول إلى وقت نهاية المزاد
assert block.timestamp >= self.auctionEnd
# تحقق مما إذا كانت هذه الدالة قد تم استدعاؤها بالفعل
assert not self.ended
# 2. التأثيرات
self.ended = True
# 3. التفاعل
send(self.beneficiary, self.highestBid)
يجب أن يمنحك هذا المثال فكرة عن شكل بنية عقد Vyper. للحصول على وصف أكثر تفصيلاً للدوال والمتغيرات، راجع التوثيق (opens in a new tab).
Yul وYul+
إذا كنت جديدًا على إيثيريوم ولم تقم بأي برمجة باستخدام لغات العقود الذكية بعد، فنوصيك بالبدء باستخدام Solidity أو Vyper. لا تنظر في Yul أو Yul+ إلا بعد أن تكون على دراية بأفضل ممارسات أمان العقود الذكية وتفاصيل العمل مع آلة إيثيريوم الافتراضية (EVM).
Yul
- لغة وسيطة لإيثيريوم.
- تدعم آلة إيثيريوم الافتراضية (EVM) وEwasm (opens in a new tab)، وهي نسخة من WebAssembly مخصصة لإيثيريوم، ومصممة لتكون قاسمًا مشتركًا قابلاً للاستخدام لكلا المنصتين.
- هدف جيد لمراحل التحسين عالية المستوى التي يمكن أن تفيد منصتي EVM وEwasm على حد سواء.
Yul+
- امتداد منخفض المستوى وعالي الكفاءة للغة Yul.
- صُممت في البداية لعقد رول أب متفائل.
- يمكن النظر إلى Yul+ على أنها مقترح ترقية تجريبي للغة Yul، حيث تضيف ميزات جديدة إليها.
روابط مهمة
- توثيق Yul (opens in a new tab)
- توثيق Yul+ (opens in a new tab)
- منشور تعريفي عن Yul+ (opens in a new tab)
مثال على عقد
ينفذ المثال البسيط التالي دالة القوة (الأس). يمكن تجميعه باستخدام solc --strict-assembly --bin input.yul. يجب تخزين المثال في ملف input.yul.
{
function power(base, exponent) -> result
{
switch exponent
case 0 { result := 1 }
case 1 { result := base }
default
{
result := power(mul(base, base), div(exponent, 2))
if mod(exponent, 2) { result := mul(base, result) }
}
}
let res := power(calldataload(0), calldataload(32))
mstore(0, res)
return(0, 32)
}
إذا كنت تتمتع بخبرة جيدة بالفعل في العقود الذكية، فيمكن العثور على تنفيذ كامل لـ ERC-20 بلغة Yul هنا (opens in a new tab).
Fe
- لغة مكتوبة بشكل ثابت لآلة إيثيريوم الافتراضية (EVM).
- مستوحاة من Python وRust.
- تهدف إلى أن تكون سهلة التعلم -- حتى للمطورين الجدد في نظام إيثيريوم البيئي.
- لا يزال تطوير Fe في مراحله الأولى، وقد تم إصدار النسخة الأولية (alpha) من اللغة في يناير 2021.
روابط مهمة
- GitHub (opens in a new tab)
- إعلان Fe (opens in a new tab)
- خارطة طريق Fe لعام 2021 (opens in a new tab)
- دردشة Fe على ديسكورد (opens in a new tab)
- تويتر Fe (opens in a new tab)
مثال على عقد
فيما يلي عقد بسيط تم تنفيذه بلغة Fe.
type BookMsg = bytes[100]
contract GuestBook:
pub guest_book: map<address, BookMsg>
event Signed:
book_msg: BookMsg
pub def sign(book_msg: BookMsg):
self.guest_book[msg.sender] = book_msg
emit Signed(book_msg=book_msg)
pub def get_msg(addr: address) -> BookMsg:
return self.guest_book[addr].to_mem()
كيفية الاختيار
كما هو الحال مع أي لغة برمجة أخرى، يتعلق الأمر في الغالب باختيار الأداة المناسبة للمهمة المناسبة بالإضافة إلى التفضيلات الشخصية.
إليك بعض الأشياء التي يجب مراعاتها إذا لم تجرب أيًا من اللغات بعد:
ما الرائع في Solidity؟
- إذا كنت مبتدئًا، فهناك العديد من البرامج التعليمية وأدوات التعلم المتاحة. تعرف على المزيد حول ذلك في قسم التعلم من خلال البرمجة.
- تتوفر أدوات تطوير جيدة.
- تمتلك Solidity مجتمع مطورين كبير، مما يعني أنك ستجد على الأرجح إجابات لأسئلتك بسرعة كبيرة.
ما الرائع في Vyper؟
- طريقة رائعة للبدء لمطوري Python الذين يرغبون في كتابة العقود الذكية.
- تحتوي Vyper على عدد أقل من الميزات مما يجعلها رائعة للنماذج الأولية السريعة للأفكار.
- تهدف Vyper إلى أن تكون سهلة التدقيق وقابلة للقراءة من قبل البشر إلى أقصى حد.
ما الرائع في Yul وYul+؟
- لغة منخفضة المستوى مبسطة ووظيفية.
- تتيح الاقتراب أكثر من آلة إيثيريوم الافتراضية (EVM) الخام، مما يمكن أن يساعد في تحسين استخدام الغاز في عقودك.
مقارنات اللغات
لمقارنات البنية الأساسية، ودورة حياة العقد، والواجهات، والعوامل، وهياكل البيانات، والدوال، وتدفق التحكم، والمزيد، تحقق من الورقة المرجعية هذه بواسطة Auditless (opens in a new tab)