أمان العقود الذكية Rust: 3 استراتيجيات رئيسية للدفاع ضد هجمات DoS

أمان العقود الذكية في Rust: الدفاع ضد هجوم حجب الخدمة

هجوم حجب الخدمة(DoS) سوف يؤدي إلى عدم إمكانية استخدام العقود الذكية بشكل طبيعي لفترة من الزمن، وقد يتسبب حتى في تعطيلها بشكل دائم. الأسباب الرئيسية تشمل:

  1. تحتوي منطق العقد على عيب في التعقيد الحسابي العالي، مما يؤدي إلى استهلاك الغاز بما يتجاوز الحد.

  2. الاعتماد على حالة تنفيذ العقد الخارجي عند استدعاء العقود عبر العقود الأخرى، قد يتم حظره بواسطة العقد الخارجي.

  3. فقد مالك العقد المفتاح الخاص، ولا يمكنه تنفيذ الوظائف الرئيسية.

سوف نقوم بالتحليل هنا مع أمثلة محددة.

1. تجنب التنقل عبر هياكل البيانات الكبيرة التي يمكن التحكم فيها من الخارج

以下 هو عقد "تقسيم الأرباح" بسيط، ويواجه خطر هجوم حجب الخدمة:

صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، حسابات pub: UnorderedMap<accountid, balance="">, }

pub fn register_account(&mut self) { إذا كان self.accounts.insert(&env::p redecessor_account_id(), &0).is_ some() { env::panic("الحساب مسجل بالفعل".to_string().as_bytes()); } else { self.registered.push(env::p redecessor_account_id()); } log!("حساب مسجل {}", env::p redecessor_account_id()); }

pub fn distribute_token(& mut self, amount: u128) { assert_eq!(env::p redecessor_account_id(), DISTRIBUTOR, "ERR_NOT_ALLOWED");

ل cur_account في self.registered.iter() {
    Let balance = self.accounts.get(&cur_account).expect("ERR_GET");
    self.accounts.insert(&cur_account, &balance.checked_add(amount).expect("ERR_ADD" ));
    log!("حاول التوزيع إلى الحساب {}", &cur_account);
    
    ext_ft_token::ft_transfer(
        cur_account.clone(),
        المبلغ,
        و FTTOKEN ،
        0,
        GAS_FOR_SINGLE_CALL
    );
}

}

تتمثل المشكلة في العقد في عدم وجود حد لحجم مصفوفة registered، مما يمكن المستخدمين الخبيثين من التلاعب بها وجعلها كبيرة جدًا، مما يؤدي إلى تجاوز استهلاك الغاز في وظيفة distribute_token.

الحل الموصى به هو اعتماد وضع "السحب":

صدأ pub fn distribute_token(& mut self, amount: u128) { assert_eq!(env::p redecessor_account_id(), DISTRIBUTOR, "ERR_NOT_ALLOWED");

للحساب في self.registered.iter() {
    let balance = self.accounts.get(&account).unwrap();
    self.accounts.insert(&account, &(balance + amount));
}

}

pub fn withdraw(& mut self) { Let account = env::p redecessor_account_id(); let amount = self.accounts.get(&account).unwrap(); self.accounts.insert(&account, &0);

ext_ft_token::ft_transfer(account, المبلغ, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL);

}

!

2. تجنب الاعتماد على الحالة في استدعاءات العقود المتعددة

下面是一个العقود الذكية示例:

صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId ، حانة highest_bid: u128 ، }

pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { أكد!(amount > self.highest_bid);

إذا كان القائد الحالي هو الحساب الافتراضي {
    self.current_leader = sender_id ؛
    self.highest_bid = المبلغ ؛
} else {
    ext_ft_token::account_exist(
        self.current_leader.clone(),
        و FTTOKEN ،
        0,
        env::p repaid_gas() - GAS_FOR_SINGLE_CALL * 4,
    ).then(ext_self::account_resolve(
        sender_id،
        المبلغ،
        &env::current_account_id(),
        0,
        GAS_FOR_SINGLE_CALL * 3 ،
    ));
}

PromiseOrValue::Value(0)

}

#[private] pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { مطابقة ENV::p romise_result(0) { PromiseResult::Successful(_) => { ext_ft_token::ft_transfer( self.current_leader.clone(), self.highest_bid، و FTTOKEN ، 0, GAS_FOR_SINGLE_CALL * 2 ، ); self.current_leader = sender_id ؛ self.highest_bid = المبلغ ؛ } PromiseResult::Failed = > { ext_ft_token::ft_transfer( sender_id.clone(), المبلغ, و FTTOKEN ، 0, GAS_FOR_SINGLE_CALL * 2 ، ); log!("العودة الآن"); } PromiseResult::NotReady => غير قابل للوصول!(), }; }

المشكلة الموجودة في العقد هي أنه إذا قام أعلى مزايد سابق بإلغاء حسابه، فلن يتمكن المزايدون الجدد من تحديث الحالة بنجاح.

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

صدأ عقد بنية pub { // ... pub lost_found: UnorderedMap<accountid, balance="">, }

pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { مطابقة ENV::p romise_result(0) { PromiseResult::Successful(_) => { // منطق استرداد عادي } PromiseResult::Failed = > { // تخزين الرموز غير القابلة للاسترداد مؤقتًا دع lost_amount = self.lost_found.get(&self.current_leader).unwrap_or(0); self.lost_found.insert(&self.current_leader, &(lost_amount + self.highest_bid));

        // تحديث الحالة
        self.current_leader = sender_id ؛
        self.highest_bid = المبلغ ؛
    }
    PromiseResult::NotReady => غير قابل للوصول!(),
}

}

pub fn withdraw_lost_found(&mut self) { Let account = env::p redecessor_account_id(); المبلغ = self.lost_found.get(&account).unwrap_or(0); إذا كان المبلغ > 0 { self.lost_found.insert(&account, &0); ext_ft_token::ft_transfer(account, المبلغ, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL); } }

3. تجنب الأعطال الفردية

فقدان المفتاح الخاص لمالك العقد سيؤدي إلى عدم إمكانية استخدام الوظائف الحيوية الأساسية. الحل هو اعتماد آلية التوقيع المتعدد:

صدأ عقد بنية pub { مالكي الحانات: Vec\u003caccountid\u003e, حانة required_confirmations: U64 ، معاملات الحانة: Vec ، }

pub fn propose_transaction(&mut self, transaction: Transaction) { assert!(self.owners.contains(&env::p redecessor_account_id()), "ليس المالك "); self.transactions.push(transaction); }

pub fn confirm_transaction(& mut self, transaction_id: u64) { assert!(self.owners.contains(&env::p redecessor_account_id()), "ليس المالك ");

let transaction = &mut self.transactions[transaction_id as usize];
transaction.confirmations += 1 ؛

إذا كانت transaction.confirmations >= self.required_confirmations {
    self.execute_transaction(transaction_id).
}

}

fn execute_transaction(& mut self, transaction_id: u64) { دع المعاملة = self.transactions.remove(transaction_id ك usize) ؛ // تنفيذ منطق المعاملات }

من خلال آلية التوقيع المتعدد، يمكن تجنب تعطل العقد الناتج عن فقدان مفتاح خاص لمالك واحد، مما يزيد من درجة لامركزية العقد وأمانه.

! </accountid,>< / accountid ، الرصيد > < / accountid ، >

شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • 6
  • مشاركة
تعليق
0/400
TokenomicsTherapistvip
· منذ 7 س
فقدان المفتاح الخاص حقيقي جداً هاها
شاهد النسخة الأصليةرد0
GasFeeNightmarevip
· 08-04 04:49
لا عجب أنه مستثمرين كبار في الغاز
شاهد النسخة الأصليةرد0
PretendingToReadDocsvip
· 08-04 04:49
لا يمكن تجنب هجمات DoS ، فما الذي يمكن مناقشته حول الأمان؟
شاهد النسخة الأصليةرد0
HashRatePhilosophervip
· 08-04 04:32
جيش الصدأ قادم، اهتزوا أيها الأعداء
شاهد النسخة الأصليةرد0
TestnetFreeloadervip
· 08-04 04:28
防dos你搁 هنا فخ理论呢
شاهد النسخة الأصليةرد0
MevShadowrangervip
· 08-04 04:26
تكاليف الغاز انفجرت ، لقد جننت.
شاهد النسخة الأصليةرد0
  • تثبيت