Yazımıza başlamadan önce bilmemizin faydalı olacağı birkaç kavramı burada listeledim.
Unicode (Evrensel Kod) Unicode Consortium organizasyonu tarafından geliştirilen ve her karaktere bir sayı değeri karşılığı atayan bir endüstri standardıdır.[ayr. bkz.]
Bilişim ve matematik alanında kullanılan 1-9 rakamlarının 1-9 sembolleriyle, 10-16 sayılarının sırasıyla A-F arasındaki harflerle temsil edildiği on altılık tabanlı sayı sisteminin adıdır. Benzer olarak ikili sayı sistemi ve onlu sayı sistemi de vardır.
UTF-8, UTF-16 ise birer karakter kodlamasıdır. Açılımı, Unicode Transformation Format olan UTF 8, 8-bitlik byte grubları oluşturmayı sağlayan karakterlerin kodlamasıdır ve Rob Pike ve Ken Thompson tarafından geliştirilmiştir.
ASCII ve Unicode birer karakter setidir. ASCII (American Standard Code for Information Interchange) 7 bitlik karakter kod setidir. 0 ve 127'de dahil olmak üzere aralarındaki tüm sayıların binary karşılıklarının belirlendiği bir karakter setidir.
Unicode ise ASCII karakterlerinin yetersiz gelmesiyle birlikte oluşturulan karakter setidir. ASCII'deki 7 bitlik karakter tanımlamasına kıyasla kalan karakterlerin(semboller, farklı dillerdeki karakterler vb.) 8-bitlik karakterleri kullanılarak oluşturulduğu bir karakter setidir.
EN: Contract Types
Her sözleşme kendi türünü tanımladığı için başka bir sözleşmeyi kalıtabilir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; //ContractTypes isimli bir sözleşmemiz contract ContractTypes{ } //ContractTypes2 isimli sözleşmemizi ContractTypes isimli diğer sözleşmemizden kalıttık. /*contract <Kendi Sözleşmemizin İsmi> is <Kalıtacağımız Ana Sözleşme İsmi>*/ contract ContractTypes2 is ContractTypes{
Sözleşmeler, to
ve from
adres türlerine dönüştürülebilir. address payable
kodu bir sözleşmedeki fonksiyonların payable
olmasıyla mümkünken bunun haricinde payable
bir address
üretmek payable(<address>)
ile mümkün olmaktadır. Aşağıdaki örneğe göz atabilirsiniz.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract yonetimSozlesmesi{ //Yapılandırıcı constructor() { //yonetici değişkeni sözleşmeyi oluşturan kişinin adresidir. (msg.sender) Bu adresin ödenebilir özelliğine sahip olması için // payable(msg.sender) fonksiyonunu çağırdık. Çağırmadığımızda bir hata meydana gelecektir. yonetici = payable(msg.sender); } //Tanımladığımız ödenebilir adres türündeki yonetici değişkeni address payable yonetici; }
Solidity 0.5.0 versiyonundan önceaddress
veaddress payable
arasında fark gözetilmezdi. Tek biraddress
kodu ile türetilirdi.
Sözleşmeler kendi içlerinde de tekrardan kalıtılabilir. Kalıtılan sözleşmedeki fonksiyonlar çağrılarak çeşitli işlemler gerçekleştirilebilir ve değerler alınarak atanabilir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract YonetimSozlesmesi{ //Yapılandırıcı constructor() { //yonetici değişkeni sözleşmeyi oluşturan kişinin adresidir. (msg.sender) Bu adresin ödenebilir özelliğine sahip olması için // payable(msg.sender) fonksiyonunu çağırdık. Çağırmadığımızda bir hata meydana gelecektir. yonetici = payable(msg.sender); } address payable yonetici; function kalitimYapacagimizFonksiyon() public view returns(address payable){ return yonetici; } //Aynı Sozlesmeyi kalıttık. YonetimSozlesmesi sozlesme; //Kalıtmış olduğumuz sözleşmeden adres değerini fonksiyon yardımıyla çektik. address payable yoneticiKalitilmis = sozlesme.kalitimYapacagimizFonksiyon();
Sözleşmelerde herhangi bir operatör kullanılmaz. Ayrıca ana sözleşmenin kopyalarındaki(members of a contract) herhangi bir fonksiyonun kullanılması için fonksiyonun public
türünde olması gerekmektedir.
Not olarak, fonksiyonlara eklenecek public
, returns()
, payable
gibi türler fonksiyon isminden sonra tanımlanmalıdır.
//public türü fonksiyon isminden önce tanımlandığı için hata fırlatılıyor. function public kalitimYapacagimizFonksiyon() view returns(address payable){ return yonetici; } //function <-Fonksiyon İsminiz-> <-Tür Etiketleri(public, view vb)-> şeklinde kullanım doğrudur. function kalitimYapacagimizFonksiyon() public view returns(address payable){ return yonetici; }
Sözleşmemizin bazı özelliklerine type()
fonksiyonu ile erişebiliriz. Örneğin sözleşme ismi, type(C).name
, type(C).creationCode
, type(C).runtimeCode
, type(T).min
, type(T).max
, type(I).interfaceId
gibi değerlere erişebiliriz. [ayr. bkz.] Bu konuyu bu yazımızda örnekleyip geçeceğim. İlerleyen yazılarda daha ayrıntılı inceleyebiliriz.
EN: Fixed-size byte arrays
Sabit büyüklükteki veri türleri bytes1
, bytes2
bytes3
... bytes32
yani X, 1-32 aralığında bir tam sayı olursa bytesX
örneğindeki gibi herhangi bir şekilde tanımlanabilmektedir. Her rakam kaç byte verinin tutulacağını göstermektedir. İkili sayı sistemi alfabesine göre düşünürsek her bir rakam, harf veya sembol 8 bitlik bir byte değerine sahiptir. Yani bytes3
değişkeni 1-2-3 karakterli bir string değerine sahip olabilir ancak 3 karakterden fazla değer tanımlamamıza izin verilmez. Örnek olması açısından aşağıdaki kodu inceleyebiliriz.
//maksimum 32 byte(1 byte = 8 bit) değerinde veri koyulabilir. bytes32 ornek = "ornekornekornekornekornekornekor";//maksimum 32 karakter veri depolayabilir. //maksimum 10 byte(1 byte = 8 bit) değerinde veri koyulabilir. bytes10 ornek2 = "ornek2orne";//maksimum 10 karakter veri depolayabilir.
Byte listeleri ile karşılaştırma, shift, bit ve sıralama operatörleri kullanılmaktadır.
- Karşılaştırma operatörleri(comparisons),
<=
,<
,==
,!=
,>=
,>
(evaluate tobool
) - Bit operatörleri,
&
,|
,^
(bit seviyesinde özel veya),~
(bit seviyesinde olumsuzlama) - Kaydırma Operatörleri(Shift Operators),
<<
(sola kaydırma),>>
(sağa kaydırma), - Sıralama operatörleri, a
bytesX
türünde bir değer isea[i]
,0 <= i < X
şartını sağladığı taktirde okunabilir bir byte değeri döndürecektir.
.length
, byte listelerinin(byte arrays), uzunluğunu uint
değerinde döndürür.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract BitwiseOperatorleri{ //Örnek bitwise operatörleri kullanımı function f() public pure returns(bytes1[4] memory){ bytes1 a = 0xb5; // [10110101] byte bytes1 b = 0x56; // [01010110] byte bytes1 sonucOr = a & b; bytes1 sonucAnd = a | b; bytes1 sonucXOr = a ^ b; bytes1 sonucOlumsuzlama = ~b; //Tüm bytes1 türlerinden bir liste oluşturduk. Tüm elemanların listeye tanımlanmış türde olması gerekmekte. bytes1[4] memory ornekByteArray = [sonucOr,sonucAnd,sonucXOr,sonucOlumsuzlama]; //Array uzunluğunu aldık. Uzunluk değeri uint türünde olmalıdır. Aksi taktirde hata fırlatacaktır. uint256 len = ornekByteArray.length; return ornekByteArray;
EN: Dynamically-sized byte array
Değişken büyüklükteki byte listeleri bytes
, değişken büyüklükteki metin listeleri ise string
ile kullanılır.
string
, bytes
değişkenine eşittir ancak string
'de bytes
'daki gibi byte sırasına [k] kullanarak erişemeyiz ve byte
listemize belirli bir büyüklük veremeyiz. Büyüklük dinamik olarak ayarlanır!
EN: Address Literals
Adres değişmezleri address
ile tanımlanan, hexadecimal sayı sistemine göre oluşturulan ve kontrol edilen, 39 ve 41 hane arasındaki değişmez değerlerdir.
0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF
örnek bir adrestir. [Kaynak: Solidity Docs.]
Karışık adresler tanımlanırken EIP-55 şartı benimsenir.
address ornekAdres = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; //Kaynak: Solidity Docs
Tam sayı değişmezleri, 0 ve 9 arasındaki rakamlardan meydana gelen sayılardır. Sekizli değişmezler Solidity'de desteklenmemektedir.
//DOĞRU KULLANIMLAR uint128 sayiOrnek = 2.5 + 0.5; //Toplamı bir tam sayı olduğundan sorunsuz çalışır. uint128 sayiOrnek2 = 3; uint128 sayiOrnek3 = 3.0; uint128 sayiOrnek4 = 5 / 2 + 2.5; //Toplamı bir tam sayı olduğundan sorunsuz çalışır. //HATALI KULLANIMLAR uint128 sayiHataliOrnek = 0.3; uint128 sayiHataliOrnek1 = 5.7; uint128 sayiHataliOrnek2 = 60 / 22;
Bilimsel sayı değerleri Solidity'de desteklenmektedir. Örneğin, A ve B iki sayı olsun(aynı da olabilir) AeB
şeklinde bir sayı tanımlaması yaptığımızda sonuç A * 10 ** B
yani A çarpı 10 üzeri B olacaktır.
int bilimselGosterim = 2e10;//2 * 10 üzeri 10 int bilimselGosterim2 = 2e1;//2 * 10 üzeri 1 = 20 int bilimselGosterim3 = -3e2;//-3 * 10 üzeri 2 = -300
Solidity'de sayılar 0 ile başlamazlar. Örneğin 0.4
sayısını kullanmak istediğimiz zaman .4
şeklinde tanımlama yapmamız gerekmektedir.
int ornekCarpim = .5 * 8; // 8 ile 0.5 çarpımı => 4
Sayı değişmezleri birbirleriyle bir işlemde kullanılacakları zaman işlemlerin sonuçlarının öncelikleri önemlidir. Örneğin uint128
türünde bir b
değeri elde etmek için bazı işlemler yapıyor olalım. b
değeri sonuç olarak tam sayı çıkıyor dahil olsa işlem önceliği kuralları uygulanmadığı için karşımıza bir hata çıkacaktır.
//Değişmez bir a sayısı uint128 a = 1; // b sayısı aşağıdaki şekilde elde edilmek istendiğinde HATA fırlatır! uint128 b = 2.5 + a + 0.5; //Benzer olarak bu şekilde kullanılabilir. uint128 bRevizeEdilmis = (2.5 + 0.5) + a;
2.5 + a
bir ondalıklı sayı olduğu için ETH sanal makinesi bu kodu kabul etmeyecektir. Benzer olarak (2.5 + 0.5) + a
bir kod kullanarak tanımladığımızda önce parantez içerisi toplandığı için çıkan sayı istenen türde yani uint
olacaktır. Sonrasında yine aynı türdeki a
ile topladığımızda bir sorun çıkmayacaktır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract DegismezlerLiteralsSozlesmeOrnegiSayilar { //DOĞRU KULLANIMLAR uint128 sayiOrnek = 2.5 + 0.5; //Toplamı bir tam sayı olduğundan sorunsuz çalışır. uint128 sayiOrnek2 = 3; uint128 sayiOrnek3 = 3.0; uint128 sayiOrnek4 = 5 / 2 + 2.5; //Toplamı bir tam sayı olduğundan sorunsuz çalışır. //HATALI KULLANIMLAR // uint128 sayiHataliOrnek = 0.3; // uint128 sayiHataliOrnek1 = 5.7; // uint128 sayiHataliOrnek2 = 60 / 22; int bilimselGosterim = 2e10;//2 * 10 üzeri 10 int bilimselGosterim2 = 2e1;//2 * 10 üzeri 1 = 20 int bilimselGosterim3 = -3e2;//-3 * 10 üzeri 2 = -300 int dagitikSayi1 = 589_000; //589000 int dagitikSayi2 = 0x2efff_abde; // 12616444894 int dagitikSayi3 = 589_20341; //58920341 int ornekCarpim = .5 * 8; // 8 ile 0.5 çarpımı => 4 //Değişmez bir a sayısı uint128 a = 1; // b sayısı aşağıdaki şekilde elde edilmek istendiğinde hata fırlatır. uint128 b = 2.5 + a + 0.5; //Benzer olarak bu şekilde kullanılabilir. uint128 bRevizeEdilmis = (2.5 + 0.5) + a; //Sayıları almak için kullandığımız fonksiyon. function get() public view returns(int){ return ornekCarpim;
Metin değişmezleri(string literals), tek ya da çift tırnak içerisine yazılabilen karakterlerdir. String değişmezleri, yalnızca ASCII karakterlerini içerebilirler. String değerler arasında boşluk bırakılarak ayrı ayrı yazılabildiği gibi birbirlerine eklenerek de kullanılabilir. Örnek koda baktığımızda "solidity" "egitimi"
ile "solidityegitimi"
aynı değere eşittir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract DegismezlerLiteralsSozlesmeOrnegiString { string ciftTirnakString = "cift tirnak isareti"; string tekTirnakString = 'tek tirnak isareti'; string bosluklarlaAyrilmisString = "solidity" "egitimi"; //eşittir => "solidityegitimi
Ayrıca string değişmezleri, kaçış karakterlerini(escape characters) de desteklemektedir.
\<newline>
(diğer satıra atlar)\\
(ters slash)\'
(tek tırnak)\"
(çift tırnak)\n
(yeni satır açar ve oradan ilerler)\r
(carriage return)\t
(tab, 4 karakter boşluk bırakır)\xNN
(hex kaçış işareti)\uNNNN
(unicode kaçış işareti)
\xNN
hex değeri alır ve byte ekler. \uNNNN
Unicode değeri alır ve UTF-8 dizesi ekler.
EN: Unicode Literals
ASCII tarafından desteklenmeyen karakterlerin kullanılmasını sağlamak adına unicode
ön eki kullanılarak unicode karakterlerinin okunması ve kullanılması sağlanır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract DegismezlerLiteralsSozlesmeOrnegi { //HATALI KULLANIM! Ö, Ş gibi Unicode karakterler desteklenmediği için hata alacağız. string unicodeStringDegeri = "Ömer"; //DOĞRU KULLANIM! "unicode" ön ekini kullanarak UTF-8 formatındaki Unicode karakterleri sorunsuz kullanabiliriz. string unicodeStringDegeri = unicode"Ömer";
EN: Hexadecimal Literals
Hexadecimal Değişmezleri, hex
ön ekiyle kullanılır ve hex'BF'
ya da hex"BF"
şeklinde tek veya çoklu tırnak işaretleri ile kullanılabilr. Tırnakların içerisinde tanımlanacak olan değerler hexadecimal haneli olmalıdırlar yoksa sistem tarafından karşımıza hata fırlatılacaktır.
Hexadecimal değişmezleri _
ile byte sınırları arasında(byte boundaries) ayırıcı olarak kullanılabilir.
bytes memory hexOrnek = hex'0011'; bytes memory hexOrnek3 = hex'0011_FF'; bytes memory hexOrnek4 = hex'0011_FF_0F'; bytes memory hexOrnek5 = hex'0011_FF_0F_0F_0F';
Birden fazla hexadecimal değişmezler boşlukla ayrılabildiği gibi birbirlerine eklenerek de aynı değeri verecek şekilde kullanılabilirler.
hex"00112233" hex"44556677"
= hex"0011223344556677"
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract DegismezlerLiteralsSozlesmeOrnegi { //Fonksyion içerisinden hexOrnegini aldık function getHex() public pure returns(bytes memory){ bytes memory hexOrnek = hex"0F"; return hexOrnek; } //Bir diğer kullanım bytes hexOrnek2 = hex"0F"; //Memory kodu hata veriyor. function getHexDifferent() public view returns(bytes memory){ return hexOrnek2; }
Enums, Solidity'de kullanıcı tanımlı değer(user-defined type) oluşturmanın bir yoludur. Enum listeleri tanımlandıktan sonra kendisi dışındaki satırlarda değiştirilemez. Listeler en az bir eleman ile tanımlanabilir ve tanımlanan elemanlardan ilk eleman varsayılan elemandır.
Son olarak, listelerin maksimum ve minimum eleman sayısını type(ListeAdi).min
ve type(ListeAdi).max
ile alabiliriz. Ancak bu özellik her derleyici için geçerli değildir!
Listeler(Enums), 256 elemandan fazla elemana sahip olamaz.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract EnumListeSozlesmeOrnegi { enum Aksiyonlar { SolaGit, SagaGit, GeriyeGit, OneGit } Aksiyonlar secim; Aksiyonlar constant varsayilanSecim = Aksiyonlar.GeriyeGit; function GeriyeGitmesiniSagla() public { secim = Aksiyonlar.GeriyeGit; } function secimiAl() public view returns (Aksiyonlar) { return secim; } function varsayilanSecimiAl() public pure returns (uint) { return uint(varsayilanSecim); }
Bu yazımızda akıllı sözleşmelerde değer türlerinin(value types) büyük çoğunluğunu tamamlamış olduk. Bir sonraki yazımızda fonksiyon türleri ve kullanıcı tanımlı değer türlerini detaylı şekilde inceleyeceğiz.
Yorumunu Bırak
Yorumlar
0 Yorum yokHenüz yorum yapılmamış. İlk yorum yapan sen ol.