Ana içeriğe geç

Solidity akıllı sözleşmeleri test etmek için nasıl taklit edilir?

solidity
akıllı kontratlar
test etmek
taklit etme
Orta düzey
Markus Waas
2 Mayıs 2020
3 dakikalık okuma

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;
2
3import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
4import "@openzeppelin/contracts/access/Ownable.sol";
5
6contract PrivateERC20 is ERC20, Ownable {
7 mapping (address => bool) public isPrivateUser;
8 uint256 private publicAfterTime;
9
10 constructor(uint256 privateERC20timeInSec) ERC20("PrivateERC20", "PRIV") public {
11 publicAfterTime = now + privateERC20timeInSec;
12 }
13
14 function addUser(address user) external onlyOwner {
15 isPrivateUser[user] = true;
16 }
17
18 function isPublic() public view returns (bool) {
19 return now >= publicAfterTime;
20 }
21
22 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
23 super._beforeTokenTransfer(from, to, amount);
24
25 require(_validRecipient(to), "PrivateERC20: geçersiz alıcı");
26 }
27
28 function _validRecipient(address to) private view returns (bool) {
29 if (isPublic()) {
30 return true;
31 }
32
33 return isPrivateUser[to];
34 }
35}
Tümünü göster

Şimdi sözleşmeyi taklit edelim.

1pragma solidity ^0.6.0;
2import "../PrivateERC20.sol";
3
4contract PrivateERC20Mock is PrivateERC20 {
5 bool isPublicConfig;
6
7 constructor() public PrivateERC20(0) {}
8
9 function setIsPublic(bool isPublic) external {
10 isPublicConfig = isPublic;
11 }
12
13 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 mint iş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

Bu rehber yararlı oldu mu?