Solidity 5 — Interface ve Library

Engin UNAL
5 min readOct 17, 2022

Bu yazıyla birlikte Solidity dil özellikleri ile ilgili konularımızın sonuna yaklaşıyoruz. Örneklerle Interface ve Library konularını işleyeceğiz. Önceki yazıların linkleri: Temel Bilgiler, İlk Akıllı Kontrat ve Remix, Tipler, Contract ve Function.

Interface

Interface yapıları akıllı kontratlara bazı standartlar getirmek için kullanılan tanımları içerir. Bunları protokol gibi de düşünebiliriz. Interface ile çerçevesi çizilmiş yani minimum içerik gereksinimi belirlenmiş standartlar getirebiliriz. Bir akıllı kontrat içerisinde mutlaka bulunması istenen fonksiyonlarımız olduğunu düşünelim, interface ile bu fonksiyonları tanımlarız. Ve kontratı interface’ten türeterek fonksiyonların kontrat içinde kodlanmasını zorunlu hale getirebiliriz. Interface tanımları constructor, modifier, state variable tanımlarını içeremez ve içerisinde tanımlı fonksiyonlar mutlaka external olarak tanımlanmalıdır. Interface’ler arasında da inheritance desteği vardır, bir interface diğerinden türeyebilir.

Şimdi kod örneğimizle devam edelim. IRegistration isimli bir interface bulunmakta. Bu interface ile okul kayıt işlemi ve sorgulama işlemi standartları konuluyor. Yani IRegistration interface’inden türeyen bir kontrat mutlaka getCount, getPerson, registerPerson fonksiyonlarının kodlamalarını içermeli.

IRegistration interface’inden türeyen iki kontrat bulunmakta biri RegisterStudent diğer RegisterTeacher. Böylece ortak bir interface tanımı ile bazı gereklilikler getirmiş olduk ve kayıt işlemi yapan kontratlar için standart belirlemesi yaptık. RegisterStudent ve RegisterTeacher farklı yerlere kayıt atmalarına rağmen aynı mimariye sahip oldular. Bu bize ne gibi yararlar sağladı? En önde gelen faydası artık RegisterStudent ve RegisterTeacher ortak bir yapıdan türediği için bir interface ile bu iki kontratı çağırabilir hale geldik. Bunu kodlamada görelim.

Buradaki fark RegistrationFactory isimli bir kontrat ekledik. Bu kontrat ile ister öğrenci ister öğretmen kaydı üretebiliriz. Bunu nasıl yapıyoruz? register ve getByNo fonksiyonlarına dikkat ederseniz contractAddr isimli parametre bulunmakta. Bu parametreye ilgili kontrat adresi geçilir. Bu adres RegisterStudent veya RegisterTeacher kontrat adreslerinden biri olabilir. Veya IRegistration interface’inden türeyen herhangi bir kontrat adresi de olabilir.

Bu adresi alıp interface ile çağırdığımızda adresi verilen kontrat nesnesine ulaşırız. Böylece devamında interface’in ortak fonksiyonlarını kullanarak ulaştığımız kontrat ile etkileşime geçip çalıştırabiliriz. Örnekte registerPerson ve getPerson fonksiyonlarına ulaşıp adresi verilen kontratlar ile etkileşime geçtik ve kayıt üretip okuyabildik.

Remix üzerinden bunu nasıl deneyebiliriz? Meraklısı için ekran görüntüleri ile kısaca ona da cevap bulalım. Öncelikle RegisterStudent ve RegisterTeacher kontratlarımız deploy ediyoruz ve deploy edilen adresi alıyoruz.

0x5e17b14ADd6c386305A32928F985b29bbA34Eff5 adresine deploy edildi
0xe2899bddFD890e320e643044c6b95B9B0b84157A adresine deploy edildi

Devamında RegistrationFactory kontratları deploy edilir veya yayınlanır.

Artık RegistrationFactory kontratı içindeki fonksiyonlarımızı çağırabiliriz. Öncelikle öğrenci kaydı üretmeyi deneyelim. Bunun için RegisterStudent kontrat adresini alacağız. RegistrationFactory kontrat içindeki register fonksiyonundaki contractAddr parametresine bu değeri yazacağız. Ve name, surname, no alanlarını da doldurup transact ile işlemi başlatacağız.

Kontrata aşağıdaki değerleri göndermiş olduk.

{  
"address contractAddr": "0x5e17b14ADd6c386305A32928F985b29bbA34Eff5",
"string _name": "engin",
"string _surname": "ünal",
"uint256 _no": "123"
}

İşlem başarıyla tamamladı. Sorgulama için getByNo fonksiyonunu kontrat adresi ve yeni öğrenci kaydı için verdiğimiz numara(123) ile çağırıyoruz. Sonuç aşağıdaki gibi olacaktır.

Library

Yazılan kodların tekrar kullanılabilirliği önemli bir konudur. Programlama dillerinde bunun için library veya kütüphane yapıları bulunur. Solidity için de aynı durum geçerlidir. Diğer dillerde olan library mantığı burada da mevcuttur. Akıllı kontratlar içinde bazen tekrarlı kodlar olabilmekte veya bir işi yapan fonksiyon iki kontrat içinde de bulunabilmektedir.

Library yapıları özellikle kod tekrarının önlenmesi ve yeniden kullanılabilir kodlar yazmaya yardımcı olması, kontrat kodunun daha kısa ve sade olması ve gas tüketiminin düşürülebilmesi açısından faydalar sağlamaktadır.

Library yapıları kontrat yapılarına çok benzer, sadece fonksiyonların tutulduğu özel tip kontrat gibi düşünülebilir. Bir library fonksiyonunun çağrılması durumunda çalışma anındaki context, çağıran kontratın context’idir. Library fonksiyonları, çağıran kontrat içindeki state değişkenlerine erişebilir.

Library kısıtlamaları ve yetenekleri:

  • State değişkenleri tutmaz.
  • Inheritance yani kalıtım desteği yoktur. Türemez veya türetilemez.
  • Fonksiyonları akıllı kontrat state’leri üzerinde değişiklik yapamaz.
  • Pure ve View fonksiyonları içerir.
  • Fonksiyonlarını çağırmak gas tüketmez.
  • Fallback ve Receive fonksiyonlarını içeremez.
  • Ether bulunduramaz veya alamaz.

Library fonksiyonlarının tümü internal olarak tanımlanmış ise derleme aşamasında onu kullanan kontrat içine gömülür ve öyle deploy edilir. Diğer şekilde ise yani tüm fonksiyonlar internal değil ise library derlemesi deploy edilmeli ve onu kullanan kontrata nerede olduğu tanımlanmalıdır.

Aşağıdaki kodlama örneğide toplama ve çarpma işlemlerini içeren bir library bulunmakta. Daha sonrasında bir kontrat tarafından referans edilip fonksiyonları çağırılmaktadır.

Calculator1 library içerisinde add ve multiply isimli iki fonksiyon bulunmakta. CalculateData1 kontratı ise bu fonksiyonları çağırmaktadır. Dikkat ederseniz library bir nesne gibi yaratılmadı ve doğrudan fonksiyonlara erişildi.

Şimdi aynı işlemi library ve kontrat dosyalarını ayırarak yapalım.

Calculator2 isimli library olsun bunu Library2_Lib.sol dosyasına kaydedelim.

CalculateData2 isimli kontrat kodlarını Library2_Contract.sol dosyasına kaydedelim.

Kontrat içinde import anahtar kelimesi ile referans olarak ekleyeceğimiz library eklenmektedir. Böylece library ve kontrat kodlarını farklı dosyalara ayırmış olduk.

Her iki kullanım da mümkündür ve duruma göre tercih edilebilir. Önemli olan ortak fonksiyonlarımızı library gibi yapılar içine alarak tekrar yazmaktan kurtulmaktır.

Her iki durumda(yani library tanımının kontrat ile aynı dosyada olması veya farklı dosyalarda olması durumlarında) derleme ve ardından deploy yaptığımızda library ve kontrat kodları iki ayrı transaction ile blockchain’e kaydedilir. Remix bunu otomatik olarak gerçekleştirmektedir.

CalculateData1 kontrat ve Calculator1 library deployment sonucu.
CalculateData2 ve Calculator2 library deploy sonucu.

Son olarak library fonksiyonlarının internal olduğu durumda yayınlama yapıldığında tek transaction gözükür, bunun nedeni library kodlarının kontrat içine gömülmesidir. Örnekte inceleyelim.

CalculateData kontrat ve Calculator library örneği. Fakat library fonksiyonları internal tanımlıdır. Bu durumda deployment sonrası tek transaction görülür.

using Kullanımı

Bir tipe fonksiyon bağlamak için kullanılan tanımlardır. Library konusundaki calculator örneği üzerinden gidersek. Library kodlama örneğimiz aşağıdaki gibiydi.

library Calculator {
function add(int a, int b) public pure returns(int) {
return a + b;
}

function multiply(int a, int b) public pure returns(int) {
return a * b;
}
}

add ve multiply fonksiyonlarını int tipinin bir üye fonksiyonu gibi kullanabiliriz. Bunun için

using Calculator for int;

Tanımı yapmak yeterlidir. Bu tanımda her iki fonksiyonu int tipine bağlamış oluruz. Kontrat ise aşağıdaki gibi yazılabilir.

contract CalculateData {
using Calculator for int;
int public result;
function processNumbers(int x, int y) public {
//result = x.add(y);
result = x.multiply(y);
}
}

Böylece x.add(y) olarak çağırıldığında add(a,b) fonksiyonunun ilk parametresi olan a parametresine x değeri atanacak ve b parametresine y değeri atanacaktır.

Serideki diğer yazılar:

Temel Bilgiler

İlk Akıllı Kontrat ve Remix

Tipler

Contract ve Function

Engin Ünal

--

--