主頁 > 區塊鏈 > Uniswap V2 — 從代碼解釋 DeFi 協議

Uniswap V2 — 從代碼解釋 DeFi 協議

2023-04-23 07:37:22 區塊鏈

Uniswap V2 — 從代碼解釋 DeFi 協議

為了理解我們在分析代碼時將要經歷的不同組件,首先了解哪些是主要概念以及它們的作用是很重要的,所以,和我一起裸露吧,因為這是值得的,

我在 5 個段落中總結了您需要了解的主要重要概念,您將在本文結束時理解這些概念,

Uniswap 是一種去中心化交易協議,該協議是一套持久的、不可升級的智能合約,它們共同創建了一個自動化的做市商,

Uniswap 生態系統貢獻流動性的流動性提供者、交換代幣的交易員和與智能合約互動以開發代幣新互動的開發人員組成,

每個 Uniswap智能合約或對管理一個由兩個 ERC-20 代幣儲備組成的流動資金池,

每個流動性池重新平衡以保持 50/50 比例的加密貨幣資產,這反過來又決定了資產的價格,

流動性提供者可以是任何能夠向 Uniswap 交易合約提供等值的 ETH 和 ERC-20 代幣的人,作為回報,他們從交易合約中獲得流動性提供者代幣(LP 代幣代表流動性提供者擁有的池的份額),可用于隨時提取其在流動性池中的比例,

他們存盤庫中的主要智能合約是:

  • UniswapV2ERC20— 用于 LP 令牌的擴展 ERC20 實作,它還實施了 EIP-2612 以支持鏈下傳輸批準,
  • UniswapV2Factory— 與 V1 類似,這是一個工廠合約,它創建配對合約并充當它們的注冊表,注冊表使用 create2 來生成對地址——我們將詳細了解它是如何作業的,
  • UniswapV2Pair— 負責核心邏輯的主合約,值得注意的是,工廠只允許創建獨特的貨幣對,以免稀釋流動性,
  • UniswapV2Router— Uniswap UI 和其他在 Uniswap 之上作業的網路和去中心化應用程式的主要入口點,
  • UniswapV2Library — 一組實作重要計算的輔助函式,

在這篇文章中,我們將提及所有這些,但我們將主要關注瀏覽UniswapV2RouterUniswapV2Factory編碼,盡管UniswapV2Pair并且UniswapV2Library會涉及很多,

UniswapV2Router02.sol

該合約使創建貨幣對、添加和洗掉流動性、計算所有可能的掉期變化的價格以及執行實際掉期變得更加容易,路由器適用于通過工廠合約部署的所有對

您需要在合約中創建一個實體才能呼叫 addLiquidity、removeLiquidity 和 swapExactTokensForTokens 函式

address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;

IUniswapV2Router02 public uniswapV2Router;
uniswapV2Router = IUniswapV2Router02(ROUTER);

現在讓我們看看流動性管理:

函式 addLiquidity():

function addLiquidity(
    address tokenA,
    address tokenB,
    uint amountADesired,
    uint amountBDesired,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
  • tokenAtokenB:是我們需要獲取或創建我們想要增加流動性的貨幣對的代幣,
  • amountADesiredamountBDesired是我們要存入流動資金池的金額,
  • amountAMinamountBMin是我們要存入的最小金額,
  • to address 是接收 LP 代幣的地址,
  • 截止日期,最常見的是block.timestamp

在內部 _addLiquidity() 中,它將檢查這兩個令牌中的一對是否已經存在,如果不存在,它將創建一個新令牌

if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
    IUniswapV2Factory(factory).createPair(tokenA, tokenB);
}

然后它需要獲取現有的代幣數量或也稱為reserveAand reserveB,我們可以通過 UniswapV2Pair 合約訪問它

IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves()

現在,外部函式 addLiquidity, 回傳(uint amountA, uint amountB, uint liquidity),那么它是如何計算的呢?

通過UniswapV2Library拿到上面提到的reserves之后,還有一系列的檢查

如果該對不存在,并且新創建 amountAamountB回傳一個新的,則將amountADesired作為amountBDesired引數傳遞(見上文),

否則,它會做這個操作

amountBOptimal = amountADesired.mul(reserveB) / reserveA;

如果amountB小于或等于,amountBDesired那么它將回傳:

(uint amountA, uint amountB) = (amountADesired, amountBOptimal)

否則,它將回傳

(uint amountA, uint amountB) = (amountAOptimal, amountBDesired)

其中amountAOptimal的計算方式與amountBOptimal

然后,要計算liquidity回傳值將經過以下程序:

首先,它將使用現有/新創建的對的地址部署 UniswapV2Pair 合約,

它是如何做到的?它計算一對的 CREATE2 地址而無需進行任何外部呼叫:(閱讀有關 CREATE2 Opcode 的更多資訊)

pair = address(uint(keccak256(abi.encodePacked(address(uint(keccak256(abi.encodePacked(
    hex'ff',
    factory,
    keccak256(abi.encodePacked(token0, token1)),
    hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash
))));

然后,它獲取新部署合約的地址,我們需要用它來從這對代幣中鑄造代幣,

當您向貨幣對添加流動性時,合約會生成 LP 代幣;當你移除流動性時,LP 代幣就會被銷毀,

pairFor因此,首先我們使用UniswapV2Library獲取地址:

address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);UniswapV2Library.pairFor(factory, tokenA, tokenB);

因此,稍后可以鑄造 ERC20 代幣并計算回傳的流動性:

liquidity = IUniswapV2Pair(pair).mint(to);

如果您想知道為什么它最終成為 ERC20,在 mint 函式中它是這樣存盤的https://github.com/Uniswap/v2-core/blob/ee547b17853e71ed4e0101ccfd52e70d5acded58/contracts/UniswapV2Pair.sol#L112)

uint balance0 = IERC20(token0).balanceOf(address(this));
uint balance1 = IERC20(token1).balanceOf(address(this));

****函式removeLiquidity():

function removeLiquidity(
    address tokenA,
    address tokenB,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB);

從池中移除流動性意味著燃燒 LP 代幣以換取一定數量的基礎代幣,

IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity);

然后,外部函式回傳兩個值(uint amountA, uint amountB),這些值是使用傳遞給函式的引數計算的,

隨提供的流動性回傳的代幣數量計算如下:

amount0 = liquidity.mul(balance0) / _totalSupply; 
amount1 = liquidity.mul(balance1) / _totalSupply;

然后它將這些數量的代幣轉移到指定的地址

_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);

您的 LP 代幣份額越大,銷毀后獲得的儲備份額就越大,

上面的這些計算發生在 burn 函式內部

IUniswapV2Pair(對).burn(對)

https://github.com/Uniswap/v2-periphery/blob/0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f/contracts/UniswapV2Router02.sol#L114)

IUniswapV2Pair(pair).burn(to)

****函式swapExactTokensForTokens()

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

Uniswap 的核心功能是交換代幣,所以讓我們弄清楚代碼中發生了什么,以便更好地理解它

您很可能聽說過流動資金池中使用的神奇公式

X * Y = K

所以,這將首先發生在 swap 函式內部getAmountOut()

里面用到的關鍵函式有:

TransferHelper.safeTransferFrom().safeTransferFrom()

代幣金額發送到配對代幣的地方

在 UniswapV2Pair 合約的較低級別交換功能中,它將是

_safeTransfer(_token, to, amountOut);

這將實際轉移回預期地址,

我知道資訊量很大,但您將有足夠的時間閱讀所有內容,直到完全理解為止,所以……

UniswapV2Factory.sol

工廠合約是所有已部署對合約的注冊表,這個合約是必要的,因為我們不希望有成對的相同代幣,這樣流動性就不會分成多個相同的對,

該合約還簡化了配對合約的部署:無需通過任何外部呼叫手動部署配對合約,只需呼叫工廠合約中的方法即可,

好吧,讓我們倒回去,因為在上面的這些行中已經說了非常重要的事情,我們把它們拆分開來分別分析:

該合約是所有已部署對合約的注冊表

只部署了一個工廠合約,該合約用作 Uniswap 交易對的官方注冊處,

現在,我們在代碼中的什么地方看到了它以及發生了什么:

address[] public allPairs;

它有 的陣列allPairs,如上所述,存盤在這個合約中,這些對被添加到一個方法中,該方法createPair()通過將新初始化的對推送到陣列來呼叫,

allPairs.push(pair);push(pair);

這個合約是必要的,因為我們不想擁有成對的相同代幣

mapping(address => mapping(address => address)) public getPair;

它具有該對的地址與構成該對的兩個令牌的映射,這用于檢查一對是否已經存在,

require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS');

該合約還簡化了配對合約的部署

這是一個更深層次的話題,但我將嘗試總結一下這里發生的事情的重要性,

在以太坊中,合約可以部署合約,可以呼叫已部署合約的函式,該函式將部署另一個合約,

您不需要從您的計算機上編譯和部署合約,您可以通過現有合約來執行此操作,

那么,Uniswap 是如何部署智能合約的呢?

通過使用操作碼CREATE2

bytes memory bytecode = type(UniswapV2Pair).creationCode;type(UniswapV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
    pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}

在第一行,我們得到創建位元組碼UniswapV2Pair

下一行創建了salt一個位元組序列,用于確定性地生成新合約的地址,

最后一行是我們呼叫以使用+create2確定性地創建新地址的地方,部署,bytecode``salt``UniswapV2Pair

并得到對地址,我們可以看到這是createPair()函式的回傳值

function createPair(
  address tokenA, address tokenA, 
  address tokenB
) external returns (address pair)

當提供的標記不是現有的對_addLiquidity()時,它在內部函式中使用,

所以,這就是關于 Uniswap 代碼的全部內容,

現在,為了看到我們測驗的所有內容,我可以推薦您查看 Smart Contract Programmer 在他的defi-by-example 內容中實作的代碼,他已經在視頻中進行了解釋,

在這里你可以看到我們可以增加流動性的方式

function addLiquidity(
  address _tokenA,
  address _tokenB,
  uint _amountA,
  uint _amountB
) external {
  IERC20(_tokenA).transferFrom(msg.sender, address(this), _amountA);
  IERC20(_tokenB).transferFrom(msg.sender, address(this), _amountB);

  IERC20(_tokenA).approve(ROUTER, _amountA);
  IERC20(_tokenB).approve(ROUTER, _amountB);

  (uint amountA, uint amountB, uint liquidity) =
    IUniswapV2Router(ROUTER).addLiquidity(
      _tokenA,
      _tokenB,
      _amountA,
      _amountB,
      1,
      1,
      address(this),
      block.timestamp
    );

  emit Log("amountA", amountA);
  emit Log("amountB", amountB);
  emit Log("liquidity", liquidity);
}

以及我們必須如何考慮消除流動性

function removeLiquidity(address _tokenA, address _tokenB) external {
  address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB);

  uint liquidity = IERC20(pair).balanceOf(address(this));
  IERC20(pair).approve(ROUTER, liquidity);

  (uint amountA, uint amountB) =
    IUniswapV2Router(ROUTER).removeLiquidity(
      _tokenA,
      _tokenB,
      liquidity,
      1,
      1,
      address(this),
      block.timestamp
    );

  emit Log("amountA", amountA);
  emit Log("amountB", amountB);
}

通過Github 獲取更多區塊鏈學習資料!

https://github.com/Manuel-yang/BlockChainSelfLearning

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/550867.html

標籤:區塊鏈

上一篇:web3 產品介紹: safe --多簽錢包 多人審批更放心

下一篇:返回列表

標籤雲
其他(157862) Python(38092) JavaScript(25381) Java(17985) C(15215) 區塊鏈(8258) C#(7972) AI(7469) 爪哇(7425) MySQL(7137) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4557) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2430) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1959) Web開發(1951) HtmlCss(1919) python-3.x(1918) 弹簧靴(1913) C++(1910) xml(1889) PostgreSQL(1872) .NETCore(1854) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • Uniswap V2 — 從代碼解釋 DeFi 協議

    Uniswap V2 — 從代碼解釋 DeFi 協議 為了理解我們在分析代碼時將要經歷的不同組件,首先了解哪些是主要概念以及它們的作用是很重要的。所以,和我一起裸露吧,因為這是值得的。 我在 5 個段落中總結了您需要了解的主要重要概念,您將在本文結束時理解這些概念。 Uniswap 是一種去中心化交 ......

    uj5u.com 2023-04-23 07:37:22 more
  • web3 產品介紹: safe --多簽錢包 多人審批更放心

    Safe是一款由Gnosis團隊開發的多簽錢包,它提供了一種安全、靈活和易于使用的方式來管理加密資產。在本文中,我們將介紹Safe的主要特點以及如何使用Safe來保護您的數字資產。 一、Safe的特點 多重簽名:Safe使用多重簽名機制來保護用戶的資產,需要至少兩個簽名才能完成交易。這使得用戶的資產 ......

    uj5u.com 2023-04-23 07:37:18 more
  • web3 產品介紹:硬體錢包Ledger 離線管理私鑰更安全

    Ledger是一款硬體錢包,可以安全地存盤用戶的加密資產,并在需要時進行交易。作為一種離線存盤設備,Ledger錢包比在線錢包更加安全,因為它能夠保護用戶的私鑰和交易資訊,使其免受黑客攻擊和網路病毒的影響。本文將詳細介紹Ledger錢包的特點和使用方法。 一、Ledger錢包的特點 1.安全性高:L ......

    uj5u.com 2023-04-21 09:16:38 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more