كيفية استخدام التشفير لإنشاء "منفعة عامة" دون المخاطرة للمستثمرين



في هذه المقالة ، سأتحدث عن ماهية عقد الضمان ، والمعروف أيضًا باسم آلية لتوفير الفوائد العامة والمجتمعية ، وسنقوم معًا بكتابة تنفيذ التمويل الجماعي الخاص بنا استنادًا إلى وكلاء الحكم الذاتي على منصة Obyte.

عقد الضمان عبارة عن آلية منظمة لجمع التبرعات لإنشاء منفعة عامة جديدة. قد يكون الموقف التالي مثالًا نموذجيًا على استخدام هذه العقود: قرر المشاركون في تعاونية صيفية بناء طريق للوصول بسهولة إلى منازلهم الصيفية. للقيام بذلك ، جمع المبلغ N ونقله إلى المقاول لبناء الطريق. تثور أسئلة كثيرة: من أين يمكن العثور على شخص يثق به الجميع ويشحن المجموعة ، وكيفية جعل جميع المستخدمين المحتملين للطريق يستثمرون في بنائه ، وماذا سيحدث إذا لم يكن هناك ما يكفي من الأموال التي تم جمعها ، إلخ.

إن عقود الضمان متشابهة جدًا في معنى التمويل الجماعي ، فالمستثمرون وحدهم لا يتعرضون للمخاطر ، كما هو الحال مع المستثمرين الذين يستثمرون في مؤسسات محفوفة بالمخاطر. يمكن أن يكون لهذه العقود ، وكذلك التمويل الجماعي ، نتيجتان - ناجحة وغير ناجحة ، اعتمادًا على تحقيق الهدف للمبلغ الذي تم جمعه. ستكون نتيجة المجموعة الناجحة هي استلام المستثمرين ، لكن في بعض الأحيان ليس فقط من جانبهم ، لسلعة عامة جديدة. في حالة الفشل ، يتم إرجاع الأموال ببساطة إلى المودعين.

لذلك ، بالنسبة للمبتدئين ، نكرر الشروط الأساسية. يتمثل جوهر التمويل الجماعي في جمع الأموال "في حشد" لهدف محدد مسبقًا ، مع مبلغ نهائي محدد (غير ثابت بالضرورة ، يمكن أن يكون ديناميكيًا) وتاريخ انتهاء (أيضًا ليس دائمًا ، ولكن عادةً). عندما يتم الوصول إلى هذا المبلغ ، تعتبر جولة التمويل ناجحة وتوقف التحصيل ، يتم تخصيص جميع الأموال لتحقيق الهدف. في حالة الفشل ، أي عند الوصول إلى الموعد النهائي وعدم كفاية الأموال التي يتم جمعها ، سيتم إعادة جميع الأموال إلى الجهات المانحة.

ما هي المشاكل التي يحلها التمويل الجماعي للعملة المشفرة؟ أولاً ، إنه يحفظ المستثمرين من الاضطرار إلى الثقة والتحقق من من يرسل أموالهم إليه. كود الوكيل المستقل لجمع التبرعات مفتوح ويمكن لكل مستثمر التأكد من أنه يمكن أن يسحب مساهمته في أي وقت حتى يتم الوصول إلى المبلغ النهائي ، وكذلك سيتم إرسال جميع الأموال إلى عنوان محدد مسبقًا لإنشاء السلعة. ثانياً ، تساعد المحاسبة الشفافة لجميع الأموال التي تم جمعها في توزيع الفوائد المستقبلية من تحقيق الهدف بما يتناسب مع المساهمة المقدمة.

المشكلة الأخرى التي يمكن حلها مع عقد الضمان هي مشكلة التنسيق. اليوم سنكمل مقالنا الأخير حول لعبة "الهجوم 51٪" ، وسنحل هذه المشكلة فقط. بدون استخدام AA ، سيكون المشاركون في اللعبة معرضين لخطر "نقص" المبلغ المحصل بسبب قلة التنسيق. عندئذ ، سيخسر أولئك الذين تمكنوا بالفعل من الاستثمار استثمار أموالهم ببساطة بسبب المشاركين الآخرين الذين لم يظهروا اهتمامًا ، أو ببساطة لم يتح لهم الوقت للقيام بذلك (تذكر أن الفرق المعارضة لديها 24 ساعة بالضبط لتحدي الزعيم الحالي). من خلال جمع الأموال من خلال عقد ضمان ، سيتمكن اللاعبون من سحب أموالهم في أي وقت حتى يتم جمع المبلغ اللازم.

لا ينطبق ذلك في حالتنا ، ولكن هناك ميزة أخرى مفيدة لهذه العقود وهي تقليل تأثير "تأثير المتسابق الحر" أو "مشكلة المتسابق الحر". نظرًا لأن الصالح العام ، سواء كان غير قابل للتحويل أو يصعب التحكم فيه ، فإن مشكلة المتسابق الحر هي المشكلة الرئيسية في تنظيم المنافع العامة. لا يرغب الناس في الاستثمار في شيء يمكن للآخرين استخدامه مجانًا ، أو من المرجح أن يكون المستثمر نفسه متمسكًا بالسلوك الاقتصادي العقلاني المطلق واختيار استراتيجية "غير مستثمرة" ، في حالة وجود مجموعة ناجحة ، قادرًا على استخدام الصالح الذي تم إنشاؤه.

سوف أتحدث أيضًا عن خيار عقد الضمان الأمثل ، مما يزيد من فرص النجاح في جمع الأموال سيكون السلوك العقلاني للمشاركين بالفعل اختيار استراتيجيات الاستثمار ، وليس التجاهل.

نحن نلعب اللعبة بشكل جماعي


على سبيل المثال ، سوف نأخذ لعبة "Attack 51٪" المعروفة بالفعل في المقالة الأخيرة.
في تنفيذها الحالي ، يرسل المشاركون في اللعبة الأموال إلى عنوان AA الخاص باللعبة. ولكن يمكن تحسين الخوارزمية وتقليل فرص خسارة المال من قبل المشاركين في حالة فقد فريقهم.
لهذا الغرض ، يمكن لأي عضو في الفريق تنظيم التمويل الجماعي مع هدف ديناميكي يساوي 51٪ على الأقل من إجمالي مجموعة اللعبة. مع نمو المسبح ، سيتحول هدف التمويل الجماعي النهائي أيضًا. وفقط إذا نجحت ، سيتم إرسال الأموال إلى عنوان AA الخاص باللعبة وسيصبح الفريق على الفور هو القائد الحالي. إذا لم يحدث مثل هذا الحدث أبدًا ، فلن يخسر المشاركون أموالهم ، مما يهدر مجموعة اللعبة دون جدوى ، ولكن ببساطة يأخذ المال من التمويل الجماعي AA.

تتوفر دائمًا نسخة أصلية من كلا الوكلاء المستقلين في محرر كود Oscript عبر الإنترنت في شكل قوالب ، ما عليك سوى تحديدهما من القائمة المنسدلة: "لعبة الهجوم بنسبة 51٪" و "وكيل جمع التبرعات".

قبل أن تبدأ في كتابة AA في Oscript ، أوصي بشدة بقراءة " دليل بدء الاستخدام" (eng) في وثائقنا للتعرف بسرعة على المبادئ الأساسية لكتابة AA.

كتابة رمز


أولاً ، نكتب الخوارزمية: يرسل المتبرع بايت إلى عنوان AA ، ويتلقى في المقابل رموزًا للتمويل الجماعي بنسبة 1 إلى 1. في أي وقت ، يمكنه استبدال هذه الرموز المميزة بالبايت. بعد استلام البايتات ، يتحقق AA من أننا قد وصلنا إلى هدف جمع الأموال ، وإذا كان الأمر كذلك ، فسوف يرسل جميع البايتات إلى عنوان AA للعبة ويستلم الرموز المميزة للعبة (رموز الفريق) في المقابل. يمكن للمتبرع الآن استبدال الرموز المميزة للتمويل الجماعي لرموز اللعبة ، والتي في المستقبل ، في حالة فوز الفريق ، يمكن استبدالها بالفعل بالبايت من خلال ألعاب AA ، حيث تتلقى ما يصل إلى x2 بايت من الألعاب الأصلية.

لذلك دعونا نبدأ.

وحدة معالجة البدء في فترة جمع التبرعات الجديدة. عند استلام حقل "البدء" في رسالة البيانات الواردة إلى عنوان AA الخاص بنا ، سنصدر رمز التمويل الجماعي الخاص بنا ونكتبه للحالة ، وسنعيده أيضًا كرد على المتصل.

{ // start a new fundraising period if: `{trigger.data.start AND !$asset}`, messages: [ { app: 'asset', payload: { is_private: false, is_transferrable: true, auto_destroy: false, fixed_denominations: false, issued_by_definer_only: true, cosigned_by_definer: false, spender_attested: false } }, { app: 'state', state: `{ var[response_unit || '_status'] = 'open'; var['asset'] = response_unit; response['asset'] = response_unit; }` } ] }, 

معالجة الودائع من الجهات المانحة. أولاً ، نقوم بتصفية المعاملات غير المرغوب فيها بكميات صغيرة جدًا ، والتي لا تكفي حتى بالنسبة للعمولة. بعد ذلك ، تحقق من الشروط الأساسية التي لم تكتمل بها اللعبة وأن التجميع ممكن. قائمة كتلة كاملة:

 { // contribute if: `{trigger.output[[asset=base]] >= 1e5 AND $asset}`, init: `{ if (var[$destination_aa]['finished']) bounce('game over'); $amount = trigger.output[[asset=base]] - 2000; // to account for fees we need to respond now and to refund bytes or pay shares later $total_raised = var['total_raised'] + $amount; $missing_amount = ceil((balance[$destination_aa][base] + $total_raised)*0.51) - var[$destination_aa]['team_' || $team || '_amount']; $bDone = ($total_raised > $missing_amount); }`, messages: [ { app: 'payment', payload: { asset: "{$asset}", outputs: [{address: "{trigger.address}", amount: "{$amount}"}] } }, { if: `{$bDone}`, app: 'payment', payload: { asset: "base", outputs: [{address: "{$destination_aa}", amount: "{$total_raised}"}] } }, { if: `{$bDone}`, app: 'data', payload: { team: "{$team}" } }, { app: 'state', state: `{ if ($bDone) var[$asset || '_status'] = 'raised'; else var['total_raised'] = $total_raised; }` } ] }, 

بعد الاختبارات الأولية مباشرة ، يذهب المنطق الرئيسي لـ AA:

$total_raised = var['total_raised'] + $amount; - هنا نلخص المبلغ الذي تلقيته للتو إلى إجمالي مبلغ الأموال على الوكيل.

$missing_amount = ceil((balance[$destination_aa][base] + $total_raised)*0.51) - var[$destination_aa]['team_' || $team || '_amount']; - تأكد من أن المبلغ الجديد الذي تم جمعه يكفي للفوز باللعبة. لاحظ المرجع إلى رصيد وحالة متغيرات AA الأخرى: balance[$destination_aa][base] و var[$destination_aa]['team_' || $team || '_amount'] var[$destination_aa]['team_' || $team || '_amount'] var[$destination_aa]['team_' || $team || '_amount'] .

نحن نفعل كل هذا في كتلة init ، والتي تسمى في كل مرة قبل معالجة رسائل المعاملات. من الواضح أن الإجابة على المعاملة الواردة ستكون إرسال رموز AA بمعدل واحد إلى واحد بالنسبة إلى وحدات البايت المستلمة (الكتلة الأولى من مجموعة الرسائل ). سيتم تنفيذ الكتل الثانية والثالثة فقط إذا تم تعيين المتغير المحلي $ bDone إلى صواب (تم تعيينه في كتلة init ). في نفوسهم ، سوف نرسل جميع الأموال من عنوان هذا AA إلى عنوان لعبة AA ، مع تلقي الرموز في مباراة العودة. في آخر مجموعة من الرسائل ، نقوم ببساطة بتحديث الحالة ، وتحديد الحالات اللازمة والمبلغ الذي تم جمعه.

معالجة الرموز التي تم استلامها من لعبة AA ، فهي تكمن بالفعل في رصيد AA لدينا ، نحتاج فقط إلى تغيير حالة الوكيل:

 { // received team asset if: `{trigger.output[[asset=var[$destination_aa]['team_' || $team || '_asset']]] AND $asset}`, messages: [ { app: 'state', state: `{ var[$asset || '_status'] = 'done'; var['asset'] = false; var['total_raised'] = false; }` } ] }, 

إعادة تخصيص الاستثمارات من قبل اللاعبين. نحن نسمح لك برفض المشاركة في أي وقت واستعادة وحدات البايت الخاصة بك. للقيام بذلك ، يرسل اللاعب الرموز المميزة لهذا AA ، ونرسل له نفس البايتات في معاملة الإرجاع:

 { // refund if: `{$asset AND trigger.output[[asset=$asset]] > 0}`, init: `{ $amount = trigger.output[[asset=$asset]]; }`, messages: [ { app: 'payment', payload: { asset: "base", outputs: [{address: "{trigger.address}", amount: "{$amount}"}] } }, { app: 'state', state: `{ var['total_raised'] -= $amount; }` } ] }, 

تبادل الرموز المميزة AA الخاصة بنا للحصول على الرموز المميزة للعبة. نحن ببساطة نرسل الرموز المميزة للعبة الموجودة على رصيد AA (في حالة تجاوز الكتلة if) بمبلغ يساوي عدد الرموز المميزة التي تلقيناها.

 { // pay the obtained team asset in exchange for the issued asset if: `{ $in_asset = trigger.output[[asset!=base]].asset; var[$in_asset || '_status'] == 'done' }`, messages: [ { app: 'payment', payload: { asset: "{var[$destination_aa]['team_' || $team || '_asset']}", outputs: [{address: "{trigger.address}", amount: "{trigger.output[[asset=$in_asset]]}"}] } }, ] } 

رمز الوكيل جاهز ، وهنا قائمة كاملة منه:

رمز الوكيل الكامل
 { /* This is a fundraising proxy AA. It allows to raise money up to a specific target. If the target is reached, the money is forwarded to another AA, otherwise the money is refunded. This specific example raises money for challenging the current candidate winner in 51% attack game. The target is a moving target as other teams may be adding contributions at the same time. Contributors get shares of the proxy in exchange for Bytes. They can exchange the shares back to the same amount of Bytes any time before the target is reached. As soon as the target is reached, the raised funds are forwarded to the game and the proxy receives the shares of the team in exchange. Then, the contributors can exchange the shares of the proxy for the shares of the team. */ init: `{ $asset = var['asset']; $destination_aa = 'WWHEN5NDHBI2UF4CLJ7LQ7VAW2QELMD7'; $team = 'VF5UVKDSOXPMITMDGYXEIGUJSQBRAMMN'; }`, messages: { cases: [ { // start a new fundraising period if: `{trigger.data.start AND !$asset}`, messages: [ { app: 'asset', payload: { is_private: false, is_transferrable: true, auto_destroy: false, fixed_denominations: false, issued_by_definer_only: true, cosigned_by_definer: false, spender_attested: false } }, { app: 'state', state: `{ var[response_unit || '_status'] = 'open'; var['asset'] = response_unit; response['asset'] = response_unit; }` } ] }, { // contribute if: `{trigger.output[[asset=base]] >= 1e5 AND $asset}`, init: `{ if (var[$destination_aa]['finished']) bounce('game over'); $amount = trigger.output[[asset=base]] - 2000; // to account for fees we need to respond now and to refund bytes or pay shares later $total_raised = var['total_raised'] + $amount; $missing_amount = ceil((balance[$destination_aa][base] + $total_raised)*0.51) - var[$destination_aa]['team_' || $team || '_amount']; $bDone = ($total_raised > $missing_amount); }`, messages: [ { app: 'payment', payload: { asset: "{$asset}", outputs: [{address: "{trigger.address}", amount: "{$amount}"}] } }, { if: `{$bDone}`, app: 'payment', payload: { asset: "base", outputs: [{address: "{$destination_aa}", amount: "{$total_raised}"}] } }, { if: `{$bDone}`, app: 'data', payload: { team: "{$team}" } }, { app: 'state', state: `{ if ($bDone) var[$asset || '_status'] = 'raised'; else var['total_raised'] = $total_raised; }` } ] }, { // received team asset if: `{trigger.output[[asset=var[$destination_aa]['team_' || $team || '_asset']]] AND $asset}`, messages: [ { app: 'state', state: `{ var[$asset || '_status'] = 'done'; var['asset'] = false; var['total_raised'] = false; }` } ] }, { // refund if: `{$asset AND trigger.output[[asset=$asset]] > 0}`, init: `{ $amount = trigger.output[[asset=$asset]]; }`, messages: [ { app: 'payment', payload: { asset: "base", outputs: [{address: "{trigger.address}", amount: "{$amount}"}] } }, { app: 'state', state: `{ var['total_raised'] -= $amount; }` } ] }, { // pay the obtained team asset in exchange for the issued asset if: `{ $in_asset = trigger.output[[asset!=base]].asset; var[$in_asset || '_status'] == 'done' }`, messages: [ { app: 'payment', payload: { asset: "{var[$destination_aa]['team_' || $team || '_asset']}", outputs: [{address: "{trigger.address}", amount: "{trigger.output[[asset=$in_asset]]}"}] } }, ] } ] } } 


لم ننفذ الخوارزمية الأكثر تافهة ، لأنه هدفنا ديناميكي ، وهو ليس نموذجيًا لعقد ضمان نموذجي. في نفوسهم ، في كثير من الأحيان يتم إصلاح المبلغ المستهدف ، وكذلك الموعد النهائي. لن يتطلب هذا تغييرات كبيرة في الشفرة ، لذلك دعونا نترك هذا بمثابة تمرين للقارئ.

أفضل إستراتيجية هي الاستثمار!


ونعود الآن إلى مشكلة رايدر مجانا. في حالة اللعبة ، ليس لدينا مشكلة من هذا القبيل ، لأن يمكن فقط لحاملي الرمز المميز للتمويل الجماعي الفوز. لكن حل مشكلة المتسابق الحر سيساعد في حالة اللعبة. يمكننا "تحفيز" الناس للاستثمار. للقيام بذلك ، يمكن لمنظم جمع التبرعات ، وهو أيضًا منشئ AA ، تقديم تعويض صغير ، سيدفعه من جيبه إذا لم يتحقق الغرض من المجموعة. في حالة المجموعة الناجحة ، سيأخذ المنظم نسبة مئوية صغيرة. أي أننا نقدم طرفًا ثالثًا ، من أجل الحصول على المزايا ، سيغطي مخاطر التجميع غير الناجح.

إن تطبيق مثل هذا "التمويل الجماعي الأمثل" ، فإن السلوك العقلاني السابق لـ "غير المستثمر" (بشكل عام ، لكي تكون أي سلعة عامة حرة) هو دائمًا الاستراتيجية الأكثر ربحية اقتصاديًا) قد يصبح أقل عقلانية من الاستثمار. قد يكون هذا مهمًا بشكل خاص في حالات إنشاء سلع جماعية تشارك فيها دائرة معينة من الأشخاص. هذا لا يلغي تماما مشكلة خلسة ، ولكن يجعل المشاركة سلوك عقلاني.

سيتم أيضًا ترك الكود الذي ينفذ "عقد الضمان الأمثل" كتمرين مثير للاهتمام لأولئك الذين يرغبون.

Source: https://habr.com/ru/post/ar475100/


All Articles