Solidity'den diğer sözleşmelerle etkileşime geçme
Önceki öğreticilerde ilk akıllı sözleşmenizi nasıl dağıtacağınız gibi pek çok şey öğrendik ve ona değiştiricilerle erişimi kontrol etme (opens in a new tab) veya Solidity'de hata yönetimi (opens in a new tab) gibi bazı özellikler ekledik. Bu öğreticide mevcut bir sözleşmeden bir akıllı sözleşme dağıtmayı ve onunla etkileşim kurmayı öğreneceğiz.
Bunun için bir fabrika oluşturarak herkesin kendi Counter akıllı sözleşmesine sahip olmasını sağlayan bir sözleşme yapacağız, adı CounterFactory olacak. İlk olarak, ilk Counter akıllı sözleşmemizin kodu:
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "Sözleşmenin sahibi siz değilsiniz");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "Fabrikayı kullanmanız gerekir");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}Tümünü gösterFabrikanın adresini ve sözleşme sahibinin adresini takip etmek için sözleşme kodunu biraz değiştirdiğimizi unutmayın. Başka bir sözleşmeden bir sözleşme kodu çağırdığınızda, msg.sender sözleşme fabrikamızın adresini gösterecektir. Diğer sözleşmelerle etkileşim kurmak için bir sözleşme kullanmak yaygın bir uygulama olduğundan, bu anlaşılması gerçekten önemli bir noktadır. Bu nedenle, karmaşık durumlarda göndericinin kim olduğuna dikkat etmelisiniz.
Bunun için, durum değiştiren fonksiyonun yalnızca orijinal çağırıcıyı parametre olarak geçiren fabrika tarafından çağrılabilmesini sağlayan bir onlyFactory değiştiricisi de ekledik.
Diğer tüm Sayaçları yönetecek olan yeni CounterFactory'mizin içine, bir sahibini kendi sayaç sözleşmesinin adresiyle ilişkilendirecek bir eşleme ekleyeceğiz:
1mapping(address => Counter) _counters;Ethereum'da, eşlemeler javascript'teki nesnelerin eşdeğeridir; A türünde bir anahtarı B türünde bir değere eşlemeyi sağlarlar. Bu durumda, bir sahibinin adresini onun Counter örneği ile eşleriz.
Birisi için yeni bir Counter örneği oluşturmak şöyle görünür:
1 function createCounter() public {2 require (_counters[msg.sender] == Counter(0));3 _counters[msg.sender] = new Counter(msg.sender);4 }Önce kişinin zaten bir Counter'ı olup olmadığını kontrol ederiz. Eğer bir Counter'ı yoksa, adresini Counter yapıcısına geçirerek yeni bir Counter örneği oluştururuz ve yeni oluşturulan örneği eşlemeye atarız.
Belirli bir Counter'ın sayımını almak şöyle görünür:
1function getCount(address account) public view returns (uint256) {2 require (_counters[account] != Counter(0));3 return (_counters[account].getCount());4}56function getMyCount() public view returns (uint256) {7 return (getCount(msg.sender));8}İlk fonksiyon, belirtilen adres için Counter sözleşmesinin mevcut olup olmadığını kontrol eder ve ardından örnekten getCount metodunu çağırır. İkinci fonksiyon olan getMyCount, msg.sender'ı doğrudan getCount fonksiyonuna geçirmek için kullanılan bir kısayoldur.
increment fonksiyonu oldukça benzerdir ancak orijinal işlem göndericisini Counter sözleşmesine iletir:
1function increment() public {2 require (_counters[msg.sender] != Counter(0));3 Counter(_counters[msg.sender]).increment(msg.sender);4 }Çok fazla kez çağrılırsa, counter'ımızın bir taşma hatasına maruz kalabileceğini unutmayın. Bu olası duruma karşı korunmak için SafeMath kütüphanesini (opens in a new tab) mümkün olduğunca kullanmalısınız.
Sözleşmemizi dağıtmak için hem CounterFactory hem de Counter kodunu sağlamanız gerekecektir. Örneğin Remix'te dağıtım yaparken CounterFactory'yi seçmeniz gerekecektir.
İşte kodun tamamı:
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "Sözleşmenin sahibi siz değilsiniz");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "Fabrikayı kullanmanız gerekir");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}3435contract CounterFactory {3637 mapping(address => Counter) _counters;3839 function createCounter() public {40 require (_counters[msg.sender] == Counter(0));41 _counters[msg.sender] = new Counter(msg.sender);42 }4344 function increment() public {45 require (_counters[msg.sender] != Counter(0));46 Counter(_counters[msg.sender]).increment(msg.sender);47 }4849 function getCount(address account) public view returns (uint256) {50 require (_counters[account] != Counter(0));51 return (_counters[account].getCount());52 }5354 function getMyCount() public view returns (uint256) {55 return (getCount(msg.sender));56 }5758}Tümünü gösterDerleme işleminden sonra, Remix dağıtım bölümünde dağıtılacak fabrikayı seçeceksiniz:
Ardından sözleşme fabrikanızla denemeler yapabilir ve değerin değiştiğini kontrol edebilirsiniz. Akıllı sözleşmeyi farklı bir adresten çağırmak isterseniz Remix'in Hesap seçimi bölümündeki adresi değiştirmeniz gerekir.
Sayfanın son güncellenmesi: 15 Ağustos 2023
