← Öğrenmeye Dön

Gelişmiş DeFi Desenleri

Üretim ortamındaki DeFi protokolleri, temel akıllı sözleşme geliştirmenin ötesinde zorluklarla karşılaşır: MEV çıkarımı, ölçekte gaz maliyeti, karmaşık getiri stratejileri, merkeziyetsiz governance ve gerçek zamanlı izleme. Bu kılavuz, prototipleri üretim sistemlerinden ayıran desenleri ele alır.

MEV Koruması

Maximal Extractable Value (MEV), madencilerin ve doğrulayıcıların kâr için işlemleri yeniden sıralamasına, araya sokmasına veya sansürlemesine olanak tanır. Koruma olmadan kullanıcılarınız takaslarda sandviç saldırılarıyla, büyük emirlerde ön koşuyla (front-running) ve arbitraj fırsatlarında arka koşuyla (back-running) karşılaşır. Bugün MEV koruması, kullanıcıya dönük her DeFi protokolü için temel bir gerekliliktir.

Commit-reveal deseni, en etkili zincir üstü savunmadır. Kullanıcılar önce takas parametrelerinin bir hash'ini taahhüt eder (commit), ardından bir gecikmenin ardından açıklar (reveal) ve yürütür. Bu, parametreler taahhüt aşamasında gizli olduğundan ön koşuyu önler. Bunu takaslar arasında asgari gecikme zorunluluğu ve eski taahhütler için son tarih tabanlı geçerlilik süresiyle birleştirin.

Commit-reveal takas koruması
struct SwapParams {
    address tokenIn;
    address tokenOut;
    uint256 amountIn;
    uint256 minAmountOut;
    uint256 deadline;
    bytes32 commitment;
}

// Step 1: Commit (parameters hidden as hash)
function commitSwap(bytes32 commitment) external {
    require(block.number >= lastSwapBlock[msg.sender] + MIN_DELAY, "Too frequent");
    commitments[commitment] = block.number + COMMIT_DURATION;
}

// Step 2: Reveal and execute
function executeSwap(SwapParams calldata params, uint256 nonce)
    external nonReentrant
{
    bytes32 commitment = keccak256(abi.encode(params, nonce, msg.sender));
    require(commitments[commitment] != 0, "Invalid commitment");
    require(block.number >= commitments[commitment], "Reveal too early");
    require(block.number <= commitments[commitment] + 10, "Reveal too late");
    require(block.timestamp <= params.deadline, "Swap expired");

    delete commitments[commitment];
    uint256 amountOut = _executeSwap(params);
    require(amountOut >= params.minAmountOut, "Insufficient output");
}

Flash Loan Koruması

Flash loan'lar, bir saldırganın büyük bir miktar borç aldığı, protokolünüzü manipüle ettiği ve tek bir işlemde geri ödediği aynı blok içi saldırılara olanak tanır. En basit savunma, aynı blok içi etkileşimleri engellemektir: bir kullanıcı N bloğunda yatırım yaptıysa, N+1 bloğuna kadar çekim yapamaz.

Bu, aynı blokta yatırıp çekmeye hiçbir zaman ihtiyaç duymayan normal kullanıcıları etkilemeden atomik istismar döngüsünü kırar. Ek koruma için bilinen flash loan sağlayıcı adreslerinden oluşan bir engelleme listesiyle birleştirin.

Aynı blok etkileşim koruması
mapping(address => uint256) public lastInteractionBlock;

modifier noFlashloanExploit() {
    require(
        lastInteractionBlock[msg.sender] != block.number,
        "Same block interaction"
    );
    lastInteractionBlock[msg.sender] = block.number;
    _;
}

function deposit(uint256 amount) external noFlashloanExploit { /* ... */ }
function withdraw(uint256 amount) external noFlashloanExploit { /* ... */ }

Gelişmiş Gaz Optimizasyonu

Ölçekte gaz optimizasyonu, özel hatalar (custom errors) ve struct paketlemenin ötesine geçer. Depolama düzeni optimizasyonu, birden fazla ilgili alanı tek bir 32 baytlık slota paketler — balance (uint128), son güncelleme (uint64), çarpan (uint32) ve active bayrağı (bool) içeren bir UserInfo struct'ı 29 bayta sığar ve dört yerine tek bir slot kullanır.

Toplu işlemler, temel işlem maliyetini birden fazla kullanıcıya yayar. Alıcılar ve miktarlar dizileriyle yapılan tek bir batchDeposit çağrısı, N yerine tek bir token transferi gerçekleştirir ve ek her kullanıcı başına yaklaşık 21.000 gaz tasarrufu sağlar. Sıcak yollar için satır içi assembly ek yükü daha da azaltabilir — ancak yalnızca profilleme, tasarrufun okunabilirlik maliyetine değdiğini kanıtladığında kullanın.

Optimize edilmiş depolama ve toplu işlemler
// Single-slot struct: 29 bytes total
struct UserInfo {
    uint128 balance;        // 16 bytes
    uint64  lastUpdate;     //  8 bytes
    uint32  multiplier;     //  4 bytes
    bool    isActive;       //  1 byte
}

// Batch deposit — one transfer instead of N
function batchDeposit(
    address[] calldata recipients,
    uint256[] calldata amounts
) external {
    require(recipients.length == amounts.length, "Length mismatch");
    uint256 totalAmount = 0;
    for (uint256 i = 0; i < recipients.length; i++) {
        totalAmount += amounts[i];
        users[recipients[i]].balance += uint128(amounts[i]);
    }
    IERC20(token).transferFrom(msg.sender, address(this), totalAmount);
}

Otomatik Bileşik Kasalar (Auto-Compounding Vaults)

Otomatik bileşik kasalar, temel bir protokolden ödülleri otomatik olarak toplar ve yeniden yatırım yaparak bileşik faiz yoluyla efektif APY'yi artırır. Kullanıcılar, toplam stake edilen değere göre yatırımlarıyla orantılı paylar alır. Kasa topladıkça ve yeniden yatırım yaptıkça, her pay daha fazla temel token değerine ulaşır.

Harvest fonksiyonu oran sınırlıdır (örneğin saatte bir) ve ödülleri staking token'larına dönüştürüp yeniden yatırmadan önce bir performans ücreti alır. Pay tabanlı muhasebe, kullanıcıların bileşik döngüyü bozmadan istedikleri zaman yatırım yapıp çekim yapabilecekleri anlamına gelir.

Otomatik bileşik kasa çekirdeği
function deposit(uint256 amount) external nonReentrant {
    _harvest(); // Update share price before deposit

    uint256 shares = totalShares == 0
        ? amount
        : amount * totalShares / totalStaked();

    userShares[msg.sender] += shares;
    totalShares += shares;
    stakingToken.transferFrom(msg.sender, address(this), amount);
    _stake(amount);
}

function _harvest() internal {
    if (block.timestamp < lastHarvest + 1 hours) return;
    uint256 rewards = _claimRewards();
    if (rewards == 0) return;

    uint256 fees = rewards * performanceFee / 10000;
    rewardToken.transfer(owner(), fees);

    uint256 compound = _swapRewardForStaking(rewards - fees);
    _stake(compound);
    lastHarvest = block.timestamp;
}

Delta-Nötr Stratejiler

Delta-nötr stratejiler, fiyat riskini hedge ederken getiri kazandırır. Temel akış: bir lending protokolüne teminat yatır, buna karşılık stablecoin borç al, temel varlıktan daha fazla satın al, ardından long riskini dengelemek için bir short perpetual pozisyonu aç. Sonuç piyasa-nötrdür: fiyat yönünden bağımsız olarak lending getirisi, borçlanma farkı ve funding rate ödemeleri kazanırsınız.

Yeniden dengeleme (rebalancing), pozisyon sapması bir eşiği (örneğin %5) aştığında tetiklenir. Strateji, teminat değeri ile borç arasındaki oranı izler, nötrlüğü korumak için hedge ve kaldıracı ayarlar. Bu, en sermaye verimli DeFi stratejilerinden biridir, ancak likidasyon eşikleri ve funding rate tersine dönüşleri konusunda dikkatli risk yönetimi gerektirir.

Governance ve DAO

Zincir üstü governance, token sahiplerine protokol parametreleri üzerinde kontrol verir. OpenZeppelin'in Governor çerçevesi eksiksiz bir uygulama sunar: teklif oluşturma, ERC20Votes token'larıyla oylama, quorum gereksinimleri ve timelock yürütme. Standart kurulum 1 bloklık oylama gecikmesi, 1 haftalık oylama süresi ve %4 quorum kullanır.

Governance token'ı (ERC20Votes + ERC20Permit) delegasyonu destekler — sahipler token'larını transfer etmeden oy güçlerini devredebilir. Bu, meta-governance ve her teklifte aktif olarak oy kullanmadan yön üzerinde etki sahibi olmak isteyen kullanıcıların katılımını mümkün kılar. Tüm teklifler bir TimelockController üzerinden yürütülür ve topluluğa, onaylanmış bir değişikliğe katılmadıkları takdirde çıkış yapmaları için bir zaman aralığı verir.

Governor kurulumu
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";

contract CryptaCoreGovernor is
    Governor, GovernorSettings, GovernorCountingSimple,
    GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl
{
    constructor(IVotes _token, TimelockController _timelock)
        Governor("CryptaCoreGovernor")
        GovernorSettings(1, 50400, 0) // 1 block delay, ~1 week, 0 threshold
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) // 4% quorum
        GovernorTimelockControl(_timelock)
    {}
}

Zincir Üstü İzleme

Üretim ortamındaki DeFi protokolleri; TVL, yatırma/çekme hacimleri, aktif kullanıcılar ve APY için gerçek zamanlı izlemeye ihtiyaç duyar. Bir zincir üstü analitik sözleşmesi, günlük metrikleri kaydeder ve zincir dışı indeksleme için olaylar (events) yayınlar. Her yatırma ve çekme çağrısı ayrıca günlük sayaçları günceller ve size protokol sağlığının sürekli bir görünümünü verir.

Metrik sözleşmesi, herhangi bir tarih aralığı için günlük anlık görüntülerin bir dizisini döndüren bir getMetricsForPeriod fonksiyonu sunar. Zincir dışı sistemler (The Graph, Dune Analytics veya özel indeksleyiciler) panolar ve uyarılar için MetricsUpdated olaylarına abone olur. Anomalileri izleyin: ani TVL düşüşleri, olağandışı çekim desenleri veya devam eden bir istismara işaret edebilecek APY sapmaları.

Zincir üstü metrik takibi
struct DailyMetrics {
    uint256 totalDeposits;
    uint256 totalWithdrawals;
    uint256 activeUsers;
    uint256 totalValueLocked;
    uint256 averageAPY;
}

mapping(uint256 => DailyMetrics) public dailyMetrics; // day => metrics

function recordDeposit(address user, uint256 amount) external {
    uint256 currentDay = block.timestamp / 86400;
    dailyMetrics[currentDay].totalDeposits += amount;
}

function getMetricsForPeriod(uint256 startDay, uint256 endDay)
    external view returns (DailyMetrics[] memory)
{
    uint256 length = endDay - startDay + 1;
    DailyMetrics[] memory metrics = new DailyMetrics[](length);
    for (uint256 i = 0; i < length; i++) {
        metrics[i] = dailyMetrics[startDay + i];
    }
    return metrics;
}
TipSorununuzu çözen en basit desenle başlayın. MEV koruması, otomatik bileşikleme ve delta-nötr stratejiler önemli ölçüde karmaşıklık katar. Önce güvenli bir temel sürüm yayınlayın, ardından kullanım arttıkça ve her ekleme için denetim (audit) kapsamınız oldukça gelişmiş özellikleri katmanlayın.