📢 Gate廣場 #NERO发帖挑战# 秀觀點贏大獎活動火熱開啓!
Gate NERO生態周來襲!發帖秀出NERO項目洞察和活動實用攻略,瓜分30,000NERO!
💰️ 15位優質發帖用戶 * 2,000枚NERO每人
如何參與:
1️⃣ 調研NERO項目
對NERO的基本面、社區治理、發展目標、代幣經濟模型等方面進行研究,分享你對項目的深度研究。
2️⃣ 參與並分享真實體驗
參與NERO生態周相關活動,並曬出你的參與截圖、收益圖或實用教程。可以是收益展示、簡明易懂的新手攻略、小竅門,也可以是行情點位分析,內容詳實優先。
3️⃣ 鼓勵帶新互動
如果你的帖子吸引到他人參與活動,或者有好友評論“已參與/已交易”,將大幅提升你的獲獎概率!
NERO熱門活動(帖文需附以下活動連結):
NERO Chain (NERO) 生態周:Gate 已上線 NERO 現貨交易,爲回饋平台用戶,HODLer Airdrop、Launchpool、CandyDrop、餘幣寶已上線 NERO,邀您體驗。參與攻略見公告:https://www.gate.com/announcements/article/46284
高質量帖子Tips:
教程越詳細、圖片越直觀、互動量越高,獲獎幾率越大!
市場見解獨到、真實參與經歷、有帶新互動者,評選將優先考慮。
帖子需原創,字數不少於250字,且需獲得至少3條有效互動
Rust智能合約安全:3大關鍵策略防御DoS攻擊
Rust智能合約安全:防御拒絕服務攻擊
拒絕服務(DoS)攻擊會導致智能合約在一段時間內無法被正常使用,甚至永久癱瘓。主要原因包括:
合約邏輯存在計算復雜度過高的缺陷,導致Gas消耗超出限制。
跨合約調用時對外部合約執行狀態的依賴,可能被外部合約阻塞。
合約所有者丟失私鑰,無法執行關鍵的特權函數。
下面結合具體例子進行分析。
1. 避免遍歷可被外部操控的大型數據結構
以下是一個簡單的"分紅"合約,存在DoS風險:
rust #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub accounts: UnorderedMap<accountid, balance="">, }
pub fn register_account(&mut self) { if self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("The account is already registered".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("Registered account {}", env::predecessor_account_id()); }
pub fn distribute_token(&mut self, amount: u128) { assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "ERR_NOT_ALLOWED");
}
該合約的問題在於registered數組大小沒有限制,可被惡意用戶操控使其過大,導致distribute_token函數Gas消耗超限。
推薦的解決方案是採用"提現"模式:
rust pub fn distribute_token(&mut self, amount: u128) { assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "ERR_NOT_ALLOWED");
}
pub fn withdraw(&mut self) { let account = env::predecessor_account_id(); let amount = self.accounts.get(&account).unwrap(); self.accounts.insert(&account, &0);
}
2. 避免跨合約調用狀態依賴
下面是一個"競價"合約示例:
rust #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId, pub highest_bid: u128, }
pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { assert!(amount > self.highest_bid);
}
#[private] pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { match env::promise_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 = amount; } PromiseResult::Failed => { ext_ft_token::ft_transfer( sender_id.clone(), amount, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL * 2, ); log!("Return Back Now"); } PromiseResult::NotReady => unreachable!(), }; }
該合約存在的問題是,如果前一個出價最高者注銷了帳戶,新的競價者將無法成功更新狀態。
解決方法是實現合理的錯誤處理,例如將無法退回的代幣暫存,後續再由用戶自行提取:
rust pub struct Contract { // ... pub lost_found: UnorderedMap<accountid, balance="">, }
pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { match env::promise_result(0) { PromiseResult::Successful(_) => { // 正常退款邏輯 } PromiseResult::Failed => { // 將無法退回的代幣暫存 let lost_amount = self.lost_found.get(&self.current_leader).unwrap_or(0); self.lost_found.insert(&self.current_leader, &(lost_amount + self.highest_bid));
}
pub fn withdraw_lost_found(&mut self) { let account = env::predecessor_account_id(); let amount = self.lost_found.get(&account).unwrap_or(0); if amount > 0 { self.lost_found.insert(&account, &0); ext_ft_token::ft_transfer(account, amount, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL); } }
3. 避免單點故障
合約所有者私鑰丟失會導致關鍵特權功能無法使用。解決方法是採用多籤名機制:
rust pub struct Contract { pub owners: Vec, pub required_confirmations: u64, pub transactions: Vec, }
pub fn propose_transaction(&mut self, transaction: Transaction) { assert!(self.owners.contains(&env::predecessor_account_id()), "Not an owner"); self.transactions.push(transaction); }
pub fn confirm_transaction(&mut self, transaction_id: u64) { assert!(self.owners.contains(&env::predecessor_account_id()), "Not an owner");
}
fn execute_transaction(&mut self, transaction_id: u64) { let transaction = self.transactions.remove(transaction_id as usize); // 執行交易邏輯 }
通過多籤名機制,可以避免單個所有者私鑰丟失導致的合約癱瘓,提高合約的去中心化程度和安全性。