Rust akıllı sözleşmeler yetiştirme günlüğü )6( hizmet reddi saldırısı
1. Ondalık sayıların hesaplama hassasiyeti sorunu
Solidity'den farklı olarak, Rust yerel olarak ondalık sayı işlemlerini destekler. Ancak, ondalık sayı işlemlerinin kaçınılmaz hassasiyet sorunları vardır, bu nedenle özellikle önemli ekonomik/finansal kararların oranları veya faiz oranlarıyla ilgili olarak akıllı sözleşmelerde kullanılması önerilmez.
Rust, IEEE 754 standardını izleyerek kayan noktalı sayıları temsil eder. f64 çift hassasiyetli kayan nokta türü, bilgisayar içinde ikili bilimsel gösterim kullanılarak temsil edilir.
Bazı ondalık sayılar, sınırlı basamaklı ikili sayı sistemiyle tam olarak temsil edilebilir; örneğin 0.8125, 0.1101 olarak ifade edilebilir. Ancak 0.7 gibi ondalık sayılar, sonsuz döngüsel ikili temsil üretir ve sınırlı basamaklı kayan nokta sayılarıyla tam olarak gösterilemez, bu da "yuvarlama" sorununu doğurur.
NEAR kamu zincirinde 10 kullanıcıya 0.7 NEAR token dağıtma örneği:
pas
#)
fn precision_test_float[test]( {
let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
println!)"Miktarın değeri: {:.20}", amount(;
assert_eq!)result_0, 0.07(;
}
Çalışma sonucu, amount'un gerçek değerinin 0.69999999999999995559, result_0'ın ise 0.06999999999999999 olduğunu, beklenen 0.07'ye eşit olmadığını gösteriyor.
Bu sorunu çözmek için, sabit noktalı sayılar kullanılabilir. NEAR'da, genellikle 1 NEAR token'ı 10^24 yoctoNEAR olarak ifade edilir. Değiştirilen kod:
pas
#)
fn precision_test_integer[test]( {
let N: u128 = 1_000_000_000_000_000_000_000_000;
let amount: u128 = 700_000_000_000_000_000_000_000;
let divisor: u128 = 10;
let result_0 = amount / divisor;
assert_eq!)result_0, 70_000_000_000_000_000_000_000(;
}
Böylece tam bir sonuç elde edilebilir: 0.7 NEAR / 10 = 0.07 NEAR.
2. Rust tam sayı hesaplama hassasiyeti sorunu
Tam sayı işlemleri bazı durumlarda kayan nokta hassasiyet sorunlarını çözebilirken, tam sayı hesaplamalarının da hassasiyet sorunları bulunmaktadır.
) 2.1 İşlem Sırası
Aynı seviyedeki çarpma ve bölme işlemlerinde, sıralamanın sonucu etkileyebileceği.
pas
fn precision_test_div_before_mul[test]( {
let a: u128 = 1_0000;
let b: u128 = 10_0000;
let c: u128 = 20;
let result_0 = a.checked_mul)c(.unwrap)(.checked_div)b(.unwrap)(;
let result_1 = a.checked_div)b(.unwrap)(.checked_mul)c(.unwrap)(;
assert_eq!)result_0,result_1(;
}
Sonuçlar gösteriyor result_0 = 2, result_1 = 0.
Sebep, tam sayı bölmesinin bölenin altındaki hassasiyeti atmasıdır. result_1'i hesaplarken, )a / b( önce hassasiyeti kaybedip 0 olur; oysa result_0 önce )a * c( hesaplayarak hassasiyet kaybını önlemiştir.
) 2.2 çok küçük bir ölçek
pas
fn precision_test_decimals[test]( {
let a: u128 = 10;
let b: u128 = 3;
let c: u128 = 4;
let decimal: u128 = 100_0000;
let result_0 = a.checked_div)b(.unwrap)(.checked_mul)c(.unwrap)(;
let result_1 = a.checked_mul)decimal(.unwrap)(
.checked_div)b(.unwrap)(
.checked_mul)c(.unwrap)(
.checked_div)decimal(.unwrap)(;
println!)"{}:{}", result_0, result_1(;
assert_eq!)result_0, result_1(;
}
Sonuçlar gösteriyor ki result_0 = 12, result_1 = 13, ve ikincisi gerçek değer 13.3333'e daha yakın.
) 3.4 Rust Crate kütüphanesi rust-decimal kullanımı
Bu kütüphane, yüksek hassasiyet gerektiren ve yuvarlama hatası olmayan ondalık finansal hesaplamalar için uygundur.
( 3.5 Yuvarlama mekanizmasını dikkate alın
Akıllı sözleşmeler tasarımında, yuvarlama genellikle "bana faydalı" ilkesini takip eder: Aşağı yuvarlamak bana faydalıysa aşağı, yukarı yuvarlamak bana faydalıysa yukarı, nadiren dört işlem kuralı uygulanır.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
17 Likes
Reward
17
8
Share
Comment
0/400
LostBetweenChains
· 07-25 17:53
Tam sayı hesaplamalarını bile yapamıyor, hangi sözleşmeyi oynayacak?
View OriginalReply0
WagmiWarrior
· 07-25 11:45
7. makaleyi gördüm, çok ince.
View OriginalReply0
MetaMisfit
· 07-25 01:13
Rust bu akıllı sözleşmelerde çok fazla sorun var gibi.
View OriginalReply0
DuckFluff
· 07-22 22:44
Aman Tanrım, float sayılar yine bir iş çıkarıyor~
View OriginalReply0
MaticHoleFiller
· 07-22 22:44
Hassasiyet tuzağına düşenler burada deneyimlerini paylaşıyor!
View OriginalReply0
MetadataExplorer
· 07-22 22:44
Tam sayılar genellikle göz ardı ediliyor, oldukça kritik.
View OriginalReply0
MEVHunter
· 07-22 22:29
kesinlik bir mev honeypot... floatlarını sıkı tut yoksa rekt olursun ser
View OriginalReply0
TrustlessMaximalist
· 07-22 22:16
Bu kayan nokta işlemlerinden kaçınılması gereken bir tuzak!
Rust akıllı sözleşmeler tamsayı hesaplama hassasiyeti sorunu ve çözüm önerileri
Rust akıllı sözleşmeler yetiştirme günlüğü (: Tam sayı hesaplama hassasiyeti sorunu
Geçmiş değerlendirmesi:
1. Ondalık sayıların hesaplama hassasiyeti sorunu
Solidity'den farklı olarak, Rust yerel olarak ondalık sayı işlemlerini destekler. Ancak, ondalık sayı işlemlerinin kaçınılmaz hassasiyet sorunları vardır, bu nedenle özellikle önemli ekonomik/finansal kararların oranları veya faiz oranlarıyla ilgili olarak akıllı sözleşmelerde kullanılması önerilmez.
Rust, IEEE 754 standardını izleyerek kayan noktalı sayıları temsil eder. f64 çift hassasiyetli kayan nokta türü, bilgisayar içinde ikili bilimsel gösterim kullanılarak temsil edilir.
Bazı ondalık sayılar, sınırlı basamaklı ikili sayı sistemiyle tam olarak temsil edilebilir; örneğin 0.8125, 0.1101 olarak ifade edilebilir. Ancak 0.7 gibi ondalık sayılar, sonsuz döngüsel ikili temsil üretir ve sınırlı basamaklı kayan nokta sayılarıyla tam olarak gösterilemez, bu da "yuvarlama" sorununu doğurur.
NEAR kamu zincirinde 10 kullanıcıya 0.7 NEAR token dağıtma örneği:
pas #) fn precision_test_float[test]( { let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
println!)"Miktarın değeri: {:.20}", amount(; assert_eq!)result_0, 0.07(; }
Çalışma sonucu, amount'un gerçek değerinin 0.69999999999999995559, result_0'ın ise 0.06999999999999999 olduğunu, beklenen 0.07'ye eşit olmadığını gösteriyor.
Bu sorunu çözmek için, sabit noktalı sayılar kullanılabilir. NEAR'da, genellikle 1 NEAR token'ı 10^24 yoctoNEAR olarak ifade edilir. Değiştirilen kod:
pas #) fn precision_test_integer[test]( { let N: u128 = 1_000_000_000_000_000_000_000_000;
let amount: u128 = 700_000_000_000_000_000_000_000; let divisor: u128 = 10;
let result_0 = amount / divisor; assert_eq!)result_0, 70_000_000_000_000_000_000_000(; }
Böylece tam bir sonuç elde edilebilir: 0.7 NEAR / 10 = 0.07 NEAR.
2. Rust tam sayı hesaplama hassasiyeti sorunu
Tam sayı işlemleri bazı durumlarda kayan nokta hassasiyet sorunlarını çözebilirken, tam sayı hesaplamalarının da hassasiyet sorunları bulunmaktadır.
) 2.1 İşlem Sırası
Aynı seviyedeki çarpma ve bölme işlemlerinde, sıralamanın sonucu etkileyebileceği.
pas
fn precision_test_div_before_mul[test]( { let a: u128 = 1_0000; let b: u128 = 10_0000; let c: u128 = 20;
}
Sonuçlar gösteriyor result_0 = 2, result_1 = 0.
Sebep, tam sayı bölmesinin bölenin altındaki hassasiyeti atmasıdır. result_1'i hesaplarken, )a / b( önce hassasiyeti kaybedip 0 olur; oysa result_0 önce )a * c( hesaplayarak hassasiyet kaybını önlemiştir.
) 2.2 çok küçük bir ölçek
pas
fn precision_test_decimals[test]( { let a: u128 = 10; let b: u128 = 3; let c: u128 = 4; let decimal: u128 = 100_0000;
}
Sonuçlar gösteriyor ki result_0 = 12, result_1 = 13, ve ikincisi gerçek değer 13.3333'e daha yakın.
![])https://img-cdn.gateio.im/webp-social/moments-7bdd27c1211e1cc345bf262666a993da.webp(
3. Sayısal Aktüeryal Rust akıllı sözleşmeler nasıl yazılır
Hassasiyeti artırmak için aşağıdaki önlemler alınabilir:
) 3.1 İşlem sırasını ayarlama
Tam sayılar çarpımının bölmeden önce gelmesini sağlayın.
3.2 Tam sayıların büyüklüğünü artırma
Daha büyük bir ölçek kullanarak, daha büyük moleküller oluşturun. Örneğin, 1 NEAR = 10^24 yoctoNEAR olarak tanımlanır.
3.3 Birikim hesaplama doğruluğunun kaybı
Kayıt ve biriken hassasiyet kaybını düzeltmek için sonraki işlemlerde telafi et:
pas const USER_NUM: u128 = 3;
u128 { let token_to_distribute = offset + amount; let per_user_share = token_to_distribute / USER_NUM; let recorded_offset = token_to_distribute - per_user_share * USER_NUM; kayıtlı_ofset }
fn record_offset_test() { let mut offset: u128 = 0; for i in 1..7 { offset = distribute[test]10_000_000_000_000_000_000_000_000, offset(; } }
![])https://img-cdn.gateio.im/webp-social/moments-1933a4a2dd723a847f0059d31d1780d1.webp(
) 3.4 Rust Crate kütüphanesi rust-decimal kullanımı
Bu kütüphane, yüksek hassasiyet gerektiren ve yuvarlama hatası olmayan ondalık finansal hesaplamalar için uygundur.
( 3.5 Yuvarlama mekanizmasını dikkate alın
Akıllı sözleşmeler tasarımında, yuvarlama genellikle "bana faydalı" ilkesini takip eder: Aşağı yuvarlamak bana faydalıysa aşağı, yukarı yuvarlamak bana faydalıysa yukarı, nadiren dört işlem kuralı uygulanır.
![])https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###