Solidity akıllı sözleşmeleri test etmek için nasıl taklit edilir?
Taklit nesneler (opens in a new tab), nesne yönelimli programlamada yaygın olarak kullanılan bir tasarım modelidir. Fransızca'dan gelen "mocquer" kelimesi "dalga geçmek" anlamındadır. Bu kelime "gerçek olan bir şeyi taklit etmek" anlamına evrilmiştir ki bu, tam olarak programlamada yaptığımız şeydir. Akıllı sözleşmelerinizle lütfen sadece istediğiniz zaman dalga geçin ama her boş vaktinizde onları taklit edin. Bu, hayatınızı kolaylaştıracak.
Taklit nesnelerle sözleşmelerin birim testi
Bir sözleşmeyi taklit etmek, sözleşmenin gerçek hali gibi davranan ve geliştirici tarafından kolayca kontrol edilebilen ikinci bir versiyonunu oluşturmak anlamına gelir. Çoğu zaman, yalnızca sözleşmenin küçük kısımlarına birim testi yapmak istediğiniz karmaşık sözleşmelerle karşılaşırsınız. Buradaki sorun, ya bu ufak parçanın test edilmesi çok detaylı bir sözleşme durumu gerektiriyorsa ve buna ulaşmak zorsa?
Her seferinde sözleşmeyi istenen duruma getiren karmaşık bir test yazabilir veya "taklitlerle" işinizi kolayca halledebilirsiniz. Bir sözleşme, kalıtım yöntemiyle kolayca taklit edilebilir. Orijinal sözleşmeyi içeren ikinci bir taklit sözleşme yazın. Şimdi fonksiyonları taklit sözleşmeniz için geçersiz kılabilirsiniz. Bir örnekle görelim.
Örnek: Özel ERC20
Başlangıç özel zamanı olan örnek bir ERC-20 sözleşmesi kullanıyoruz. Sözleşmenin sahibi özel kullanıcıları yönetebilir ve başlangıçta yalnızca bu kullanıcıların jeton almasına izin verir. Belirli bir zaman geçtikten sonra herkes jetonları kullanabilecektir. Merak ediyorsanız, yeni OpenZeppelin sözleşmeleri v3'ten gelen _beforeTokenTransfer (opens in a new tab) kancasını kullanıyoruz.
1pragma solidity ^0.6.0;23import "@openzeppelin/contracts/token/ERC20/ERC20.sol";4import "@openzeppelin/contracts/access/Ownable.sol";56contract PrivateERC20 is ERC20, Ownable {7 mapping (address => bool) public isPrivateUser;8 uint256 private publicAfterTime;910 constructor(uint256 privateERC20timeInSec) ERC20("PrivateERC20", "PRIV") public {11 publicAfterTime = now + privateERC20timeInSec;12 }1314 function addUser(address user) external onlyOwner {15 isPrivateUser[user] = true;16 }1718 function isPublic() public view returns (bool) {19 return now >= publicAfterTime;20 }2122 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {23 super._beforeTokenTransfer(from, to, amount);2425 require(_validRecipient(to), "PrivateERC20: geçersiz alıcı");26 }2728 function _validRecipient(address to) private view returns (bool) {29 if (isPublic()) {30 return true;31 }3233 return isPrivateUser[to];34 }35}Tümünü gösterŞimdi sözleşmeyi taklit edelim.
1pragma solidity ^0.6.0;2import "../PrivateERC20.sol";34contract PrivateERC20Mock is PrivateERC20 {5 bool isPublicConfig;67 constructor() public PrivateERC20(0) {}89 function setIsPublic(bool isPublic) external {10 isPublicConfig = isPublic;11 }1213 function isPublic() public view returns (bool) {14 return isPublicConfig;15 }16}Tümünü gösterŞu hata mesajlarından birini alacaksınız:
PrivateERC20Mock.sol: TypeError: Geçersiz kılan fonksiyon "override" niteleyicisini içermiyor.PrivateERC20.sol: TypeError: Sanal olmayan bir işlevi geçersiz kılmaya çalışılıyor. "virtual" eklemeyi unuttunuz mu?.
Yeni Solidity 0.6 sürümünü kullandığımız için, üzerine yazılabilecek fonksiyonlar için virtual anahtar kelimesini ve üzerine yazan fonksiyon için de override anahtar kelimesini eklemeliyiz. Öyleyse bunları her iki isPublic fonksiyonuna da ekleyelim.
Artık birim testlerinizde bunun yerine PrivateERC20Mock kullanabilirsiniz. Özel kullanım süresi sırasındaki davranışı test etmek istediğinizde setIsPublic(false) kullanın ve benzer şekilde, genel kullanım süresini test etmek için setIsPublic(true) kullanın. Elbette örneğimizde, zamanları buna göre değiştirmek için zaman yardımcılarını (opens in a new tab) da kullanabiliriz. Ancak taklit amacı artık açık olmalıdır ve bunun sadece zamanı ilerletmek kadar kolay olmadığı durumları hayal edebilirsiniz.
Birçok sözleşmeyi taklit etme
Her taklit için ayrı bir sözleşme oluşturmak karışıklık oluşturabilir. Bu durum sizi rahatsız ediyorsa, MockContract (opens in a new tab) kütüphanesine göz atabilirsiniz. Size anlık olarak sözleşmelerin davranışlarını değiştirme ve geçersiz kılma olanağı sağlar. Ancak, yalnızca diğer bir sözleşmeye yapılan taklitler için çalışır; bu nedenle, örneğimizde işe yaramaz.
Taklit etme daha da güçlü olabilir
Taklit etmenin gücü burada bitmiyor.
- Fonksiyon ekleme: Sadece belirli bir işlevi geçersiz kılmak açısından değil, aynı zamanda ilave fonksiyonlar eklemek açısından da kullanışlıdır. Jetonlar için iyi bir örnek, herhangi bir kullanıcının ücretsiz olarak yeni jetonlar almasını sağlamak için ek bir
mintişlevine sahip olmaktır. - Test ağlarında kullanım: Sözleşmelerinizi merkeziyetsiz uygulamalarınızla birlikte test ağlarına dağıtıp test ettiğinizde, taklit sürümlerini kullanmayı düşünün. Mecbur kalmadıkça fonksiyonları geçersiz kılmaktan kaçının. Sonuçta arkasındaki gerçek mantığı test etmek istiyorsunuz. Fakat örneğin, sözleşme durumunu en başa sıfırlayan ve yeni bir dağıtım gerektirmeyen bir sıfırlama işlevi eklemek de yararlı olabilir. Tabii ki de bunu bir Ana Ağ sözleşmesinde kullanmak istemezsiniz.
Sayfanın son güncellenmesi: 25 Ağustos 2025