Keamanan smart contract Rust: 3 strategi kunci untuk pertahanan terhadap serangan DoS

Keamanan Smart Contract Rust: Pertahanan terhadap Denial-of-Service Attack

Denial-of-service ( DoS ) attack dapat menyebabkan smart contract tidak dapat digunakan dengan normal dalam jangka waktu tertentu, bahkan bisa mengalami kerusakan permanen. Penyebab utamanya meliputi:

  1. Logika kontrak memiliki cacat dengan kompleksitas perhitungan yang terlalu tinggi, menyebabkan konsumsi Gas melebihi batas.

  2. Ketergantungan pada status eksekusi kontrak eksternal saat memanggil kontrak silang, dapat diblokir oleh kontrak eksternal.

  3. Pemilik kontrak kehilangan kunci pribadi, tidak dapat melaksanakan fungsi privilese yang penting.

Di bawah ini, analisis dilakukan dengan menggabungkan contoh konkret.

1. Hindari iterasi struktur data besar yang dapat dikendalikan secara eksternal

Berikut adalah contoh sederhana dari "smart contract" "dividen", yang memiliki risiko DoS:

karat #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec\u003caccountid\u003e, pub accounts: UnorderedMap\u003caccountid, balance=""\u003e, }

pub fn register_account(&mut self) { jika self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("Akun sudah terdaftar".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("Akun terdaftar {}", env::predecessor_account_id()); }

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

untuk cur_account di self.registered.iter() {
    let balance = self.accounts.get(&cur_account).expect("ERR_GET");
    self.accounts.insert(\u0026cur_account, \u0026balance.checked_add(amount).expect("ERR_ADD"));
    log!("Coba distribusikan ke akun {}", &cur_account);
    
    ext_ft_token::ft_transfer(
        cur_account.clone(),
        jumlah,
        &FTTOKEN,
        0,
        GAS_FOR_SINGLE_CALL
    );
}

}

Masalah pada kontrak ini adalah ukuran array registered tidak terbatas, dapat dimanipulasi oleh pengguna jahat sehingga menjadi terlalu besar, mengakibatkan fungsi distribute_token menghabiskan Gas melebihi batas.

Solusi yang direkomendasikan adalah menggunakan mode "penarikan":

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

untuk akun di self.registered.iter() {
    let balance = self.accounts.get(&account).unwrap();
    self.accounts.insert(&account, &(balance + amount));
}

}

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

ext_ft_token::ft_transfer(akun, jumlah, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL);

}

2. Hindari ketergantungan status pada pemanggilan lintas kontrak

Berikut adalah contoh kontrak "lelang":

karat #[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, }

PromiseOrValue { assert!(jumlah > self.highest_bid);

jika 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,
        jumlah,
        &env::current_account_id((,
        0,
        GAS_FOR_SINGLE_CALL * 3,
    ();
}

PromiseOrValue::Value)0)

}

#( pub fn account_resolve)&mut self, sender_id: AccountId, amount: u128[private] { cocok 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)(, jumlah, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL * 2, (; log!)"Return Back Now"); } PromiseResult::NotReady => unreachable!(), }; }

Masalah yang ada pada kontrak ini adalah, jika penawar tertinggi sebelumnya membatalkan akun, penawar baru tidak akan dapat berhasil memperbarui status.

Solusinya adalah menerapkan penanganan kesalahan yang wajar, misalnya menyimpan token yang tidak dapat dikembalikan, kemudian diambil oleh pengguna sendiri.

karat pub struct Contract { // ... pub lost_found: UnorderedMap\u003caccountid, balance=""\u003e, }

pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { cocok env::promise_result(0) { PromiseResult::Successful(_) => { // Logika pengembalian normal } PromiseResult::Failed => { // Menyimpan token yang tidak dapat dikembalikan 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((;

        // memperbarui status
        self.current_leader = sender_id;
        self.highest_bid = amount;
    }
    PromiseResult::NotReady => unreachable!)),
}

}

pub fn withdraw_lost_found(&mut self) { let account = env::predecessor_account_id(); let amount = self.lost_found.get(&account).unwrap_or(0); jika jumlah > 0 { self.lost_found.insert(&account, &0); ext_ft_token::ft_transfer(akun, jumlah, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL); } }

3. Hindari Kegagalan Titik Tunggal

Kehilangan kunci pribadi pemilik kontrak dapat menyebabkan fungsi hak istimewa yang penting tidak dapat digunakan. Solusi adalah dengan menggunakan mekanisme tanda tangan ganda:

karat pub struct Contract { pemilik pub: Vec\u003caccountid\u003e, 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(((, "Bukan pemilik");

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

jika transaction.confirmations >= self.required_confirmations {
    self.execute_transaction)transaction_id);
}

}

fn execute_transaction(&mut self, transaction_id: u64) { let transaction = self.transactions.remove(transaction_id sebagai usize); // Eksekusi logika transaksi }

Dengan mekanisme multisignature, dapat menghindari kegagalan kontrak yang disebabkan oleh kehilangan kunci pribadi pemilik tunggal, meningkatkan tingkat desentralisasi dan keamanan kontrak.

</accountid,></accountid,balance></accountid,>

Lihat Asli
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
  • Hadiah
  • 5
  • Bagikan
Komentar
0/400
GasFeeNightmarevip
· 12jam yang lalu
Tidak heran jika dia adalah Investor Luas Gas
Lihat AsliBalas0
PretendingToReadDocsvip
· 12jam yang lalu
DoS tidak dapat dihindari, apa lagi yang bisa dibicarakan soal keamanan
Lihat AsliBalas0
HashRatePhilosophervip
· 13jam yang lalu
Pasukan rust datang, lawan bergetar!
Lihat AsliBalas0
TestnetFreeloadervip
· 13jam yang lalu
Menghadapi dos, kamu menggunakan jebakan teori ini?
Lihat AsliBalas0
MevShadowrangervip
· 13jam yang lalu
Biaya Gas meledak, saya bingung.
Lihat AsliBalas0
  • Sematkan
Perdagangkan Kripto Di Mana Saja Kapan Saja
qrCode
Pindai untuk mengunduh aplikasi Gate
Komunitas
Bahasa Indonesia
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)