Değer türleri(value types), her zaman bir değer döndüren değişkenlerin türleridir. Bunlar boolean, sayı(integer), adres(address), kontrat(contracts) vb türlerde karşımıza çıkmaktadır. Resmi dökümanda çok kapsamlı ve uzun şekilde anlatıldığı için parçalara bölünmüş şekilde birkaç yazıda akıllı sözleşme türlerini açıklayıp ardından örnekleyeceğim.
bool
değerler true
ya da false
değerlerini alabilmektedir. [ayr. bkz.] Bir şartın doğru ya da yanlış olduğunu belirtmek için bool
değerler kullanılmaktadır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract BoolValues { //Ödeme yapılıp yapılmadığı iki farklı değer alacağı için (true-false) bool türüyle tanımladık. bool odemeYapildiMi; }
!
➝ mantıksal olumsuzlama. Doğru ise yanlış, yanlış ise doğru döner.&&
➝ mantıksal "ve" bağlacı. İki değerin de "doğru" olması ile "doğru" döner||
➝ mantıksal "ya da" bağlacı. İki değerden biri "doğru" ise doğru döner==
➝ iki değer birbirine eşit mi? Eşitse "doğru" döner!=
(iki değer birbirine eşit değilse "doğru" döner)
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract BoolValues { //iki bool değerin hangi operatorlerle sorgunlandıgını inceleyelim function ikiBoolEsitMi(bool x, bool y) pure public returns(bool){ return x == y; } //x bool değeri true ise doğru olduğunu dönecektir. function DogruMu(bool x) pure public returns(bool){ return x; } /*x bool değeri true ise doğru olduğu için doğru değil şartı yanlış olacaktır. Bu ! işareti ile sağlanır*/ function DogruDegilMi(bool x) pure public returns(bool){ return !x; }
int
ve uint
, imzalı(signed) ve imzalanmamış(unsigned) iki sayı değerini belirtir. [ayr. bkz.] Sayı doğrusunun hem artı hem eksi tarafının olduğunu düşünecek olursak int
değerleri +
, -
ve 0
değerlerini alabilirken uint
yalnızca 0
ve +
değerleri alabilir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract OrnekSozlesme { //Pozitif ve 0 değerler tanımlanabilir. uint imzasizDegerler = 0; uint imzasizDegerler1 = 88; //-88 imzalı bir sayı olduğu için hata dönecektir. uint imzasizDegerler2 = -88; //Tüm tam sayı değerleri tanımlanabilir. int tumTamsayiDegerleri = 2; int tumTamsayiDegerleri1 = -888; int tumTamsayiDegerleri2 = 0; //Değerler tam sayı olmadığı için hata dönecektir. uint imzasizDegerler3 = 98.8; int tumTamsayiDegerleri4 = 88.8
int8
, uint8
, int
,uint
, int256
ve uint256
çeşitli uzunluklarda olabilmektedir. int
ve uint
için bir uzunluk sınırlaması yokken int8
, uint8
, int256
ve uint256
için belirli bir uzunluk sınırı vardır.
//Doğru değer int8 yeniSayi1 = 88; //Hatalı değer int8 yeniSayi1 = 888;
Operatörler:
- Karlışatırma operatörleri:
<=
,<
,==
,!=
,>=
,>
(bool
değer dönecektir) - Bit operatörleri:
&
,|
,^
(bitwise exclusive or),~
(bitwise negation) - Kaydırma operatörleri:
<<
(sola kaydırma operatörü),>>
(sağa kaydırma operatörü) - Aritmetik operatörler:
+
,-
, unary-
(yalnızca signed sayılar için),*
,/
,%
(modül),**
(üs alma operatörü)
contract SayiOperatorleri{ int256 sayi1 = 2; //Sayi1 değerinin 4 üssü alınır. (sayi1 üzeri 4) int booldeger1 = sayi1 ** 4; }
Herhangi bir programlama dilinde proje geliştirirken kodunuzda yer yer bazı şartlar belirtmeniz gerekir. Örnek olarak, karne notunu girmesini beklediğiniz kişinin not aralığı 0 ile 100 arasında olsun. Bu durumda kişi 105 ya da -5 değerini girememelidir. Bu ve benzeri durumları karşılaştırma operatörleri kullanarak sorgulamanız gerekir.
Bilgisayar programlamasında, bit düzeyinde bir işlem, bir bit dizisi, bir bit sayı dizisi veya bir ikili sayı (bir bit dizisi olarak kabul edilir) üzerinde, kendi bitlerinin düzeyinde çalışır. [ayr. bkz.]
Bit operasyonları, Solidity dilinde de kullanılmaktadır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract BitOperatorleri{ //Fonksiyon aracılığıyla şart kontrolü yapıyoruz. function kontrolFonksiyonu(int x, int y) pure public returns(bool){ //Bir sayının değilinin değili yine kendisi olacağında x == y şartında bool değer true dönecektir. //~(~x) = x return ~(~int256(x)) == int256(y); }
Kaydırma operatörleri, sağa kaydırma(right shift) ve sola kaydırma(left shift) olarak ikiye ayrılır. Kaydırma işlemlerinde işlemin uygulandığı bitler sağa ya da sola doğru kaydırılır.
Bir bit bloğu üzerinde sağa kaydırma işlemi uyguladığımız zaman o blok üzerindeki tüm bitler bir sağ pozisyona geçerler. En sağdaki bit kaybolur, en soldan bir adet 0 eklenir. [ayr. bkz.]
'x' harfine 1'lik sağa kaydırma işlemi uygulandığında her bit değeri bir sağa doğru kaydırılır. Yeni bir binary değeri elde edilir.
//Bu kod Solidity için geçerli değildir. Mantığın anlatılması için örneklenmiştir. char x = 'x'; // 01111000 char y = x >> 1; // 00111100
Bir bit bloğu üzerinde sola kaydırma işlemi uyguladığımız zaman o blok üzerindeki tüm bitler bir sol pozisyona geçerler. En soldaki bit kaybolur, en sağdan bir adet 0 eklenir. [ayr. bkz.]
//Bu kod Solidity için geçerli değildir. Mantığın anlatılması için örneklenmiştir. char x = 'x'; //01111000 char y = x << 1; // 11110000
Solidity için kaydırma operatörlerinin nasıl kullanıldığını gösteren örnek kod;
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract ShiftOperatorleri{ //Shift operatörleri. function soldanShiftOperasyonuUygula(uint256 x, uint256 y) pure public returns(uint256){ //x << y //İşemin sonucu --> x * 2 ** y (x çarpı 2 üzeri y) return x << y; } function sagdanShiftOperasyonuUygula(uint256 x, uint256 y) pure public returns(uint256){ //x >> y //İşemin sonucu --> x / 2 ** y (x bölü 2 üzeri y) return x >> y; } //HATALI KULLANIM! --> Bir kaydırma operasyonu unsigned(uint) değerler kullanılmadığında hata fırlatır. function sagdanShiftOperasyonuUygula(int x, int y) pure public returns(int){ //x >> y //İşemin sonucu --> x / 2 ** y (x bölü 2 üzeri y) return x >> y;
x << y
bir matematiksel tanım olanx * 2**y
'a eşittir..x >> y
ise benzer şekilde matematiksel tanım olanx / 2**y
'a eşittir ve sayıyı negatif sonsuza yuvarlamaya yarar.
Modulo, bir sayının diğer bir sayıya bölümünden kalanı verir ve %
işareti ile gösterilir. İki sayı pozitif olduğunda bölümden kalan bildiğimiz işlemler dahilinde uygulanır. Örneğin, 16 % 4 işleminin sonucu bölme sonrasında kalanın sonucunu yani 0'ı verir. 5 % 4(5 mod 4) işlemi de 1 sonucunu verir.
int256(16) % int256(4) == int256(0)
int256(5) % int256(4) == int256(1)
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract ModulOperatorleri{ function modulIslemiYap(int256 x, int256 y) pure public returns(bool){ //Modül işlemi sonucunda kalan yani sonuç 0 ise doğru dönecektir. if(int256(x) % int256(y) == int256(0)){ return true; } return false; } }
Bir sayının pozitif diğerinin negatif olduğu durumlarda modül alma işlemi değişkenlik gösterir. Solidity dili için inceleyecek olursak, a % b
için işlem sonucu a % b == -(-a % b)
olacaktır.
int256(-5) % int256(2) == int256(-1)
int256(5) % int256(-2) == int256(1)
int256(-5) % int256(-2) == int256(-1)
Üs alma işlemi yalnızca pozitif sayılar(unsigned) için geçerlidir. Üs alma sonucunda ise sonuç tabanın türündeki değerde yani uint
olacaktır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract UsAlma{ function usAlmaIslemiYap(uint256 x, uint256 y) pure public returns(uint256){ return x ** y; } }
- Üs alma işlemi yalnızca
uint
değerler için geçerlidir. - x üzeri 3 matematiksel ifade olarak x ** 3 'e eşittir.
- 0 üssü 0(0**0), Ethereum Sanal Makinesinde sonucunu 1 olarak verir.
address
, 20 byte uzunluğundaki Ethereum adresidir. address payable
ise adress
den farklı olarak gönderim ve transfer gibi bazı ek özelliklere sahiptir. payable
özelliğine sahip olmayan bir address Ethereum transferinden etkilenmez ancak address payable
bir Ethereum adresi, işlem sonucunda ETH transfer edebilir. Bu özelliğin payable
a bağlı olmasının sebebiyse her akıllı kontrat adresinin ETH transferine ihtiyaç duymamasındandır.
Örneğin, bir akıllı sözleşme yazdığımızı düşünelim. Bu sözleşmenin test sorularını başarılı cevaplayan öğrencilere ödül olarak bir miktar ETH vereceğini düşünelim. Burada her öğrencinin sahip olduğu adresin payable
olması gerekir ki ETH ödülünü alabilsin.
Adresler, balance,
transfer
, code
, codehash
gibi bazı taraflara sahiptir.
balance
, bir adreste bulunan ETH miktarını gösteren değerdir,transfer(uint amount)
, adrese transfer edilecek Wei miktarı işleminin yapıldığı fonksiyondur,<address>.codehash
(bytes32
), Ethereum Sanal Makinesinde bir hesabı tanımlayan Keccak-256 karma kodunun değeridir<address>.code
, kullanıldığı adresin Ethereum Sanal Makinesi bytecode değerinibytes memory
türünde verir.<address payable>.send(uint256 amount) returns (bool)
,payable
özelliğine sahip bir adrese(hesaba) para gönderme işlemi yapabildiğimiz ve ardındanbool
türünde dönüt alabildiğimiz fonksiyondur.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; /** * @title ParaIslemiSozlesmesi */ contract ParaIslemiSozlesmesi { function hesabimdanParaTransferEt() public payable { address payable gonderilecekHesapAdresi = payable(0xadasd); //test adresi gonderilecekHesapAdresi.transfer(200000000); }
Eğer transfer
fonksiyonları gönderimi yapacak hesapta yeterli miktarda ETH olmadan çağrılırsa hata dönecektir. Benzer olarak send
fonksiyonu ise hata mesajı yerine bool
türünde false
değeri dönecektir.
Send
fonksiyonu kullanırken bazı konulara dikkat etmek gerekir. Gönderim yapacak hesabın yeterli miktarda işlem için gerekli olan asgari miktarın belirtilip belirtilmediği gibi durumların kontrol edilmesi son derece önemlidir.
call
,delegatecall
andstaticcall
,bytes memory
değerini alarakbool
vebytes
türünde değer ya da değerler döndüren fonksiyonlardır.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; /** * @title OrnekCallFonksiyonu */ contract OrnekCallFonksiyonu{ function callFonksiyonuCagir() public returns(bool success, bytes memory returnData) { bytes memory payload = abi.encodeWithSignature("register(string)", "Isminiz"); return address(0xadasd).call(payload); }
Sağlanan gaz değerini {gas: 12321312}
değişkeni ile ayarlayabilirsiniz.
address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName"));
Benzer olarak değeri de değişterebilirsiniz.
address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));
delegatecall
fonksiyonu da benzer olarak kullanılır. Farkıysa diğer sözleşmelerde depolanan kütüphane kodlarını kullanmasıdır.staticcall
fonksiyonu,call
fonksiyonundan farklı olarak bir durum değişikliği yaşandığında işlemi geri çevirir.staticcall
,delegatecall
vecall
fonksiyonları Solidity dilinin tür güvenliğini tehdit eden düşük seviyeli fonksiyonlardır(low-level-functions) ve kullanılması zorda kalmadıkça tercih edilmemelidir.
gas
değişkeni call
,staticcall
ve delegatecall
fonksyionlarında mevcuttur. Ancak value
değişkeni yalnızca call
fonksiyonunda geçerlidir.
Sözleşme türleri, değişmezler(literals), listeler(enums), fonksiyon türleri(function types), referans türleri(reference types) ve dizilerin(arrays) de dahil olduğu diğer türleri bir sonraki yazımızda açıklayacağım. Görüşmek üzere!
Yorumunu Bırak
Yorumlar
0 Yorum yokHenüz yorum yapılmamış. İlk yorum yapan sen ol.