Daha iyi bir Türkiye mümkün! Türkiye'nin girişimcilik ve inovasyon topluluğu·2018'den beri

Web3

/web3

/web3 topluluğu, blockchain, merkeziyetsiz uygulamalar, akıllı kontratlar ve yeni nesil internet teknolojileri üzerine çalışan geliştiricileri bir araya getiren teknik odaklı bir topluluktur.

#web3 akışına dön
@endof · 11 gün önce

Akıllı kontratlarda fuzz testi ve invariant testi: Foundry ile bir yılda öğrendiklerim

Bir yıldır küçük bir ekipte akıllı kontrat geliştiriyorum. İlk aylarda testlerimiz klasik birim testlerinden ibaretti: şu fonksiyonu şu parametreyle çağır, sonucun şu olduğunu kontrol et. Bir iç denetimde, hiçbir birim testimizin yakalamadığı bir hata bulununca test yaklaşımımızı değiştirdik. Neler öğrendiğimi anlatayım.

Fuzz testi, aynı testi rastgele üretilmiş girdilerle yüzlerce, binlerce kez çalıştırmak. Foundry'de bir test fonksiyonuna parametre eklediğinizde, araç bu parametreler için rastgele değerler üretip testi defalarca çalıştırıyor. Bizim hatamız tam da burada çıktı: belirli bir yuvarlama durumunda, çok küçük tutarlarla yapılan bir işlem kullanıcının hak ettiğinden biraz fazla pay almasını sağlıyordu. Birim testlerimizde hep yuvarlak sayılar kullandığımız için bunu hiç görmemiştik.

Invariant testi ise bir adım daha ileri. Burada kontratta her zaman doğru olması gereken bir kural tanımlıyorsunuz. Örneğin toplam pay arzı, tüm kullanıcıların paylarının toplamına eşit olmalı. Ya da kasadaki varlık, kullanıcılara borçlu olunan toplamdan az olmamalı. Araç, kontrata rastgele sırayla rastgele fonksiyon çağrıları yapıyor ve her adımdan sonra bu kuralların hâlâ geçerli olup olmadığını kontrol ediyor.

Invariant testlerinin zor kısmı doğru kuralları bulmak. İlk yazdığımız kurallar çok genel olduğu için hiçbir şey yakalamadı. Sonra kontratın iş mantığını kağıda döktük: hangi değerler birbiriyle ilişkili, hangi durumda hangi değer hangi yönde değişmeli. Bu çalışma tek başına tasarımdaki iki zayıf noktayı ortaya çıkardı, daha test yazmadan.

İkinci zor kısım handler yazmak. Araca rastgele çağrı yaptırırken anlamsız çağrılarla zaman kaybetmemesi için çağrıları yönlendiren bir ara kontrat yazmanız gerekiyor. Örneğin para çekme fonksiyonunun yalnızca bakiyesi olan adreslerle çağrılmasını sağlamak gibi. Bunu yapmadığımızda testlerin büyük kısmı anlamsız ret durumlarında kayboluyordu.

Bu testler denetimin yerini tutmuyor, ama denetime çok daha temiz bir kodla gitmemizi sağladı. Denetçilerin bulduğu bulgu sayısı bir önceki denetime göre belirgin şekilde azaldı. Fuzz ya da invariant testi kullanan başka ekipler hangi kuralları yazıyor, merak ediyorum.
3 3 yorum
Yorumlar (3)
@mean · 11 gün önce 1
Yuvarlama hatası bulmanız tipik bir örnek, bu tür hataların çoğu küçük tutarlarla ortaya çıkıyor ve saldırganlar tam da bunu arıyor. Ben bir de testlerinizi farklı başlangıç durumlarıyla çalıştırmanızı öneririm. Boş bir kasa ile dolu bir kasa farklı davranır; ilk yatıran kullanıcının durumu genellikle en az test edilen senaryo oluyor.
@kodkedisi · 11 gün önce 5
Backend tarafında özellik tabanlı test yazıyorum, mantık aynı. Senin anlattığın kural bulma kısmı bizde de en zor kısım. Bir soru: invariant testleri ne kadar sürede çalışıyor, her commit'te mi çalıştırıyorsunuz yoksa gece mi?
@endof · 11 gün önce 4
Kısa bir versiyonunu her pull request'te, uzun ve daha derin çalışan versiyonunu gece çalıştırıyoruz. Uzun versiyon bazen sabaha kadar sürüyor ama birkaç kez tam orada bir şey yakaladı.
Tanıtım videosu · 1 dk

inovanadolu'yu 1 dakikada tanı

Kanallar, sözlük, İlham blogu, kişilik testleri ve 140'tan fazla ücretsiz araç. Üretenlerin buluşma noktasında neler olduğunu kısaca izle.