اعتمد Sputnik-DAO نمط تصميم المصنع الإنشائي لتحقيق إنشاء وإدارة موحدة لمنظمة (DAO) اللامركزية على المنصة.
ستتناول هذه المقالة التصميم والتنفيذ لنموذج المصنع في منصة Sputnik-DAO (sputnikdao-factory).
مستودع كود المصدر للعقد المقابل يقع في:
!
2. مقدمة عن وظائف وحدة DAPP
لقد أنشأت العديد من المنظمات المستقلة اللامركزية على صفحة DAPP الخاصة بمنصة Sputnik DAO وقامت بتخصيص كائنات DAO الخاصة بها ( وعقد ) Sputnikdaov2.
حتى مارس 2022، كانت أكثر DAO نشاطاً تم إنشاؤها على هذه المنصة هي news.sputnik-dao.near، حيث يوجد حالياً 3051 اقتراحاً (proposals) قيد التصويت العام أو الحالة قد انتهت.
من خلال استكشاف NEAR Explorer، يمكن أن نكتشف أن عقود كل مثيل DAO على المنصة تم نشرها بشكل موحد بواسطة حساب NEAR sputnik-dao.near( وعقد sputnikdao-factory).
أي أن جميع عقود مثيل الـ DAO التي تم إنشاؤها على منصة Sputnik DAO يتم نشرها بشكل منفصل تحت الحسابات الفرعية لحساب NEAR هذا، على سبيل المثال:
pcp.sputnik-dao.near
test-dao-bro.sputnik-dao.near
blaqkstereo.sputnik-dao.near
Octopode-dao.sputnik-dao.near
يمكن للمنظمات اللامركزية بدء المعاملات علنًا في شبكة NEAR الرئيسية عن طريق استدعاء طريقة create() التي يوفرها عقد sputnikdao-factory، لإنشاء مثيل جديد من DAO.
!
3. تفسير كود عقد الساتينكداو-فابريك
3.1 إنشاء DAO
حالة عقد sputnikdao-factory تتكون أساسًا من جزئين رئيسيين:
صدأ
/// يحاول تحديث الحساب المعطى الذي أنشأته هذه المصنع إلى الرمز المحدد.
pub fn update(& self, account_id: AccountId, code_hash: Base58CryptoHash) {
دع caller_id = env::p redecessor_account_id();
أكد!(
caller_id == self.get_owner() || caller_id == account_id ،
'يجب أن يتم تحديثه بواسطة مالك المصنع أو DAO نفسه'
);
أكد!(
self.daos.contains(&account_id) ،
'يجب أن يكون العقد الذي أنشأته المصنع'
);
self.factory_manager
.update_contract(account_id ، code_hash ، "تحديث" ) ؛
}
صدأ
/// يجبر التحديث على العقد المعطى.
/// يجب أن يدعم العقد التحديث بواسطة المصنع من خلال التحقق من الأذونات.
حانة FN update_contract(
والذات،
account_id: AccountId ،
code_hash: Base58CryptoHash ،
method_name: &str ،
) {
دع code_hash: CryptoHash = code_hash.into();
let account_id = account_id.as_bytes().to_vec();
غير آمن {
// تأكد من أن مثل هذا العقد موجود.
assert!(env::storage_has_key(&code_hash), 'العقد غير موجود');
// تحميل التجزئة من التخزين.
sys::storage_read(code_hash.len() ك _ ، code_hash.as_ptr() ك _ ، 0);
// أنشئ وعدًا تجاه الحساب المعطى.
دع promise_id =
sys::p romise_batch_create(account_id.len() ك , account_id.as_ptr() ك _ );
// استدعاء طريقة التحديث، التي يجب أن تتعامل أيضًا مع الهجرات.
sys::p romise_batch_action_function_call(
promise_id،
method_name.len() ك _ ،
method_name.as_ptr() ك _ ،
u64 :: ماكس ك _ ،
0,
&NO_DEPOSIT مثل * const u128 ك _ ،
(env::p repaid_gas() - env::used_gas() - GAS_UPDATE LEFTOVER).0,);
sys::p romise_return(promise_id);
}
}
!
4. تحليل أمان عقد مصنع Sputnik-DAO
تتم ضمانة أمان عقد مصنع Sputnik-DAO من عدة جوانب كما يلي:
التحكم في الأذونات: يجب ألا تعدل طرق العرض المفتوحة في العقد متغيرات حالة العقد، أي يجب تعيين المعامل الأول في تعريف الطريقة إلى &self، وليس &mut self.
التحكم في الأذونات: الوظائف المميزة المفتوحة للعقد، هذه الوظائف يمكن تنفيذها فقط من قبل مالك العقد ( أو حساب عقد DAO )، ويوجد في الطريقة تأكيدات مناسبة.
معالجة الأخطاء: لقد نفذ عقد مصنع Sputnik-DAO آلية معالجة أخطاء معقولة لجميع الحالات الاستثنائية المحتملة. على سبيل المثال، سيقوم عقد المصنع بالتحقق من أن جميع خطوات إنشاء عقد DAO جديد قد تم تنفيذها بشكل صحيح وكامل، وإلا فلن يتسبب ذلك في خسارة للمستخدم.
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
تحليل عقد مصنع Sputnik DAO: الآلية الأساسية لإنشاء وتحديث DAO
تفسير عقد مصنع Sputnik DAO
1. عقد مصنع Sputnik-DAO
اعتمد Sputnik-DAO نمط تصميم المصنع الإنشائي لتحقيق إنشاء وإدارة موحدة لمنظمة (DAO) اللامركزية على المنصة.
ستتناول هذه المقالة التصميم والتنفيذ لنموذج المصنع في منصة Sputnik-DAO (sputnikdao-factory).
مستودع كود المصدر للعقد المقابل يقع في:
!
2. مقدمة عن وظائف وحدة DAPP
لقد أنشأت العديد من المنظمات المستقلة اللامركزية على صفحة DAPP الخاصة بمنصة Sputnik DAO وقامت بتخصيص كائنات DAO الخاصة بها ( وعقد ) Sputnikdaov2.
حتى مارس 2022، كانت أكثر DAO نشاطاً تم إنشاؤها على هذه المنصة هي news.sputnik-dao.near، حيث يوجد حالياً 3051 اقتراحاً (proposals) قيد التصويت العام أو الحالة قد انتهت.
من خلال استكشاف NEAR Explorer، يمكن أن نكتشف أن عقود كل مثيل DAO على المنصة تم نشرها بشكل موحد بواسطة حساب NEAR sputnik-dao.near( وعقد sputnikdao-factory).
أي أن جميع عقود مثيل الـ DAO التي تم إنشاؤها على منصة Sputnik DAO يتم نشرها بشكل منفصل تحت الحسابات الفرعية لحساب NEAR هذا، على سبيل المثال:
يمكن للمنظمات اللامركزية بدء المعاملات علنًا في شبكة NEAR الرئيسية عن طريق استدعاء طريقة create() التي يوفرها عقد sputnikdao-factory، لإنشاء مثيل جديد من DAO.
!
3. تفسير كود عقد الساتينكداو-فابريك
3.1 إنشاء DAO
حالة عقد sputnikdao-factory تتكون أساسًا من جزئين رئيسيين:
صدأ pub struct SputnikDAOFactory { factory_manager: مدير المصنع ، daos: UnorderedSet ، }
factory_manager: تنفيذ المنطق الداخلي الرئيسي للعقد، ويقدم مجموعة من الطرق لإنشاء/حذف/تحديث مثيلات DAO.
daos: تستخدم بنية بيانات مجموعة، تسجل عناوين حسابات NEAR لجميع حالات DAO التي تم إنشاؤها على المنصة تاريخياً.
تُعرَّف طريقة create() لعقد sputnikdao-factory المستخدم في إنشاء مثيل DAO على النحو التالي:
صدأ #[payable] pub fn create(&mut self, name: AccountId, args: Base64VecU8) { let account_id: AccountId = format!('{}. {}', name, env::current_account_id()) .parse() .unwrap(). دع callback_args = serde_json::to_vec(&json!({ 'account_id': account_id, 'attached_deposit': U128(env::attached_deposit()), 'predecessor_account_id': env::p redecessor_account_id() })) .expect('فشل في التسلسل'); self.factory_manager.create_contract( self.get_default_code_hash()، account_id، 'جديد', &args.0 ، 'on_create', &callback_args، ); }
!
factory_manager.create_contract التنفيذ:
صدأ حانة FN create_contract( والذات، code_hash: Base58CryptoHash ، account_id: AccountId ، new_method: &str ، args: &[u8] ، callback_method: & str ، callback_args: &[u8] ، ) { دع code_hash: CryptoHash = code_hash.into(); دع attached_deposit = env::attached_deposit(); دع factory_account_id = env::current_account_id().as_bytes().to_ vec(). let account_id = account_id.as_bytes().to_vec(); غير آمن { // تحقق من أن مثل هذا العقد موجود. assert_eq!( sys::storage_has_key(code_hash.len() ك _, code_hash.as_ptr() ك _ ), 1, 'العقد غير موجود' ); // تحميل إدخال ( كود wasm) إلى السجل 0. sys::storage_read(code_hash.len() ك _ ، code_hash.as_ptr() ك _ ، 0); // جدولة معاملة وعود إلى account_id دع promise_id = sys::p romise_batch_create(account_id.len() ك _, account_id.as_ptr() ك _ ); // إنشاء الحساب أولاً. sys::p romise_batch_action_create_account(promise_id); // نقل الوديعة المرفقة. sys: :p romise_batch_action_transfer(promise_id ، &attached_deposit ك * const u128 ك _) ؛ // نشر العقد (الكود مأخوذ من السجل 0). sys::p romise_batch_action_deploy_contract(promise_id, u64::MAX ك _, 0); // استدعاء جديد بالمعطيات المعطاة. sys::p romise_batch_action_function_call( promise_id، new_method.len() ك _ ، new_method.as_ptr() ك _ ، args.len() ك _ ، args.as_ptr() ك _ ، &NO_DEPOSIT مثل * const u128 ك _ ، CREATE_CALL_GAS.0 ، ); // أرفق رد الاتصال بالمصنع. let _ = sys: :p romise_then( promise_id، factory_account_id.len() ك _ ، factory_account_id.as_ptr() ك _ ، callback_method.len() ك _ ، callback_method.as_ptr() ك _ ، callback_args.len() ك _ ، callback_args.as_ptr() ك _ ، &NO_DEPOSIT مثل * const u128 ك _ ، ON_CREATE_CALL_GAS.0 ، ); sys::p romise_return(promise_id); } }
!
تنفيذ الشيفرة الداخلية لدالة الاسترجاع on_create:
صدأ #[private] حانة FN on_create( &mut self ، account_id: AccountId ، attached_deposit: U128 ، predecessor_account_id: AccountId ، ) -> بول { إذا near_sdk::is_promise_success() { self.daos.insert(&account_id); صحيح } else { الوعد::new(predecessor_account_id).transfer(attached_deposit.0); خاطئ } }
!
3.2 تحديث DAO
واجهة العقد المقدمة من المصنع update():
صدأ /// يحاول تحديث الحساب المعطى الذي أنشأته هذه المصنع إلى الرمز المحدد. pub fn update(& self, account_id: AccountId, code_hash: Base58CryptoHash) { دع caller_id = env::p redecessor_account_id(); أكد!( caller_id == self.get_owner() || caller_id == account_id ، 'يجب أن يتم تحديثه بواسطة مالك المصنع أو DAO نفسه' ); أكد!( self.daos.contains(&account_id) ، 'يجب أن يكون العقد الذي أنشأته المصنع' ); self.factory_manager .update_contract(account_id ، code_hash ، "تحديث" ) ؛ }
!
factory_manager.update_contract() تفاصيل المعالجة:
صدأ /// يجبر التحديث على العقد المعطى. /// يجب أن يدعم العقد التحديث بواسطة المصنع من خلال التحقق من الأذونات. حانة FN update_contract( والذات، account_id: AccountId ، code_hash: Base58CryptoHash ، method_name: &str ، ) { دع code_hash: CryptoHash = code_hash.into(); let account_id = account_id.as_bytes().to_vec(); غير آمن { // تأكد من أن مثل هذا العقد موجود. assert!(env::storage_has_key(&code_hash), 'العقد غير موجود'); // تحميل التجزئة من التخزين. sys::storage_read(code_hash.len() ك _ ، code_hash.as_ptr() ك _ ، 0); // أنشئ وعدًا تجاه الحساب المعطى. دع promise_id = sys::p romise_batch_create(account_id.len() ك , account_id.as_ptr() ك _ ); // استدعاء طريقة التحديث، التي يجب أن تتعامل أيضًا مع الهجرات. sys::p romise_batch_action_function_call( promise_id، method_name.len() ك _ ، method_name.as_ptr() ك _ ، u64 :: ماكس ك _ ، 0, &NO_DEPOSIT مثل * const u128 ك _ ، (env::p repaid_gas() - env::used_gas() - GAS_UPDATE LEFTOVER).0,); sys::p romise_return(promise_id); } }
!
4. تحليل أمان عقد مصنع Sputnik-DAO
تتم ضمانة أمان عقد مصنع Sputnik-DAO من عدة جوانب كما يلي:
التحكم في الأذونات: يجب ألا تعدل طرق العرض المفتوحة في العقد متغيرات حالة العقد، أي يجب تعيين المعامل الأول في تعريف الطريقة إلى &self، وليس &mut self.
التحكم في الأذونات: الوظائف المميزة المفتوحة للعقد، هذه الوظائف يمكن تنفيذها فقط من قبل مالك العقد ( أو حساب عقد DAO )، ويوجد في الطريقة تأكيدات مناسبة.
معالجة الأخطاء: لقد نفذ عقد مصنع Sputnik-DAO آلية معالجة أخطاء معقولة لجميع الحالات الاستثنائية المحتملة. على سبيل المثال، سيقوم عقد المصنع بالتحقق من أن جميع خطوات إنشاء عقد DAO جديد قد تم تنفيذها بشكل صحيح وكامل، وإلا فلن يتسبب ذلك في خسارة للمستخدم.
!
!
!
!