Ana içeriğe geç

Solidity'den diğer sözleşmelerle etkileşime geçme

akıllı kontratlar
solidity
remix
dağıtma
birleştirilebilirlik
Gelişmiş
jdourlens
5 Nisan 2020
3 dakikalık okuma

Ö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;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "Sözleşmenin sahibi siz değilsiniz");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Fabrikayı kullanmanız gerekir");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
Tümünü göster

Fabrikanı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}
5
6function 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;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "Sözleşmenin sahibi siz değilsiniz");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Fabrikayı kullanmanız gerekir");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
34
35contract CounterFactory {
36
37 mapping(address => Counter) _counters;
38
39 function createCounter() public {
40 require (_counters[msg.sender] == Counter(0));
41 _counters[msg.sender] = new Counter(msg.sender);
42 }
43
44 function increment() public {
45 require (_counters[msg.sender] != Counter(0));
46 Counter(_counters[msg.sender]).increment(msg.sender);
47 }
48
49 function getCount(address account) public view returns (uint256) {
50 require (_counters[account] != Counter(0));
51 return (_counters[account].getCount());
52 }
53
54 function getMyCount() public view returns (uint256) {
55 return (getCount(msg.sender));
56 }
57
58}
Tümünü göster

Derleme işleminden sonra, Remix dağıtım bölümünde dağıtılacak fabrikayı seçeceksiniz:

Remix'te dağıtılacak fabrikayı seçme

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

Bu rehber yararlı oldu mu?