Solidity 1 — Temel Bilgiler

Engin UNAL
6 min readAug 11, 2022

Solidity programlama dili ve akıllı kontrat geliştirme hakkında temel bilgiler.

Daha önceki yazılarımda Ethereum Blockchain konusunda teknik bilgiler içeren yazılarım olmuştu. Bu yazı ve devamında yazmayı planladığım yazılarda işin daha çok programlama kısmına değinmeye çalışacağım. Solidity dili ile akıllı kontrat geliştirmeye ilk adımı atacak yazılımcılara veya meraklılara yardımcı olması açısından yazacağım bu yazılarda kendi öğrenme sürecimden yola çıkarak aldığım notlar üzerinden gideceğim. Öncelikle hızlıca temel kavramlara değinip devamında Solidity konusuna başlayalım.

Smart Contract

Smart Contract(Akıllı Kontrat), bir blockchain ağına kaydedilen ve buradan yürütülen değiştirilemez bilgisayar programlarıdır. Bir akıllı kontrat çalıştırıldığında elde edilen sonuç, çalıştırılma parametreleri ve çalışma anındaki Ethereum blockchain durumu değişmediğinde(state), herkes için aynıdır.

Akıllı kontrat yazarken genelde Solidity kullanılmakta fakat Vyper, Yul gibi seçenekler de var. Biz Solidity ile devam edeceğiz. Solidity ile yazdığınız bir akıllı kontrat derlendiğinde bytecode üretilir. Bytecode, düşük seviye makine kodlarıdır. EVM(Ethereum Virtual Machine) ortamında çalışır. EVM, bytecode verisini çalıştıran yazılımdır.

Akıllı kontrat, yazılıp blockhain sistemine gönderildiğinde(veya kaydedildiğinde) bir adres alır. Aldığı bu adres daha sonra akıllı kontrata erişmek ve onu çalıştırmak için kullanılır.

EOA ve Akıllı Kontrat Hesapları

Ethereum mimarisinde iki tip hesap vardır. Biri Cüzdan Adresi yani standart hesaplar(Externally Owned Account — EOA) diğeri ise Akıllı Kontrat Hesabı(Conract Account).

Metamask gibi wallet uygulamasında açtığınız hesaplar EOA olarak tanımlanır. Bu hesaplar bildiğimiz standart kullanımdaki ETH gönderip almak için kullanılan hesaplardır. Public/Private key çiftine sahiptir. Yani özel anahtara sahiptir, hesabın private key bilgisine sahip olan biri o hesaptaki tüm içeriğe sahip olacaktır.

Akıllı kontrat hesapları ise private key tarafından korunmaz tüm yönetim akıllı kontrat ile sağlanır. EOA gibi ETH gönderip alabilir. Bu adresler, akıllı kontrat Ethereum blockchain’e gönderildiğinde ve yayınlandığında oluşturulur ve değiştirilemez.

Akıllı kontratlar kendi kendilerine çalışmazlar bir EOA tarafından transaction başlatılmalıdır, devamında akıllı kontrat içinden başka bir akıllı kontrat da çağrılmış olabilir. Kontrat adreslerine ETH gönderilebilir veya adresteki akıllı kontrat çağırılarak bu tip alma gönderme işlemleri ona yaptırılabilir. Diğer yazılarda bu konuyu daha geniş inceleyeceğiz.

EVM

Ethereum sisteminin en fonksiyonel parçasıdır. Akıllı kontratların çalışması için Turing complete(veya ona yakın) mimaride çalışma ortamı sunar. EVM, validator veya node ismi verilen merkezi olmayan bileşenler tarafından çalıştırılır. Akıllı kontratların ilk yüklenmesinde transaction ile gönderilen kontrat kodları node’lar tarafından alınır ve yayınlanır. Devamında ise yani yayınlanmış ve adresi olan mevcut akıllı kontrat çağrılarında ise akıllı kontrat kodları node’lar tarafından EVM’de çalıştırılır ve sonuç yayınlanır.

Kendi içinde kapalı bir sisteme sahiptir yani EVM içerisinde akıllı kontrat çalıştırılırken dış dünyadaki bir web servisi veya web sayfasını çağıramazsınız. Sistem tamamen deterministik olarak çalışmaktadır.

Basitçe EVM’i network veya internet erişimi olmayan sanal makine olarak düşünebilirsiniz. Bu sanal makine içerisinde ise akıllı kontratlar çalıştırılır. JVM veya .NET runtime mantığına da benzer. Akıllı kontrat çalıştırıldığında bir değişikliğe neden olursa(ör:kendi içindeki değişkenlerde bir değişiklik olursa) state’i değişmiş olur ve bu yeni state blockchain’e kaydedilir.

Transaction

Transaction, bir EOA yani harici bir hesaptan herhangi bir hesaba yani EOA veya kontrat adresine gönderilen imzalanmış mesajlardır. Bunlar Ethereum ağına iletilir ve onay süreçlerinden sonra blokchain üzerinde kaydedilir. Kontrat hesapları bir transaction başlatamaz sadece EOA hesapları veya basitçe cüzdan hespları başlatabilir.

Blockchain state değişimi yapan bu işlemler öncelikle tüm ağa yayınlanır, devamında madenciler birikmiş bu mesajları alır ve onaylar. Ortaya çıkan son state değişikliğini ağın geri kalanına yayınlar.

Transaction üç nedenle kullanılır.

  • Bir hesaptan diğerine transfer işlemleri için.
  • Akıllı Kontrat yaratma işlemleri için. Transaction “to” adres değerine sıfır verilirse kontrat yaratan bir transaction işlemi anlamına gelir.
  • Akıllı Kontrat çalıştırma işlemleri için.

Ethereum mimarisinde akıllı kontrat kodları otonom olarak çalışmazlar yani kendi kendilerine çalışıp işlem yapamazlar. Bir EOA tarafından üretilip imzalanmış transaction ile çalıştırılırlar. Transaction içinde çağrılacak kontrat adresi(to)girilir ve ek olarak kontratın fonksiyon ve parametre verileri(data) de girilir bu şekilde transaction başlatılır ve kontrat çalıştırılır. Bir kontrat adresine transfer de yapılabilir, bunun için ise transaction içerisindeki value alanında transfer edilecek miktar Wei olarak verilmelidir.

Akıllı kontrat oluşturma işlemini basit bir görselle özetlersek:

Akıllı kontrat çağırma işlemi :

Solidity öğrenme sürecinde bu detaylar şimdilik yeterli, devamında Solidity nasıl bir dil? Nasıl kodlayacağız? Bunlara bakmaya başlayabiliriz.

Solidity Ön Bilgiler

Solidity, ilk olarak Gavin Wood tarafından ortaya atılmış ve sonrasında Christian Reitwiessner ve diğer geliştiriciler tarafından geliştirilmiştir. EVM üzerinde çalışan statik tipli, object oriented bir akıllı kontrat programlama dilidir. Yaygın olarak Ethereum dünyasında kullanılmakla beraber diğer blockchain mimarilerinde de kullanılır.

Bu dilde yazılan kodlar Solidity Compiler(solc) ile derlenerek EVM üzerinde çalışacak bytecode çıktısı üretir. Eğer geliştirilmiş olan akıllı kontrat, başka kontratlardan veya Web3 uygulamalarından çağırılıyorsa ABI çıktısı da üretilir. ABI konusuna birazdan değineceğim.

Öncelikle aşağıdaki gibi bir akıllı kontrat kodumuz olsun.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Deneme {
function hello() public pure returns(string memory) {
return "Merhaba";
}
}

Bu akıllı kontrat içinde hello isimli bir fonksiyonumuz var ve bu fonksiyon çağırıldığında “Merhaba” çıktısını dönmekte.

bytecode ve opcode

Akıllı kontrat derlendiğinde aşağıdaki bytecode çıktısını üretir.

608060405234801561001057600080fd5b5061017c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806319ff1d2114610030575b600080fd5b61003861004e565b60405161004591906100c4565b60405180910390f35b60606040518060400160405280600781526020017f4d65726861626100000000000000000000000000000000000000000000000000815250905090565b6000610096826100e6565b6100a081856100f1565b93506100b0818560208601610102565b6100b981610135565b840191505092915050565b600060208201905081810360008301526100de818461008b565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610120578082015181840152602081019050610105565b8381111561012f576000848401525b50505050565b6000601f19601f830116905091905056fea264697066735822122071eaf23c56253c69e9856650f4ed4dd0ecfe05a064fb57ff44d450040f26d59664736f6c63430008070033

Bu değer akıllı kontrat kodumuzun derlenmiş binary verisinin hexadecimal formatına çevrilmiş halidir. Bu veri Ethereum Blockchain’e gönderilecek yani yayınlanacak veridir. EVM bu veriyi alır ve çalıştırır.

ABI konusuna kadar olan kısım meraklısı için detay içeriyor bu bölümü geçiniz. Gerekli değildir.

Bytecode EVM’de nasıl çalışır kısa özetle geçeceğim.

EVM bir stack machine’dir. Kısaca stack machine tek tek girilen yani stack’e atılan komutları sondan itibaren alarak çalıştırır(LIFO). Örneğin 2 + 3 * 3 işlemini düşünelim. Bunu stack machine’de çalıştıracak şekilde düzenlersek 3 3 * 2 + şeklinde veririz. Yani 3 değerini al, 3 değerini al, çarp ve sonucu tut, 2 değerini al, topla. Stack’e bu işlemleri yazmak ve oradan okuman için PUSH ve POP talimatları kullanılır. PUSH ile veri eklenir POP ile çekilir. Şimdi bu kısa bilgi ile yukarıdaki bytecode’un ilk beş byte değerine bakalım.

6080604052

Bytecode değerlerinden opcode ismi verilen ve EVM üzerinde çalıştırılan düşük seviye talimatlar listesine ulaşılabilir. Her opcode 8-bit unsigned integer değerler olarak temsil edilir. Yukarıdaki kısa bytecode’un opcode karşılığı:

PUSH1 0x80 PUSH1 0x40 MSTOREya da daha açık görünümde:00:  6080 PUSH1 0x80 
02: 6040 PUSH1 0x40
04: 52 MSTORE

PUSH1, 1 byte’lık veriyi stack’e atar. Burada 0x80 ve 0x40 değerleri sonraki kullanım için stack’e atıldı. Sonraki adımda MSTORE(memory store), EVM memory yapısında veri tutmak için kullanılır. Buradaki işlemde assembly karşılığı: mstore(0x40, 0x80). Çalışma açılımı şöyle olur. 0x40 stack listemizde en üstteydi. Buradan çekilip memory adresi olarak atanır. Diğer stack değerimiz 0x80 ise kaydedilir. Yani 0x40 adresine 0x80 değeri yazılmış olur. Ve devamında stack temizlenir. Vs. bu şekilde stack machine verilen komutlara göre çalıştırma işlemini devam ettirir.

Bu kısa özetle birlkte bytecode opcode nedir bunlara değinmiş olduk. Low level programlama ile işimiz olmayacağından bunları hızlıca geçip ABI nedir? Şimdi bunu inceleyelim.

ABI (Application Binary Interface)

ABI, yazdığımız akıllı kontratın ve içindeki fonksiyonların diğer uygulamalar tarafından anlaşılabilmesini sağlamak için tasarlanmış bir arayüz formatıdır. Ethereum mimarisinde ABI, akıllı kontratın işlevlerini tanımlamak ve her işlevin argümanları nasıl kabul edeceğini ve sonucunu nasıl döndüreceğini açıklamak için kullanılır. Bunu aşağıdaki örnek akıllı kontrat kodumuzun ABI verisine bakarak inceleyelim.

Akıllı kontrat örneği:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Deneme {
function hello() public pure returns(string memory) {
return "Merhaba";
}
}

ABI çıktısı:

[
{
"inputs": [],
"name": "hello",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "pure",
"type": "function"
}
]

Açıkça görüleceği üzere ABI JSON dosyasında akıllı kontrat içindeki hello metodumuzla ilgili tüm bilgiler yeralmakta(girdi/çıktı bilgileri, fonksiyon isimleri vs). Bu kontratı çağıracak bir web3 uygulaması, ABI json verisini kullanarak akıllı kontrat içindeki fonksiyonları veya tüm yapıları görebilir ve çağırma işlemini bu şekilde kolayca yapabilir.

Solidity ile kodlama yapmak için genel anlamda yeterli ön bilgileri aldık. Diğer yazıda kodlama için editör kullanımı ve hemen ardından dilin kuralları konusunda bilgi vereceğim.

Teşekkürler, hoşçakalın.

Engin ÜNAL

--

--