
مرحبا بالجميع!
في الجزء الأول ، درسنا بالتفصيل كيفية إنشاء والعمل مع dApp (تطبيق لامركزي) في Waves RIDE IDE .
دعنا نختبر مثالًا بسيطًا الآن .
المرحلة 3. اختبار حساب dApp

ما هي المشاكل التي تظهر على الفور مع حساب Alice dApp ؟
أولا:
يمكن لـ Boob and Cooper إرسال الأموال عن طريق الخطأ إلى dApp باستخدام معاملة تحويل عادية ، وبالتالي لن يكون بإمكانهما الوصول إليها.
ثانيا:
نحن لا نقيد سحب Alice للأموال دون موافقة Boob و / أو Cooper. منذ ذلك الحين ، انتبه للتحقق ، سيتم تنفيذ جميع المعاملات من Alice.
ثالثا:
يمكن لأي شخص إجراء أي عملية من حساب Alice ببساطة عن طريق استبدال publicKey في المعاملة:
const unsignedTransferTx = transfer({ amount: 1, recipient: '3P6fVra21KmTfWHBdib45iYV6aFduh4WwC2',
لسوء الحظ ، لا تسمح لك عقود Waves الذكية بحظر المعاملات الواردة في حسابك ، لذلك يتعين على Boob و Cooper التحكم في معاملاتهما الصادرة بأنفسهما.
دعونا إصلاح 2 و 3 عن طريق تعطيل Alice لجميع المعاملات باستثناء SetScriptTransaction ، تعطيل بقية عن طريق تحديد PublicKey لها فيVerifier. أي أننا سنسمح فقط لـ Alice كمطور dApp بتحديث / تصحيح عقد ذكي لفترة من الوقت.
نعم ، يمكن لـ Alice دائمًا تحديث البرنامج النصي للحصول على مزيد من الحقوق وإدارة أموال "المستخدمين" ، لكنها فقط يمكنها القيام بذلك وسيشاهد جميع المستخدمين لحظة التغييرات غير المصرح بها على العقد وسيكون بمقدورهم اتخاذ إجراء. ولكن طالما لم يتم حظر المعاملات بخلاف invokeScript ، فإن العملاء يحتاجون إلى الوثوق من جانب Alice.
نشر البرنامج النصي الذي تم تصحيحه:
@Verifier(tx) func verify() = { match tx { case d: SetScriptTransaction => sigVerify(tx.bodyBytes, tx.proofs[0], base58'x51ySWMyhE8G2AqJqmDpe3qoQM2aBwmieiJzZLK33JW') case _ => true }
نحن نحاول سحب العملات باستخدام dApp Alice وتوقيعها. حصلنا على الخطأ:

نحاول الانسحاب من خلال السحب:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))
البرنامج النصي يعمل ومع النقطة الثانية برزت!
المرحلة 4. نخلق DAO مع التصويت
لسوء الحظ ، لم توفر لغة RIDE حتى الآن إمكانية العمل مع المجموعات (القواميس ، القواميس ، التكرارات ، المخفضات ، إلخ). ومع ذلك ، بالنسبة لأي عمليات مع مجموعات قيمة مفتاح مسطح ، يمكننا تصميم نظام للعمل مع سلاسل ، على التوالي ، مع مفاتيح وفك التشفير.
السلاسل سهلة للغاية ؛ يمكن فصل السلاسل حسب الفهرس.
لدينا كل ما تحتاجه لكتابة منطق DAO dApp معقدة!
معاملات البياناتمعاملات البيانات:
"الحد الأقصى لحجم المفتاح هو 100 حرفًا ، ويمكن أن يحتوي المفتاح على نقاط رمز Unicode عشوائية بما في ذلك المسافات وغيرها من الرموز غير القابلة للطباعة. تحتوي قيم السلسلة على 32،768 بايت والحد الأقصى لعدد الإدخالات المحتملة في معاملة البيانات 100. بشكل عام ، يبلغ الحد الأقصى لحجم معاملة البيانات حوالي 140 كيلو بايت - للإشارة ، بالضبط طول مسرحية شكسبير تقريبًا "روميو وجولييت". "
إنشاء DAO بالشروط التالية:
من أجل الحصول على تمويل لبدء التشغيل ، يتطلب استدعاء getFunds () دعم مشاركين على الأقل - مستثمرو DAO. سيكون من الممكن السحب تمامًا مثل المبلغ الإجمالي الذي أشار إليه مالكو DAO.
دعنا نجعل 3 أنواع من المفاتيح ونضيف منطقًا للعمل مع الأرصدة في وظيفتين جديدتين ، قم بالتصويت و getFunds:
xx ... xx _ia = المستثمرين ، الرصيد المتاح (التصويت ، الإيداع ، السحب)
xx ... xx _sv = بدء التشغيل ، عدد الأصوات (التصويت ، getFunds)
xx ... xx _sf = بدء التشغيل ، عدد الأصوات (التصويت ، getFunds)
xx ... xx = العنوان العام (35 حرفًا)
لاحظ في التصويت أننا بحاجة إلى تحديث عدة حقول في وقت واحد:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),
WriteSet يسمح لنا بعمل عدة سجلات مرة واحدة في معاملة invokeScript واحدة.
هذه هي الطريقة التي يظهر بها في وحدة التخزين ذات القيمة الرئيسية DAO dApp ، بعد أن قام بوب وكوبر بتجديد الودائع:

لقد تغيرت وظيفة الإيداع قليلاً:

الآن تأتي اللحظة الأكثر أهمية في أنشطة DAO - التصويت لمشاريع التمويل.
Bob Votes for Neli's 500،000 Wavelets Project:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
رمز وظيفة التصويت:
@Callable(i) func vote(amount: Int, address: String) = { let currentKey = toBase58String(i.caller.bytes) let xxxInvestorBalance = currentKey + "_" + "ib" let xxxStartupFund = address + "_" + "sf" let xxxStartupVotes = address + "_" + "sv" let flagKey = address + "_" + currentKey let flag = match getInteger(this, flagKey) { case a:Int => a case _ => 0 } let currentAmount = match getInteger(this, xxxInvestorBalance) { case a:Int => a case _ => 0 } let currentVotes = match getInteger(this, xxxStartupVotes) { case a:Int => a case _ => 0 } let currentFund = match getInteger(this, xxxStartupFund) { case a:Int => a case _ => 0 } if (amount <= 0) then throw("Can't withdraw negative amount") else if (amount > currentAmount) then throw("Not enough balance!") else if (flag > 0) then throw("Only one vote per project is possible!") else WriteSet([ DataEntry(xxxInvestorBalance, currentAmount - amount), DataEntry(xxxStartupVotes, currentVotes + 1), DataEntry(flagKey, 1), DataEntry(xxxStartupFund, currentFund + amount) ]) }
في مستودع البيانات ، نرى جميع الإدخالات اللازمة لعنوان Neli:

كما صوت كوبر لصالح مشروع نيلي.

دعونا نلقي نظرة على رمز وظيفة getFunds . يجب على Neli جمع ما لا يقل عن صوتين حتى تتمكن من سحب الأموال من DAO.

ستقوم نيلي بسحب نصف المبلغ المنوط بها:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))

انها تنجح ، وهذا هو ، يعمل DAO!
نظرنا في عملية إنشاء DAO بلغة RIDE4DAPPS .
في الأجزاء التالية ، سنتعامل بمزيد من التفصيل مع إعادة تنظيم الأكواد واختبار الحالات.
النسخة الكاملة من الكود في Waves RIDE IDE:
# In this example multiple accounts can deposit their funds to DAO and safely take them back, no one can interfere with this. # DAO participants can also vote for particular addresses and let them withdraw invested funds then quorum has reached. # An inner state is maintained as mapping `address=>waves`. # https:
الجزء الاول
كود جيثب
موجات ركوب IDE
إعلان برنامج المنحة