Solidity 7 — Logs ve Events

Engin UNAL
4 min readNov 1, 2022

Veri yönetimi konusunun devamında ve onunla da ilgili bir konu olan Logs ve Events yapılarını göreceğiz. Öncelikle Logs devamında Event başlıklarını inceleyeceğiz. Birbiriyle ilişkili konular olduğundan kavramlara değinilip devamında iki konu birleştirilip örnekle yazı sonlanacaktır.

Logs

EVM, logs isminde özel veri yapısına sahiptir. Blockchain üzerinde gerçekleşen işlemleri bu özel veri yapısına kaydeder. İndeksli bir veri yapısı olan logs’a kaydedilen verilere akıllı kontratlar erişemez.

Ethereum node’ları üzerinden logs verilerine erişilebilir ve arama yapılabilir. Logs verileri front-End uygulamaları veya blockchain dışındaki uygulamalar için değerlidir. Logs yayınlarını takip ederek değişiklikleri dinlerler ve yapılan işlem ile ilgili bilgilere ulaşabilirler.

Bu neden önemli? Örneğin bir web uygulaması yazdınız ve burada bir transfer işlemi gerçekleşiyor olsun. Transfer sonucu sonunda ekran güncellenmeli. Tam bu aşamada logs kayıtları önemlidir bu kayıtlar dinlenerek transaction işleminin tamamlandığı bilgisi alındığında sayfa güncellenebilir. Başka bir örnekle devam edelim. Bir web servis yazdınız ve bunun görevi bir akıllı kontratı takibe almak ve onda yapılan işlemlere göre başka bir kontratı çalıştırmak olsun. Temel olarak web servisimizin yapması gereken en kritik iş takip ettiği kontrat işlemlerini dinlemek ve buna göre aksiyon almaktır. İşte bu dinleme işlemleri logs yapısı ile gerçekleşir.

Ethereum node’undan çekilmiş bir logs kaydı örneği:

{
"address": "0xb59f67a8bff5d8cd03f...",
"blockHash": "0x8243343df08b9751f5ca0c5f8c9c0460d83...",
"blockNumber": "0x117a05",
"data": "0x0000000000...0000000012a05f200",
"logIndex": "0x56",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa...",
"0x00000000000000000000000000b46c...",
"0x00000000000000000000000054a2d42a40f512..."
],
"transactionHash": "0xab059a62e22e230fe0f56d8555340a2...",
"transactionIndex": "0xac"
}

Topics değerleri indekslenmiş event verisini tutar. Data içerisinde ise indekslenmemiş event verilerini içerir. Buna events konusunda değineceğim.

Logs yapıları storage ile kıyaslandığında çok daha ekonomiktir. Bu nedenle eğer storage’da saklanması şart olmayan veya daha sonra okunmasına gerek olmayan veri saklanıyorsa bunu logs üzerinde almak gas ücretini önemli oranda düşürecektir.

Konuyu şu şekilde de özetleyebilirim: Web3 uygulamalarının veya merkezi olmayan uygulamaların(dApps) gereksinimlerinden biri de blockchain üzerinde gerçekleşen olaylardan haberdar olmaktır. Böylece uygulama kapsamına göre kullanıcıyla veya diğer uygulamalarla etkileşime girebilirler. Blockchain içerisinde gerçekleşen olayları logs yapılarından takip etmek mümkündür. Akıllı kontratlar bu yapılara veri gönderebilir ama okuyamaz. Okuma ve sorgulama işlemi blockchain node’ları üzerinden yapılmaktadır.

Events

Logs yapıları içinde tutulan veriler event verileridir. Logs yapısını bir veritabanı gibi düşünürsek events ise veri taşıyan satır gibi düşünülebilir. Solidity kodları ile event hazırlayıp gönderebiliriz yani logs’a event yazabiliriz fakat okuma yapamayız.

Peki bu ne işe yarıyor? Event yapılarıyla blockchain dışındaki yani dış dünyadaki uygulamaları tetikleme imkanı olmaktadır. Akıllı kontrat içinde yapılan bir işlemin herhangi bir web uygulamasına erişme şansı yok. Fakat event dinleyen bir web uygulamasının kontrat içindeki işlem ve değişiklikleri algılama imkanı olmaktadır. Bu köprü event ile kurulmaktadır. Kontrat kodlarında tanımlanan event ile istenilen veri gönderilir bu veri logs veritabanına kaydedilir. Yayınlanan event verisini herhangi bir uygulama dinleyebilir ve buna göre aksiyon alabilir.

Event içerisinde tanımlanan verinin indeksleme seçeneği bulunmaktadır. Indekslenmiş olarak işaretlenen veriler logs yapısında aranabilir ve filtrelenebilir tutulur. Bu şekilde logs üzerinde ilgili event verisini dinleyen veya arama yapan uygulama hızlıca indekslenmiş verilere erişebilir. İndekslenmemiş veriler abi encoded olarak saklanır ve decode edilmeleri gerekir. Indekslenmiş parametre tanımı limiti vardır, en fazla 3 adet yapılabilir.

Bu kadar teorik bilgi yeterli, events konusunu kod örneği ile daha net anlayabiliriz.

Bu örnek kodlamada AmountChanged isimli bir event tanımladık. Daha sonra changeAmount fonksiyonu içinden bu event’i kullandık. Emit ile event gönderimi yapılmakta, tanımlı olan parametre tiplerine göre event verisi dolurulup emit ile yayınlanmaktadır. Tanımladığımız event içine eski ve yeni state değerleri bulunmakta. Artık kontrat içindeki state değişkenimizin değişimleri dış dünya tarafından takip edilebilir ve buna göre aksiyon alınabilir.

Yukarıdaki kontrat kodu yayınlanıp çalıştırıldığında log’a yazılacak çıktı aşağıdaki gibi olacaktır. Örnek olarak changeAmount fonksiyonunu 123 değeri ile çağıracağım(HEX değeri : 0x7B). Üretilen log verisi aşağıdaki gibi olacaktır.

Topics[0], event tanımı hash değeridir. Buradaki örnekte AmountChanged event tanımladık bunun hash değeri : keccak256(“AmountChanged(uint, uint )”).

Topics[1], oldAmount değerini gösterir. İlk değeri 0 idi.

Topics[2], newAmount değerini yani 0x7b(123) gösterir.

Şimdi indexed tanımını bir parametreden kaldırıp tekrar yayınlayalım. Event tanımı aşağıdaki gibi olsun.

event AmountChanged(uint oldAmount, uint indexed newAmount);

changeAmount fonksiyonunu yine aynı değerle çağırdığımızda log kaydı aşağıdaki gibi olacaktır.

Görüleceği üzere artık üç adet Topics yok. Indekslemediğimiz oldAmount topics içine eklenmedi. Fakat Data içerisinde bulunmakta.

Son örnekle konuyu sonlandıralım.

Bu örnekte AccountCreated isimli bir event tanımladık. Kontratın amacı bir banka hesabı oluşturmak ve hesap oluşma işlemi sonrasında bir event yayınlamaktır. Kodlamada herhangi bir güvenlik kontrolü, önlem vs. yoktur, sadece event örneği içindir. ceateAccount fonksiyonu içinde BankAccount nesnesi yaratılır ve accounts dizisine eklenir. Devamında AccountCreated event emit edilerek işlem sonlanır.

Bu kodlamada görüleceği üzere BankAccount tipinde bir değişken ve uint256 tipinde bir değişken verisinden event oluşturduk. Bu şekilde event yayınlaması da mümkündür. Bunun logs tarafındaki karşılığı aşağıdaki gibi olacaktır.

Topics[0], BankAccount içindeki veri yerine hash değeri geldi. Bu nedenle kompleks tiplerle çalışmak yerine sistem tipleri kullanılması önerilir.

Topics[1], uint256 tipinde dizi uzunluğunu ifade eden veri(tek eleman ekledik bu durumda : 1).

Örnekler kullanıma göre artırılabilir. Tanım ve kullanımı gayet kolaydır.

Tanım :

event EventAdı(tip tipAdı, …);

Event yayınlama :

emit EventAdı(değer1, …);

Event dinleyen web3 uygulamaları örneklerine sonraki yazılarda değinmek üzere okuduğunuz için teşekkürler.

Serideki diğer yazılar:

Temel Bilgiler

İlk Akıllı Kontrat ve Remix

Tipler

Contract ve Function

Interface ve Library

Veri Yönetimi

Engin Ünal

--

--