Blockchain'in Kalbi: Smart Contract'ları Anlamak ve Pratikte Kullanmak

Blockchain'in Kalbi: Smart Contract'ları Anlamak ve Pratikte Kullanmak
Photo by Shubham Dhage / Unsplash

"Eğer... O Zaman" Dünyasına Hoş Geldin

Blockchain'i sadece kripto para transferi için kullandığını düşünüyorsan, asıl gücünü kaçırıyorsun. Blockchain'in gerçek devrimi, merkeziyetsiz uygulamalar (dApps) oluşturmamızı sağlayan smart contract'larda yatıyor. Bu yazıda, smart contract'ların nasıl çalıştığını, neden bu kadar güçlü olduklarını ve pratikte nasıl kullanabileceğini derinlemesine inceleyeceğiz.

Smart Contract Nedir ve Nasıl Çalışır?

Smart contract, temelde "eğer X olursa, o zaman Y yap" mantığıyla çalışan, blockchain üzerinde çalışan bir bilgisayar programı. Geleneksel kontratlardan farkı, bir avukata, mahkemeye veya üçüncü bir tarafa ihtiyaç duymadan kendini otomatik olarak yürütmesi.

Basit bir örnekle başlayalım: Bir kira kontratı düşün. Geleneksel dünyada, kiracı kira parasını banka havalesiyle gönderir, ev sahibi parayı alır, her şey insanların dürüstlüğüne ve banka sisteminin çalışmasına bağlıdır. Smart contract ile bu süreç şöyle işler:

1. Smart contract, blockchain üzerinde deploy edilir (örneğin Ethereum)
2. Kiracı, kira parasını smart contract'ın adresine gönderir
3. Para smart contract'ta "esir" kalır
4. Ayın 1'inde, smart contract otomatik olarak parayı ev sahibinin adresine transfer eder
5. Eğer kiracı para göndermezse, smart contract ev sahibine bildirim gönderebilir veya kapı kilidini devre dışı bırakabilir (eğer IoT cihazları bağlıysa)

Burada kritik nokta: Hiçbir banka, avukat veya aracı yok. Kod, kodun yazıldığı gibi çalışıyor ve kimse (ev sahibi dahil) bu süreci durduramıyor veya değiştiremiyor.

Solidity ile İlk Smart Contract'ını Yaz

Smart contract yazmak için en popüler dil Solidity. JavaScript'e benzer bir syntax'ı var ama blockchain'e özgü konseptleri içeriyor. Hadi basit bir merkeziyetsiz banka (DeFi'nin en temel hali) yazalım:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleBank {
    mapping(address => uint) private balances;
    
    event DepositMade(address indexed account, uint amount);
    event WithdrawalMade(address indexed account, uint amount);
    
    function deposit() public payable {
        require(msg.value > 0, "Deposit amount must be greater than 0");
        balances[msg.sender] += msg.value;
        emit DepositMade(msg.sender, msg.value);
    }
    
    function withdraw(uint amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        require(address(this).balance >= amount, "Contract has insufficient funds");
        
        balances[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
        emit WithdrawalMade(msg.sender, amount);
    }
    
    function getBalance() public view returns (uint) {
        return balances[msg.sender];
    }
}

Bu contract ne yapıyor?
1. Kullanıcılar para yatırabilir (deposit fonksiyonu)
2. Kendi paralarını çekebilir (withdraw fonksiyonu)
3. Bakiyelerini görebilir (getBalance fonksiyonu)
4. Tüm işlemler blockchain'de kalıcı olarak kaydedilir

Bu kodda dikkat etmen gereken birkaç önemli nokta:
require: Koşul kontrolü yapar, eğer koşul sağlanmazsa işlemi geri alır (revert)
msg.sender: İşlemi gönderen adres
msg.value: Gönderilen Ether miktarı
event: Blockchain dışı uygulamaların dinleyebileceği olaylar

Smart Contract'ları Test Etmek ve Deploy Etmek

Smart contract yazdın, sıra test etmekte. Geleneksel yazılımdan farklı olarak, blockchain'de bir kodu deploy ettikten sonra değiştiremezsin. Bu yüzden testler çok daha kritik.

Hardhat kullanarak test yazalım:

const { expect } = require("chai");

describe("SimpleBank", function() {
  it("Should deposit and update balance", async function() {
    const SimpleBank = await ethers.getContractFactory("SimpleBank");
    const bank = await SimpleBank.deploy();
    
    const [owner] = await ethers.getSigners();
    const depositAmount = ethers.utils.parseEther("1.0");
    
    await bank.deposit({ value: depositAmount });
    const balance = await bank.getBalance();
    
    expect(balance).to.equal(depositAmount);
  });
  
  it("Should fail withdrawal with insufficient balance", async function() {
    const SimpleBank = await ethers.getContractFactory("SimpleBank");
    const bank = await SimpleBank.deploy();
    
    await expect(
      bank.withdraw(ethers.utils.parseEther("1.0"))
    ).to.be.revertedWith("Insufficient balance");
  });
});

Testleri geçtikten sonra, contract'ı deploy etmek için:

npx hardhat run scripts/deploy.js --network goerli

Goerli, Ethereum'un test network'ü. Gerçek para kullanmadan contract'ını test edebilirsin.

Smart Contract Güvenliği: Paranı Kaybetmemen İçin Kritik Kurallar

Smart contract güvenliği sadece bir "iyi uygulama" değil, bir zorunluluk. 2022'deki Axie Infinity hack'inde 600 milyon dolar çalındı ve hepsi smart contract güvenlik açıklarından kaynaklandı.

Yapma bunları:
1. External call'lardan sonra state değiştirme: Reentrancy saldırısına davetiye çıkarır
2. Rastgele sayı üretmek için block.timestamp kullanma: Miner'lar timestamp'i manipüle edebilir
3. Kullanıcı input'larını validate etmeden kullanma: Integer overflow/underflow
4. Private değişkenlerin gizli olduğunu sanma: Blockchain'de her şey public

Güvenli contract yazmak için:
OpenZeppelin kütüphanelerini kullan
Slither veya Mythril ile static analysis yap
• Test coverage'in %90+ olsun
• Mümkünse formal verification yap

Real World Örnek: Uniswap V2 Core Contract'ını İncele

Teoride anladık, hadi gerçek dünyadan bir örneğe bakalım. Uniswap, DeFi'nin en popüler merkeziyetsiz borsası. İşte UniswapV2Pair contract'ının önemli bir kısmı:

function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
    require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
    (uint112 _reserve0, uint112 _reserve1,) = getReserves();
    require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
    
    uint balance0;
    uint balance1;
    {
    // scope for _token{0,1}, avoids stack too deep errors
    address _token0 = token0;
    address _token1 = token1;
    require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
    if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out);
    if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out);
    if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
    balance0 = IERC20(_token0).balanceOf(address(this));
    balance1 = IERC20(_token1).balanceOf(address(this));
    }
    uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
    uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
    require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
    {
    // scope for reserve{0,1}Adjusted, avoids stack too deep errors
    uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
    uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
    require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
    }
    _update(balance0, balance1, _reserve0, _reserve1);
    emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}

Bu kodda dikkat çeken noktalar:
lock modifier: Reentrancy koruması
require kontrolleri: Her durum için validation
K constant formülü: x * y = k, Uniswap'ın temel formülü
Event emission: Swap olayını log'luyor

Smart Contract'ların Sınırları ve Geleceği

Smart contract'lar güçlü ama her şeyin çözümü değil. Şu anki sınırlamaları:
Gas cost: Her işlem için ödeme yapman gerekiyor
Scalability: Ethereum'da saniyede ~15-30 işlem
Oracle problemi: Blockchain dışı verilere güvenli erişim
Privacy: Tüm işlemler public

Ancak gelecek vaat ediyor:
Layer 2 solutions: Arbitrum, Optimism ile daha düşük gas fee
zk-SNARKs: Privacy + scalability
Cross-chain interoperability

Şimdi Ne Yapmalısın?

Smart contract öğrenmek istiyorsan, şu adımları takip et:
1.
CryptoZombies'u bitir (ücretsiz Solidity tutorial)
2.
Hardhat kur ve local development environment'ını hazırla
3.
OpenZeppelin Contracts'ı incele
4. Testnet'te (Goerli) küçük projeler deploy et
5.
Uniswap GitHub'ını incele, nasıl çalıştığını anla

Unutma: Smart contract development'da en iyi öğrenme yolu, kod okumak ve yazmak. Başlangıçta karmaşık gelebilir ama her satır kod, blockchain'in nasıl çalıştığını daha iyi anlamana yardımcı olacak.

Blockchain sadece para transferi değil, programlanabilir güven. Smart contract'lar da bu gücü senin ellerine veriyor. Şimdi sıra sende - ilk contract'ını yaz ve blockchain'in gerçek potansiyelini keşfet.