📢 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智能合約DoS攻擊漏洞分析及解決方案
Rust智能合約中的拒絕服務攻擊
拒絕服務(DoS)攻擊可能導致智能合約在一段時間內甚至永久無法正常使用。主要原因包括:
合約邏輯存在缺陷,如某些函數的計算復雜度過高,導致Gas消耗超出限制。
跨合約調用中,合約執行依賴外部合約狀態,可能被外部合約阻塞。
人爲因素,如合約所有者丟失私鑰,導致特權函數無法調用。
下面通過具體例子分析智能合約中的DoS攻擊漏洞。
1. 循環遍歷可被外部修改的大型數據結構
以下是一個用於給註冊用戶分紅的簡單合約:
rust #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub accounts: UnorderedMap<accountid, balance="">, }
impl Contract { pub fn register_account(&mut self) { if self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("帳戶已註冊".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("註冊帳戶 {}", env::predecessor_account_id()); }
}
該合約的問題在於registered數組大小沒有限制,可被惡意用戶操控變得過大,導致distribute_token函數Gas消耗過高。
推薦解決方案:
採用提現模式重構合約。讓用戶主動調用提現函數來獲取獎勵,合約只需記錄用戶可提現的獎勵數額。
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 refund: bool }
impl Contract { pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { assert!(amount > self.highest_bid); if self.current_leader == DEFAULT_ACCOUNT { self.current_leader = sender_id; self.highest_bid = amount; } else { ext_ft_token::account_exist( self.current_leader.clone(), &FTTOKEN, 0, env::prepaid_gas() - GAS_FOR_SINGLE_CALL * 4, ).then(ext_self::account_resolve( sender_id, amount, &env::current_account_id(), 0, GAS_FOR_SINGLE_CALL * 3, )); } log!( "當前最高出價者: {} 最高出價: {}", self.current_leader, self.highest_bid ); PromiseOrValue::Value(0) }
}
該合約的問題在於:必須成功退回前一位出價者的代幣,才能更新最高出價。如果前一位出價者注銷了帳戶,合約將無法完成退款而阻塞。
解決方法:
考慮外部合約調用可能失敗的情況,實現合理的錯誤處理。可以將無法退回的代幣暫存在合約中,後續允許用戶主動提取。
3. 合約所有者私鑰丟失
部分合約函數被設置爲只有所有者可執行,用於更改關鍵系統變量。如果所有者私鑰丟失,這些函數將無法調用,可能導致合約無法正常運行。
解決方法:
設置多個合約所有者共同治理,或採用多籤名機制來替代單一所有者的權限控制,實現去中心化治理。