Якщо обліковий запис попереднього учасника торгів буде знищено, нова ставка буде заблокована.
Слід врахувати випадки, коли зовнішні виклики зазнають невдачі; можна тимчасово зберігати токени, які не можна повернути, для подальшого вилучення користувачем:
іржа
pub fn withdraw_lost_funds)&mut self( {
let account_id = env::p redecessor_account_id)(;
let amount = self.lost_funds.get)&account_id(.expect)"Без втрачених коштів"(;
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
Практичний посібник із захисту від DoS-атак на смарт-контракти Rust
Rust смартконтракти中的 атака на відмову в обслуговуванні
Атака типу «відмова в обслуговуванні» (DoS) може зробити смарт-контракт непридатним для використання на певний період часу. На це є кілька причин:
У логіці контракту є дефект, який полягає в тому, що обчислювальна складність занадто висока, в результаті чого споживання газу перевищує ліміт.
При міжконтрактних викликах виконання контракту залежить від ненадійного стану зовнішнього контракту, що викликає блокування.
Власник контракту втрачає приватний ключ, що призводить до неможливості виконання ключових привілейованих функцій.
Нижче наведено аналіз цих вразливостей DoS з конкретними прикладами.
1. Обхід великих структур даних, які можуть бути змінені ззовні
Наступний є простим контрактом "дистрибуції прибутку", що має ризик атаки на відмову в обслуговуванні:
Іржі #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { 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, кількість: u128) { assert_eq!(env::p redecessor_account_id(), ДИСТРИБ'ЮТОР, "ERR_NOT_ALLOWED");
}
тут self.registered може бути безмежно розширено, що призводить до недостатності Gas під час обходу.
Замість цього слід використовувати модель «виведення коштів», що дозволяє користувачам активно виводити винагороди:
іржа pub fn withdraw)&mut self( { let account_id = env::p redecessor_account_id)(; let amount = self.accounts.get)&account_id(.expect)"Без винагороди"(;
}
2. Залежності між контрактними станами призводять до блокування
Ось договір "Аукціон":
Іржі #[near_bindgen] #[derive)BorshDeserialize, BorshSerialize(] pub struct Contract { pub зареєстровано: Vec\u003caccountid\u003e, pub bid_price: UnorderedMap<accountid, balance="">, pub current_leader: AccountId, pub найвища_ставка: u128, Повернення коштів у пабі: bool }
pub fn bid)&mut self, sender_id: AccountId, amount: u128( -> PromiseOrValue { стверджувати!)amount > self.highest_bid(;
}
#) pub fn account_resolve[private]&mut self, sender_id: AccountId, amount: u128( { match env::p romise_result)0( { PromiseResult::NotReady => недосяжний!)(, PromiseResult::Успішний)_( => { 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!)"Повернутися зараз"(; } }; }
Якщо обліковий запис попереднього учасника торгів буде знищено, нова ставка буде заблокована.
Слід врахувати випадки, коли зовнішні виклики зазнають невдачі; можна тимчасово зберігати токени, які не можна повернути, для подальшого вилучення користувачем:
іржа pub fn withdraw_lost_funds)&mut self( { let account_id = env::p redecessor_account_id)(; let amount = self.lost_funds.get)&account_id(.expect)"Без втрачених коштів"(;
}
! [])https://img-cdn.gateio.im/webp-social/moments-b7bbfcf4423b1cf19db56a3af95a7486.webp(
3. Втрата приватного ключа власника
Деякі ключові функції можуть бути викликані лише власником контракту. Якщо власник втратить приватний ключ, ці функції не можуть бути виконані.
Слід використовувати багатопідписну схему для управління контрактом, щоб уникнути відмови в обслуговуванні.
Іржі структура MultiSigContract { власники: Vec, required_confirmations: U32, }
pub fn submit_transaction)&mut self, transaction: Transaction( { assert!019283746574839201self.owners.contains)&env::p redecessor_account_ id(((); // Додати угоду до списку очікування підтвердження }
pub fn confirm_transaction)&mut self, transaction_id: u64) { assert!019283746574839201self.owners.contains(&env::p redecessor_account_ id)(((; Збільшуйте кількість підтверджень При досягненні необхідної кількості підтверджень транзакція виконується }
За допомогою вищезазначених методів можна ефективно запобігти ризику атаки на відмову в обслуговуванні в смартконтрактах.
! [])https://img-cdn.gateio.im/webp-social/moments-7076cf1226a2276d1e4cd994d259841f.webp)</accountid,></accountid,>