1. Anasayfa
  2. 100 Günde Solidity

🧵 #100GündeSolidity 082 – DeFi : Uniswap V2 Swap Nedir ve Nasıl Yapılır?

🧵 #100GündeSolidity 082 – DeFi : Uniswap V2 Swap Nedir ve Nasıl Yapılır?
Uniswap V2
0

DeFi : Uniswap V2 Swap Nedir ve Nasıl Yapılır?

Bu bültenimizde, popüler bir DeFi protokolü olan Uniswap V2’de swap işleminin nasıl gerçekleştirileceğini öğreneceğiz.

Merhaba,

#100GündeSolidity serisinde 82. bültenimize hoş geldiniz! Bu bültenimizde, popüler bir DeFi protokolü olan Uniswap V2’de swap işleminin nasıl gerçekleştirileceğini öğreneceğiz.

Solidity diline giriş yaparak temelleri detaylıca öğrendik ve bülten serimizin devamında uygulama, hacks ve test konularına değindik. Şimdi ise DeFi alanında popüler olan Uniswap V2’de swap işlemini öğrenerek bilgilerimizi genişletiyoruz.

Uniswap V2, Ethereum tabanlı bir DEX (Decentralized Exchange) protokolüdür. Kullanıcılar, Uniswap V2’de token alım satım işlemlerini gerçekleştirebilir ve bununla birlikte piyasa fiyatına göre otomatik olarak işlem yapabilirler. Bu bültenimizde, Uniswap V2’de swap işleminin ne olduğunu, nasıl gerçekleştirileceğini ve işlem ücretleri hakkında detaylı bilgiler vereceğiz.

Hadi başlayalım!

Uniswap V2 Swap

Uniswap V2 Swap, Uniswap V2 protokolünün en temel işlemlerinden biridir. Swap işlemi, bir kullanıcının bir tokeni diğerine dönüştürmek istediği zaman gerçekleştirilir. Bu işlem, Ethereum blok zinciri üzerinde doğrudan kullanıcı arasında gerçekleşir ve aracılar olmadan yapılır. Kullanıcılar, Uniswap V2’de swap işlemi yaparak tokenlerini piyasa fiyatına göre takas edebilirler.

Swap işlemi, kullanıcıların tokenlerini Uniswap V2’nin likidite havuzlarına eklemesiyle gerçekleştirilir. Uniswap V2’de, tokenlerin piyasa fiyatına göre oranı, likidite havuzuna katkı sağlayan token miktarına göre belirlenir. Bu sayede, kullanıcılar likidite sağlayarak swap işlemi yaparken piyasa fiyatına yakın bir fiyatla tokenlerini takas edebilirler.

Swap işlemi için kullanıcıların gas ücreti ödemesi gerekiyor. Bu ücret, swap işleminin hızı ve önceliği gibi faktörlere göre değişebilir. Uniswap V2, swap işlemleri için ücretlerin yüksek olmasını önlemek için işlem ücretlerini optimize etmektedir.

Uniswap V2 Swap işleminin detaylarına bir sonraki bölümde değineceğiz.

Swap İşlemi Nedir?

Swap işlemi, bir tokenin diğerine dönüştürüldüğü bir işlemdir. Swap işlemi, DeFi protokollerinde token alım satım işlemleri için kullanılır. Swap işlemi, doğrudan kullanıcı arasında gerçekleştirilir ve aracılar olmadan yapılır. Bu sayede kullanıcılar, swap işlemi yaparken aracı maliyetlerinden tasarruf ederler.

Swap işlemi için kullanılan tokenlerin, bir likidite havuzu içinde işlem görmesi gerekir. Likidite havuzu, kullanıcıların tokenlerini depolayabilecekleri bir konumdur ve işlem hacmini belirleyen faktördür. Swap işlemi yapmak için kullanıcılar, likidite havuzlarına tokenlerini ekleyerek piyasa fiyatına göre tokenlerini takas edebilirler.

Swap işlemi, Ethereum blok zinciri üzerinde gerçekleştirilir. Kullanıcılar, swap işlemi yapmak için gas ücreti ödemelidirler. Gas ücreti, swap işleminin hızı ve önceliği gibi faktörlere göre değişebilir. Swap işlemi için kullanılan gas ücreti, kullanıcının işlemi ne kadar hızlı gerçekleştirmek istediğine bağlıdır.

Uniswap V2 Swap işlemi de bir swap işlemidir ve Uniswap V2 protokolünün temel işlemlerinden biridir. Bir sonraki bölümde, Uniswap V2 Swap işleminin detaylarına değineceğiz.

Uniswap V2 Swap İşlemi Nasıl Gerçekleştirilir?

Uniswap V2 Swap işlemi, bir tokenin diğerine dönüştürüldüğü bir işlemdir ve Uniswap V2 protokolünde gerçekleştirilir. Uniswap V2 Swap işlemi, aşağıdaki adımlarla gerçekleştirilir:

1. Uniswap V2 arayüzüne erişin ve swap işlemi yapmak istediğiniz tokenleri seçin.

2. Swap işleminin yapılacağı likidite havuzunu seçin. Uniswap V2, farklı likidite havuzlarından swap işlemi yapma imkanı sunar.

3. Swap işlemi için gerekli olan tokenlerin miktarını belirleyin. Bu miktar, işlem hacmini belirleyen faktördür.

4. Swap işlemi için gas ücreti belirleyin. Gas ücreti, işlemi ne kadar hızlı gerçekleştirmek istediğinize bağlıdır.

5. Swap işlemi için onay verin. İşlem onayı, kullanıcının cüzdanından gerçekleştirilir.

Uniswap V2 Swap işlemi, likidite havuzlarının piyasa fiyatına göre oranını kullanarak tokenleri takas eder. Bu sayede kullanıcılar, piyasa fiyatına yakın bir fiyatla tokenlerini takas edebilirler.

Uniswap V2 Swap işlemi için gas ücreti, swap işleminin hızı ve önceliği gibi faktörlere göre değişebilir. Kullanıcılar, gas ücretlerinin optimize edilmesi için swap işlemi yapmadan önce gas ücretlerini kontrol edebilirler.

Uniswap V2 Swap işlemi, DeFi protokollerinde token alım satım işlemleri için kullanılan temel işlemlerden biridir.

Swap İşlemi İçin Gereken Adımlar Nelerdir?

Swap işlemi yapmak için aşağıdaki adımları takip etmeniz gerekmektedir:

1. Bir Ethereum cüzdanına sahip olun. Swap işlemi yapmak için bir Ethereum cüzdanına ihtiyacınız vardır. En popüler Ethereum cüzdanlarından bazıları MetaMask, Trust Wallet ve MyEtherWallet’tir.

2. İşlem yapmak istediğiniz tokenlere sahip olun. Swap işlemi yapmak için, işlem yapmak istediğiniz tokenlere sahip olmanız gerekir. Ethereum tabanlı bir token satın almak için Binance, Coinbase, Kraken veya diğer kripto para borsalarından satın alabilirsiniz.

3. Likidite havuzu seçin. Swap işlemi yapmak için likidite havuzlarını kullanmanız gerekir. En popüler likidite havuzlarından bazıları Uniswap, SushiSwap ve Curve’dir.

4. Token miktarını belirleyin. Swap işlemi için token miktarını belirlemeniz gerekmektedir. Bu miktar, işlem hacmini belirleyen faktördür.

5. Gas ücretini belirleyin. Swap işlemi için gas ücreti belirlemeniz gerekmektedir. Gas ücreti, işlemi ne kadar hızlı gerçekleştirmek istediğinize bağlıdır.

6. İşlemi onaylayın. Swap işlemini gerçekleştirmek için işlemi onaylamanız gerekmektedir. Bu işlem, kullanıcının Ethereum cüzdanı üzerinden gerçekleştirilir.

Swap işlemi yaparken, doğru tokenleri, likidite havuzunu ve gas ücretini belirlemek önemlidir. Ayrıca, işlem yapmadan önce gas ücretlerini kontrol etmek de faydalı olacaktır.

Swap İşlemi Ücretleri Nelerdir?

Swap işlemi yaparken, çeşitli ücretlerle karşılaşabilirsiniz. Bu ücretler, işlemi gerçekleştiren kişilerin ödemeleri gereken ücretlerdir. Swap işlemi ücretleri şunlardır:

1. Gas Ücretleri: Ethereum ağı üzerindeki tüm işlemler için gas ücreti ödenmesi gerekir. Gas ücreti, işlemin blok zincirindeki madenciler tarafından işlenmesi için ödenen ücrettir. Gas ücreti, işlem hızına ve talebe bağlı olarak değişebilir.

2. Spread Ücretleri: Spread, bir likidite havuzundaki satın alma ve satış fiyatları arasındaki farktır. Bu ücret, kullanıcının swap işlemi sırasında ödemesi gereken ücrettir. Spread ücreti, likidite havuzu tarafından belirlenir.

3. Komisyon Ücretleri: Bazı swap platformları, swap işlemi gerçekleştiren kişilere komisyon ücreti talep edebilir. Bu ücret, kullanıcının swap işlemi sırasında ödemesi gereken ek ücrettir.

Swap işlemi ücretleri, kullanıcının tercih ettiği swap platformuna ve işlem yapılan tokenlere bağlı olarak değişebilir. Bu nedenle, swap işlemi yaparken ücretleri kontrol etmek önemlidir. Ayrıca, düşük gas ücretleri için uygun zamanları seçmek, swap işlemi maliyetlerini azaltabilir.

Akıllı Sözleşme Örneği İNCELEME

// SPDX-License-Identifier: MI
pragma solidity ^0.8.17;


contract UniswapV2SwapExamples {
    address private constant UNISWAP_V2_ROUTER =
        0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;


    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;


    IUniswapV2Router private router = IUniswapV2Router(UNISWAP_V2_ROUTER);
    IERC20 private weth = IERC20(WETH);
    IERC20 private dai = IERC20(DAI);


    // Swap WETH to DAI
    function swapSingleHopExactAmountIn(
        uint amountIn,
        uint amountOutMin
    ) external returns (uint amountOut) {
        weth.transferFrom(msg.sender, address(this), amountIn);
        weth.approve(address(router), amountIn);


        address[] memory path;
        path = new address[](2);
        path[0] = WETH;
        path[1] = DAI;


        uint[] memory amounts = router.swapExactTokensForTokens(
            amountIn,
            amountOutMin,
            path,
            msg.sender,
            block.timestamp
        );


        // amounts[0] = WETH amount, amounts[1] = DAI amount
        return amounts[1];
    }


    // Swap DAI -> WETH -> USDC
    function swapMultiHopExactAmountIn(
        uint amountIn,
        uint amountOutMin
    ) external returns (uint amountOut) {
        dai.transferFrom(msg.sender, address(this), amountIn);
        dai.approve(address(router), amountIn);


        address[] memory path;
        path = new address[](3);
        path[0] = DAI;
        path[1] = WETH;
        path[2] = USDC;


        uint[] memory amounts = router.swapExactTokensForTokens(
            amountIn,
            amountOutMin,
            path,
            msg.sender,
            block.timestamp
        );


        // amounts[0] = DAI amount
        // amounts[1] = WETH amount
        // amounts[2] = USDC amount
        return amounts[2];
    }


    // Swap WETH to DAI
    function swapSingleHopExactAmountOut(
        uint amountOutDesired,
        uint amountInMax
    ) external returns (uint amountOut) {
        weth.transferFrom(msg.sender, address(this), amountInMax);
        weth.approve(address(router), amountInMax);


        address[] memory path;
        path = new address[](2);
        path[0] = WETH;
        path[1] = DAI;


        uint[] memory amounts = router.swapTokensForExactTokens(
            amountOutDesired,
            amountInMax,
            path,
            msg.sender,
            block.timestamp
        );


        // Refund WETH to msg.sender
        if (amounts[0] < amountInMax) {
            weth.transfer(msg.sender, amountInMax - amounts[0]);
        }


        return amounts[1];
    }


    // Swap DAI -> WETH -> USDC
    function swapMultiHopExactAmountOut(
        uint amountOutDesired,
        uint amountInMax
    ) external returns (uint amountOut) {
        dai.transferFrom(msg.sender, address(this), amountInMax);
        dai.approve(address(router), amountInMax);


        address[] memory path;
        path = new address[](3);
        path[0] = DAI;
        path[1] = WETH;
        path[2] = USDC;


        uint[] memory amounts = router.swapTokensForExactTokens(
            amountOutDesired,
            amountInMax,
            path,
            msg.sender,
            block.timestamp
        );


        // Refund DAI to msg.sender
        if (amounts[0] < amountInMax) {
            dai.transfer(msg.sender, amountInMax - amounts[0]);
        }


        return amounts[2];
    }
}


interface IUniswapV2Router {
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);


    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
}


interface IERC20 {
    function totalSupply() external view returns (uint);


    function balanceOf(address account) external view returns (uint);


    function transfer(address recipient, uint amount) external returns (bool);


    function allowance(address owner, address spender) external view returns (uint);


    function approve(address spender, uint amount) external returns (bool);


    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool);


    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}


interface IWETH is IERC20 {
    function deposit() external payable;


    function withdraw(uint amount) external;
}

Bu örnek, Uniswap V2 Swap işlemlerini gerçekleştiren bir akıllı sözleşme göstermektedir. Sözleşme, bir kullanıcının Ethereum (WETH), Dai (DAI) veya USDC token’larını Uniswap V2 üzerinde başka bir token ile değiştirmesine olanak tanır.

Sözleşme, iki tür işlemi destekler: “swapExactTokensForTokens” ve “swapTokensForExactTokens”. İlk işlem, kullanıcının belirtilen miktarda bir tokeni başka bir token ile değiştirmesine izin verir. İkinci işlem, kullanıcının belirli bir miktar başka bir token almak için gereken minimum miktarı belirlediği bir tokeni değiştirmesine olanak tanır.

Sözleşme, “swapSingleHopExactAmountIn”, “swapMultiHopExactAmountIn”, “swapSingleHopExactAmountOut” ve “swapMultiHopExactAmountOut” adlı dört işlemi destekler. İlk iki işlem, kullanıcının yalnızca tek bir token ile işlem yapmasına olanak tanırken, diğer ikisi birden fazla token ile işlem yapmasına olanak tanır.

Sözleşmenin başlangıcında, Uniswap V2 Router adresi, WETH adresi, DAI adresi ve USDC adresi gibi sabitler tanımlanmaktadır. Bu sabitler, sözleşmenin içinde kullanılan adresleri ve tokenleri tanımlamak için kullanılır.

Sonrasında, IUniswapV2Router ve IERC20 arayüzleri tanımlanır. Bunlar, Uniswap V2 Router ve tokenlerle etkileşime geçmek için gerekli işlevleri içerir.

Son olarak, sözleşme, kullanıcının belirtilen miktarlarda tokenları Uniswap V2’de başka bir tokenla değiştirmesini sağlayan işlevleri içerir. Bu işlevler, belirtilen miktarları transfer eder, Uniswap V2 Router’ın “swapExactTokensForTokens” veya “swapTokensForExactTokens” işlevlerini çağırır ve son olarak, alınan token miktarını kullanıcıya geri döndürür.

// SPDX-License-Identifier: MI
pragma solidity ^0.8.17;


import "forge-std/Test.sol";
import "forge-std/console.sol";


import "../src/UniswapV2SwapExamples.sol";


address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;


contract UniswapV2SwapExamplesTest is Test {
    IWETH private weth = IWETH(WETH);
    IERC20 private dai = IERC20(DAI);
    IERC20 private usdc = IERC20(USDC);


    UniswapV2SwapExamples private uni = new UniswapV2SwapExamples();


    function setUp() public {}


    // Swap WETH -> DAI
    function testSwapSingleHopExactAmountIn() public {
        uint wethAmount = 1e18;
        weth.deposit{value: wethAmount}();
        weth.approve(address(uni), wethAmount);


        uint daiAmountMin = 1;
        uint daiAmountOut = uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin);


        console.log("DAI", daiAmountOut);
        assertGe(daiAmountOut, daiAmountMin, "amount out < min");
    }


    // Swap DAI -> WETH -> USDC
    function testSwapMultiHopExactAmountIn() public {
        // Swap WETH -> DAI
        uint wethAmount = 1e18;
        weth.deposit{value: wethAmount}();
        weth.approve(address(uni), wethAmount);


        uint daiAmountMin = 1;
        uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin);


        // Swap DAI -> WETH -> USDC
        uint daiAmountIn = 1e18;
        dai.approve(address(uni), daiAmountIn);


        uint usdcAmountOutMin = 1;
        uint usdcAmountOut = uni.swapMultiHopExactAmountIn(
            daiAmountIn,
            usdcAmountOutMin
        );


        console.log("USDC", usdcAmountOut);
        assertGe(usdcAmountOut, usdcAmountOutMin, "amount out < min");
    }


    // Swap WETH -> DAI
    function testSwapSingleHopExactAmountOut() public {
        uint wethAmount = 1e18;
        weth.deposit{value: wethAmount}();
        weth.approve(address(uni), wethAmount);


        uint daiAmountDesired = 1e18;
        uint daiAmountOut = uni.swapSingleHopExactAmountOut(
            daiAmountDesired,
            wethAmount
        );


        console.log("DAI", daiAmountOut);
        assertEq(daiAmountOut, daiAmountDesired, "amount out != amount out desired");
    }


    // Swap DAI -> WETH -> USDC
    function testSwapMultiHopExactAmountOut() public {
        // Swap WETH -> DAI
        uint wethAmount = 1e18;
        weth.deposit{value: wethAmount}();
        weth.approve(address(uni), wethAmount);


        // Buy 100 DAI
        uint daiAmountOut = 100 * 1e18;
        uni.swapSingleHopExactAmountOut(daiAmountOut, wethAmount);


        // Swap DAI -> WETH -> USDC
        dai.approve(address(uni), daiAmountOut);


        uint amountOutDesired = 1e6;
        uint amountOut = uni.swapMultiHopExactAmountOut(amountOutDesired, daiAmountOut);


        console.log("USDC", amountOut);
        assertEq(amountOut, amountOutDesired, "amount out != amount out desired");
    }
}

Bu Solidity test sözleşmesi, UniswapV2SwapExamples.sol adlı bir sözleşmenin testini gerçekleştiriyor. Bu sözleşme, Uniswap v2 protokolü aracılığıyla token takası yapmayı gösteren örnekleri içeriyor. Sözleşmenin içindeki fonksiyonlar, belirli senaryolarda farklı token takaslarının gerçekleştirilmesini test ediyor.

Test sözleşmesi, Test.sol ve console.sol olmak üzere iki başka kütüphaneyi de içeriyor. Test.sol, UniswapV2SwapExamples.sol sözleşmesindeki fonksiyonların doğru çalıştığını doğrulamak için kullanılan bir kütüphanedir. Console.sol, testlerin konsola yazdırılması için kullanılan bir kütüphanedir.

Sözleşmede ayrıca WETH, DAI ve USDC adlı üç token’ın adresleri de sabit olarak tanımlanmıştır. Bunlar Ethereum ağındaki gerçek token adresleri ile eşleştirilmiştir.

setUp() fonksiyonu, test öncesi hazırlık işlemleri yapmak için kullanılır. Ancak bu test sözleşmesinde herhangi bir hazırlık işlemi yapılmamıştır.

testSwapSingleHopExactAmountIn(), testSwapMultiHopExactAmountIn(), testSwapSingleHopExactAmountOut() ve testSwapMultiHopExactAmountOut() fonksiyonları, farklı senaryolarda token takaslarının gerçekleştirilmesini test eder. Fonksiyonların içinde, öncelikle belirli token’lar için gerekli izinler verilir, ardından ilgili takas fonksiyonları çağrılır. Daha sonra, fonksiyon sonuçları ve öngörülen sonuçlar karşılaştırılır ve sonuçlar doğruysa test başarılı olarak geçer.

Bu test sözleşmesi, UniswapV2SwapExamples.sol sözleşmesindeki token takas fonksiyonlarının doğru çalıştığını doğrulamak için kullanılabilir.

SONUÇ BAĞLAMI

Bu bülten, Solidity programlama dili ve UniswapV2SwapExamples konusunda temel bilgileri içeren bir giriş niteliğindedir. Solidity programlama dilinin temel özellikleri, akıllı sözleşme oluşturma süreci ve UniswapV2SwapExamples ile ilgili basit örnekler sunulmuştur. Ayrıca, Solidity programlama dilinde birim testlerin nasıl yazılacağına ve UniswapV2SwapExamples konusunda birim testlerin nasıl oluşturulacağına da değinilmiştir. Böylece, Solidity ve UniswapV2SwapExamples ile ilgili temel kavramları öğrenmek isteyenler için faydalı bir kaynak oluşturulmuştur.

Solidity Programlama Dili Öğrenme yolculuğunuz hakkında daha iyi rehberlik almak için Solidity nedir? Ethereum Akıllı Sözleşmelerinin Dili Rehberi içeriğimize göz atın. Dilerseniz Yeni Başlayanlar için Solidity – Akıllı Sözleşme Geliştirme Hızlandırılmış Kursuna katılın.

Çalışmaya nereden başlayacağım diyenler için Blockchain ​​Developer Olmak İçin Yol Haritası içeriğine de muhakkak bakın.

Gelin aklınızdaki soruları SUPERPEER sohbetinde cevaplayalım.

Bu makaleyi okuduğunuz için teşekkürler! Bana destek olmak isterseniz;

Beni TwitterLinkedin ve YouTube‘da takip edin.

Kısa bir yorum bırakmayı UNUTMAYIN!

solidity101 - Solidity, 2015 yılında Christian Reitwiessner liderliğinde piyasaya sürülen, büyük harf kullanımına göre ikinci en büyük kripto para piyasası olan Ethereum tarafından oluşturulan yepyeni bir programlama dilidir.

Yazarın Profili

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir