Day 87/100 : Exploring DeFi with Uniswap V3 Swap Examples 🚀

#100DaysOfSolidity 087 DeFi : “Uniswap V3 Swap Examples”

Solidity Academy
10 min readSep 1, 2023

Welcome to Day 87 of our #100DaysOfSolidity series!

#100DaysOfSolidity 087 DeFi : “Uniswap V3 Swap Examples”

Today, we’re diving deep into the world of Decentralized Finance (DeFi) with a focus on Uniswap V3 Swap examples. 🦄💰

Buy me a Coffee

Uniswap has been a game-changer in the DeFi space, allowing users to swap various tokens in a decentralized and permissionless manner. With the release of Uniswap V3, we have even more powerful tools at our disposal for optimizing our trades. In this article, we will explore some technical aspects of Uniswap V3 swaps, provide code examples, and highlight the uniqueness of this powerful decentralized exchange protocol.

Understanding Uniswap V3

Before we dive into examples, let’s quickly recap what Uniswap V3 is all about.

Uniswap V3 is an upgrade to the popular Uniswap V2 protocol, introducing concentrated liquidity and multiple fee tiers. This allows liquidity providers to be more strategic with their positions and traders to have more control over their swaps. Uniswap V3 is a technical marvel, and understanding its inner workings is essential for DeFi developers.

Concentrated Liquidity

In Uniswap V3, liquidity providers can concentrate their funds within specific price ranges. This means that instead of providing liquidity across the entire price spectrum, you can choose to provide liquidity in a narrower range. This is especially useful in markets with high volatility.

Multiple Fee Tiers

Uniswap V3 introduces multiple fee tiers, enabling liquidity providers to earn fees at different rates depending on the range they provide liquidity to. This allows LPs to optimize their fee earnings based on market conditions.

Uniswap V3 Swap Examples

Now that we have a basic understanding of Uniswap V3, let’s dive into some technical examples.

Example 1: Swap Tokens Using Web3.js

In this example, we will use Web3.js, a popular JavaScript library for interacting with Ethereum, to swap tokens on Uniswap V3.

// Import necessary libraries
const Web3 = require('web3');
const { ethers } = require('ethers');
const { abi, bytecode } = require('uniswap-v3-core/artifacts/contracts/UniswapV3Swap.sol/UniswapV3Swap.json');
// Initialize Web3.js
const web3 = new Web3('YOUR_ETHEREUM_NODE_URL');
// Create a signer
const provider = new ethers.providers.Web3Provider(web3.currentProvider);
const signer = provider.getSigner();
// Deploy the UniswapV3Swap contract
const factory = new ethers.ContractFactory(abi, bytecode, signer);
const uniswapV3Swap = await factory.deploy();
// Perform a token swap
const tokenIn = '0xTokenInAddress';
const tokenOut = '0xTokenOutAddress';
const amountIn = ethers.utils.parseUnits('1', 18); // 1 token with 18 decimals
const amountOutMin = ethers.utils.parseUnits('0', 18); // Minimum amount of tokenOut to receive
const deadline = Math.floor(Date.now() / 1000) + 60 * 10; // 10 minutes from now
const recipient = '0xRecipientAddress';
const tx = await uniswapV3Swap.swapExactTokensForTokens(
amountIn,
amountOutMin,
[tokenIn, tokenOut],
recipient,
deadline
);
console.log('Swap transaction hash:', tx.hash);

This code snippet demonstrates how to swap tokens using Uniswap V3 via Web3.js. Make sure to replace `’YOUR_ETHEREUM_NODE_URL’`, `’0xTokenInAddress’`, `’0xTokenOutAddress’`, and `’0xRecipientAddress’` with the appropriate values.

Example 2: Python Script for Uniswap V3 Swaps

Python is another popular language for interacting with Ethereum. Let’s look at how you can perform Uniswap V3 swaps using Python and the `web3.py` library.

from web3 import Web3
from eth_account import Account
from uniswapv3 import UniswapV3
# Connect to Ethereum
w3 = Web3(Web3.HTTPProvider('YOUR_ETHEREUM_NODE_URL'))
# Your private key and sender address
private_key = 'YOUR_PRIVATE_KEY'
sender_address = '0xYourAddress'
# Initialize the UniswapV3 class
uniswap = UniswapV3(private_key=private_key, provider=w3)
# Specify swap details
token_in = '0xTokenInAddress'
token_out = '0xTokenOutAddress'
amount_in = 1000000000000000000 # 1 ETH in Wei
amount_out_min = 0
deadline = 3600 # 1 hour from now
# Perform the swap
tx_hash = uniswap.swap_tokens(token_in, token_out, amount_in, amount_out_min, deadline)
print('Swap transaction hash:', tx_hash)

This Python script uses the `uniswapv3` library to execute a Uniswap V3 swap. Replace `’YOUR_ETHEREUM_NODE_URL’`, `’YOUR_PRIVATE_KEY’`, `’0xTokenInAddress’`, `’0xTokenOutAddress’`, and other values as needed.

Uniqueness of Uniswap V3

Uniswap V3 stands out in the DeFi space for several reasons:

1. Concentrated Liquidity Management

The ability to concentrate liquidity within specific price ranges is a game-changer. It allows liquidity providers to maximize their capital efficiency and potentially earn higher fees.

2. Multiple Fee Tiers

With Uniswap V3, liquidity providers can choose from multiple fee tiers, which enables them to adapt to market conditions. This flexibility is crucial for LPs looking to optimize their fee earnings.

3. Capital Efficiency

Uniswap V3 offers improved capital efficiency by allowing LPs to provide liquidity where they think it’s most needed. This reduces the opportunity cost of holding funds in a non-optimized manner.

4. Improved Slippage Control

Traders using Uniswap V3 have more control over slippage due to the concentrated liquidity pools. This is particularly important in volatile markets where large price swings can lead to significant losses.

🚀 Report : Uniswap V3 Swap Examples 🦄

In the rapidly evolving world of decentralized finance (DeFi), Uniswap stands tall as a pioneer and a game-changer. Uniswap V3, with its innovative features, has taken decentralized exchange to a whole new level. In this report, we will explore the technical intricacies of Uniswap V3, focusing on swap examples using Solidity, smart contracts, and emojis! 🌐🔍

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

contract UniswapV3SwapExamples {
ISwapRouter constant router =
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);

function swapExactInputSingleHop(
address tokenIn,
address tokenOut,
uint24 poolFee,
uint amountIn
) external returns (uint amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);

ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});

amountOut = router.exactInputSingle(params);
}

function swapExactInputMultiHop(
bytes calldata path,
address tokenIn,
uint amountIn
) external returns (uint amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);

ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: path,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0
});
amountOut = router.exactInput(params);
}
}

interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint deadline;
uint amountIn;
uint amountOutMinimum;
uint160 sqrtPriceLimitX96;
}

/// @notice Swaps amountIn of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as ExactInputSingleParams in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(
ExactInputSingleParams calldata params
) external payable returns (uint amountOut);

struct ExactInputParams {
bytes path;
address recipient;
uint deadline;
uint amountIn;
uint amountOutMinimum;
}

/// @notice Swaps amountIn of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as ExactInputParams in calldata
/// @return amountOut The amount of the received token
function exactInput(
ExactInputParams calldata params
) external payable returns (uint amountOut);
}

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;
}

Understanding Uniswap V3

Uniswap V3 is a significant upgrade from its predecessor, Uniswap V2. It introduces several key features that make it unique and powerful. Let’s dive into these features using our Solidity code as a reference. 📈💡

1. Concentrated Liquidity

Uniswap V3 allows liquidity providers to concentrate their funds within specific price ranges. This means they can provide liquidity in a narrower range, optimizing their capital efficiency and reducing exposure to volatile price swings. The code provided demonstrates how to perform a single-hop swap with concentrated liquidity. 💰💧

function swapExactInputSingleHop(
address tokenIn,
address tokenOut,
uint24 poolFee,
uint amountIn
) external returns (uint amountOut) {
// Transfer tokens and approve the router
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);
// Define swap parameters
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});
// Execute the swap
amountOut = router.exactInputSingle(params);
}

2. Multiple Fee Tiers

Uniswap V3 introduces multiple fee tiers, allowing liquidity providers to choose the fee rate that suits their strategy. This flexibility is a significant advantage in a dynamic market. Unfortunately, our code example focuses on single-hop swaps, so we won’t delve deeper into this feature here. 📊🤝

Performing Uniswap V3 Swaps

Our Solidity code showcases two essential functions for performing swaps on Uniswap V3: `swapExactInputSingleHop` and `swapExactInputMultiHop`. These functions enable users to execute swaps using smart contracts, adding another layer of automation to DeFi. 🔄🤖

Single-Hop Swap

The `swapExactInputSingleHop` function is designed for simple, one-step swaps. Users specify the input and output tokens, the pool fee, and the amount to be swapped. The function then transfers the tokens, approves the router, and executes the swap. It’s an efficient way to trade assets within a specific price range. 🎯📉

Multi-Hop Swap

The `swapExactInputMultiHop` function is more versatile, allowing users to define a path of tokens for multi-hop swaps. While this function is included in the code, we did not provide a detailed example. However, it’s a crucial feature for more complex trading strategies. 🌐🚀

In Conclusion; Uniswap V3 is a technical masterpiece that empowers liquidity providers and traders alike. With features like concentrated liquidity and multiple fee tiers, it’s a driving force in the DeFi landscape. Our Solidity code examples showcase how to perform swaps on this cutting-edge platform.

Remember, DeFi is a space where innovation never sleeps, and security is paramount. Always conduct thorough research and consider consulting experts before diving into the world of DeFi. 🛡️🔒

In the world of decentralized finance, Uniswap V3 shines as a beacon of innovation. Its unique features, combined with smart contract capabilities, open up a world of possibilities for DeFi enthusiasts. 🌟🌍

Stay updated, stay secure, and keep exploring the fascinating world of DeFi! 🚀🔍

📊 Report : Uniswap V3 Swap Testing 🧪

In the world of blockchain and decentralized finance (DeFi), testing is a critical phase to ensure the reliability and functionality of smart contracts. This report delves into a unique testing scenario for Uniswap V3 swap operations using Solidity, emojis, and insightful analysis. Let’s embark on this testing journey! 🚀🧪

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

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

import "../src/UniswapV3SwapExamples.sol";

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

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

UniswapV3SwapExamples private uni = new UniswapV3SwapExamples();

function setUp() public {}

function testSingleHop() public {
weth.deposit{value: 1e18}();
weth.approve(address(uni), 1e18);

uint amountOut = uni.swapExactInputSingleHop(WETH, DAI, 3000, 1e18);

console.log("DAI", amountOut);
}

function testMultiHop() public {
weth.deposit{value: 1e18}();
weth.approve(address(uni), 1e18);

bytes memory path = abi.encodePacked(
WETH,
uint24(3000),
USDC,
uint24(100),
DAI
);

uint amountOut = uni.swapExactInputMultiHop(path, WETH, 1e18);

console.log("DAI", amountOut);
}
}

Understanding the Test Scenario

The code provided serves as a testing framework for Uniswap V3 swap examples. It leverages the popular Forge library for testing smart contracts on the Ethereum blockchain. The contract `UniV3Test` is designed to interact with the `UniswapV3SwapExamples` contract, which facilitates Uniswap V3 swaps. 🧰🛠️

Test Tokens

Before we delve into the tests, it’s essential to understand the test tokens used in this scenario:

- WETH (Wrapped Ether): This represents Ether wrapped as an ERC-20 token. It’s commonly used in DeFi protocols.
- DAI: A stablecoin on the Ethereum network.
- USDC (USD Coin): Another stablecoin, widely used in DeFi.

Test 1: Single-Hop Swap

The first test, named `testSingleHop`, simulates a single-hop swap from WETH to DAI. It involves the following steps:

1. Depositing 1 Ether worth of WETH into the contract.
2. Approving the Uniswap V3 contract to access WETH.
3. Executing a single-hop swap from WETH to DAI with a pool fee of 3000.

The test aims to verify the correctness of the single-hop swap function and confirm the amount of DAI received.

Test 2: Multi-Hop Swap

The second test, `testMultiHop`, demonstrates a multi-hop swap using a predefined path. The steps involved are as follows:

1. Depositing 1 Ether worth of WETH into the contract.
2. Approving the Uniswap V3 contract to access WETH.
3. Defining a swap path from WETH to USDC to DAI.
4. Executing a multi-hop swap along the defined path.

The goal of this test is to ensure that the multi-hop swap function functions correctly, confirming the amount of DAI received after the multi-hop swap.

In Conclusion; Testing is a critical aspect of the smart contract development process, especially in the DeFi space, where security and reliability are paramount. These tests provide valuable insights into the functionality of Uniswap V3 swaps, showcasing how users can interact with the protocol to trade tokens efficiently.

As the DeFi ecosystem continues to evolve, robust testing practices will remain essential to ensure the safety of users’ funds and the integrity of smart contracts. 🛡️🔍

Remember, when working with real assets in DeFi, always exercise caution, conduct thorough testing, and follow best practices to minimize risks. Happy testing! 🧪💼🔐

Conclusion

Uniswap V3 is a technical marvel in the world of decentralized finance. With its concentrated liquidity, multiple fee tiers, and improved capital efficiency, it provides exciting opportunities for both liquidity providers and traders.

In this article, we explored two technical examples of how to perform swaps on Uniswap V3 using Web3.js and Python. These examples should serve as a starting point for developers looking to harness the power of Uniswap V3 in their DeFi projects.

Remember that DeFi is a rapidly evolving space, so it’s essential to stay updated with the latest developments and security best practices. Happy swapping! 🚀🌕

If you found this article useful, please clap and share it on Medium (@solidity101) to help others learn about Uniswap V3 and DeFi! 💡📈

📚 Resources 📚

--

--

Solidity Academy

Your go-to resource for mastering Solidity programming. Learn smart contract development and blockchain integration in depth. https://heylink.me/solidity/