区块链技术博客
www.b2bchain.cn

从零开始了解 Uniswap求职学习资料

本文介绍了从零开始了解 Uniswap求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

你一定听说过Uniswap,甚至非常了解它的运作方式。

Uniswap是一个神奇的产品,没有订单簿?没有服务器?没有预言机?WTF!!!!

X * Y = K 是其✨魔法所在。✨

这是一个永远执行、去中心化的AMM的执行引擎

让我们从头开始实现它,了解它到底是如何工作的。

本文的目的不是要进行一个完美和安全的Uniswap实现。而是为了以最简化的方式展示其机制,你可以在文末查看到本文的完整代码。

我们假定你对以太坊有基本了解,例如了解 Solidity、智能合约、交易和代币。

如果还不了解,订阅全面掌握Solidity智能合约开发专栏全面学习。

Pool(流动性资金池)

Uniswap的故事从Pool(以下简称:流动池)开始。流动池是一个智能合约,它储备了两个代币的token0token1

contract LooneySwapPool is ERC20 {   address public token0;   address public token1;    // Reserve of token 0   uint public reserve0;    // Reserve of token 1   uint public reserve1;   ... }

创建一个流动池很简单:只需要指定这个流动池可以存储的2个代币:

constructor(address _token0, address _token1) ERC20("LiquidityProvider", "LP") {   token0 = _token0;   token1 = _token1; }

合约创建后,它将在状态变量reserve0reserve1中分别记录token0token1的数量余额。

请注意,该合约也扩展了ERC20。这是因为,除了计算每个代币的储备量之外,它本身也是一个代币,正如你从名字中可以看出,该代币代表了流动性提供者的余额。

增加流动性资金

为了将流动性添加到我们的资金池中,必须调用add函数,指定我们要存入的每个代币的数量:

function add(uint amount0, uint amount1)

首先我们把代币转移到流动池(本身)里:

assert(IERC20(token0).transferFrom(msg.sender, address(this), amount0)); assert(IERC20(token1).transferFrom(msg.sender, address(this), amount1));

由于用户不再拥有这些代币的控制权,我们需要一种方法来给他们一个对象,代表他们在流动池中的所占的份额。这就是流动池代币的作用!

我们按照用户在资金池中的份额,铸造新的流动池代币。

如果这是第一个提供流动资金的用户,我们会铸造一个初始金额,有效地给他们一个100%的份额。

_mint(msg.sender, INITIAL_SUPPLY);

否则,我们将计算出按比例的份额,并铸造出等值的LP代币:

uint reserve0After = reserve0 + amount0; uint reserve1After = reserve1 + amount1;  ...  uint currentSupply = totalSupply(); // Current supply of LP tokens uint newSupplyGivenReserve0Ratio = reserve0After * currentSupply / reserve0; uint newSupplyGivenReserve1Ratio = reserve1After * currentSupply / reserve1; uint newSupply = Math.min(newSupplyGivenReserve0Ratio, newSupplyGivenReserve1Ratio); _mint(msg.sender, newSupply - currentSupply);

很好!我们的流动池现在有一个代币的比例,我们可以说明谁提供了这些代币。我们现在可以开始实现兑换了!

神奇的公式

在我们执行兑换之前,我们需要得出一个价格。

在传统的交易所模式中,流动性提供者明确规定了价格和规模,例如:卖出2.4ETH @ $2210/ETH。这就要求参与者积极参与交易所的运作,不断调整/补充。在区块链的背景下,它会带来一系列的问题,因为每次调整都需要提交交易,订单簿往往会变得低效。而如果订单簿作为一个中心化的服务来提供,就会产生了信任问题。

Uniswap没有明确的定价,而是用一个公式来推导价格。

x * y = k

它看起来很抽象,但通过一些例子来演示,你就会明白它是直截了当的,公式中

xreserve0(流动池token0的储备量)
yreserve1(流动池token1的储备量)

因此,k的值成为 reserve0 * reserve1。而且在确定价格时k必须保持不变。

k保持不变意味着:

  • 如果你减少reserve0,你必须增加reserve1
  • 如果你减少reserve1,你必须增加reserve0

写成代码后,看起来是这样:

“`
function getAmountOut(uint amountIn, address fromToken) {

uint k = reserve0 * reserve1;

你一定听说过Uniswap,甚至非常了解它的运作方式。

Uniswap是一个神奇的产品,没有订单簿?没有服务器?没有预言机?WTF!!!!

X * Y = K 是其✨魔法所在。✨

这是一个永远执行、去中心化的AMM的执行引擎

让我们从头开始实现它,了解它到底是如何工作的。

本文的目的不是要进行一个完美和安全的Uniswap实现。而是为了以最简化的方式展示其机制,你可以在文末查看到本文的完整代码。

我们假定你对以太坊有基本了解,例如了解 Solidity、智能合约、交易和代币。

如果还不了解,订阅全面掌握Solidity智能合约开发专栏全面学习。

Pool(流动性资金池)

Uniswap的故事从Pool(以下简称:流动池)开始。流动池是一个智能合约,它储备了两个代币的token0token1

contract LooneySwapPool is ERC20 {   address public token0;   address public token1;    // Reserve of token 0   uint public reserve0;    // Reserve of token 1   uint public reserve1;   ... }

创建一个流动池很简单:只需要指定这个流动池可以存储的2个代币:

constructor(address _token0, address _token1) ERC20("LiquidityProvider", "LP") {   token0 = _token0;   token1 = _token1; }

合约创建后,它将在状态变量reserve0reserve1中分别记录token0token1的数量余额。

请注意,该合约也扩展了ERC20。这是因为,除了计算每个代币的储备量之外,它本身也是一个代币,正如你从名字中可以看出,该代币代表了流动性提供者的余额。

增加流动性资金

为了将流动性添加到我们的资金池中,必须调用add函数,指定我们要存入的每个代币的数量:

function add(uint amount0, uint amount1)

首先我们把代币转移到流动池(本身)里:

assert(IERC20(token0).transferFrom(msg.sender, address(this), amount0)); assert(IERC20(token1).transferFrom(msg.sender, address(this), amount1));

由于用户不再拥有这些代币的控制权,我们需要一种方法来给他们一个对象,代表他们在流动池中的所占的份额。这就是流动池代币的作用!

我们按照用户在资金池中的份额,铸造新的流动池代币。

如果这是第一个提供流动资金的用户,我们会铸造一个初始金额,有效地给他们一个100%的份额。

_mint(msg.sender, INITIAL_SUPPLY);

否则,我们将计算出按比例的份额,并铸造出等值的LP代币:

uint reserve0After = reserve0 + amount0; uint reserve1After = reserve1 + amount1;  ...  uint currentSupply = totalSupply(); // Current supply of LP tokens uint newSupplyGivenReserve0Ratio = reserve0After * currentSupply / reserve0; uint newSupplyGivenReserve1Ratio = reserve1After * currentSupply / reserve1; uint newSupply = Math.min(newSupplyGivenReserve0Ratio, newSupplyGivenReserve1Ratio); _mint(msg.sender, newSupply - currentSupply);

很好!我们的流动池现在有一个代币的比例,我们可以说明谁提供了这些代币。我们现在可以开始实现兑换了!

神奇的公式

在我们执行兑换之前,我们需要得出一个价格。

在传统的交易所模式中,流动性提供者明确规定了价格和规模,例如:卖出2.4ETH @ $2210/ETH。这就要求参与者积极参与交易所的运作,不断调整/补充。在区块链的背景下,它会带来一系列的问题,因为每次调整都需要提交交易,订单簿往往会变得低效。而如果订单簿作为一个中心化的服务来提供,就会产生了信任问题。

Uniswap没有明确的定价,而是用一个公式来推导价格。

x * y = k

它看起来很抽象,但通过一些例子来演示,你就会明白它是直截了当的,公式中

xreserve0(流动池token0的储备量)
yreserve1(流动池token1的储备量)

因此,k的值成为 reserve0 * reserve1。而且在确定价格时k必须保持不变。

k保持不变意味着:

  • 如果你减少reserve0,你必须增加reserve1
  • 如果你减少reserve1,你必须增加reserve0

写成代码后,看起来是这样:

“`
function getAmountOut(uint amountIn, address fromToken) {

uint k = reserve0 * reserve1;

你一定听说过Uniswap,甚至非常了解它的运作方式。

Uniswap是一个神奇的产品,没有订单簿?没有服务器?没有预言机?WTF!!!!

X * Y = K 是其✨魔法所在。✨

这是一个永远执行、去中心化的AMM的执行引擎

让我们从头开始实现它,了解它到底是如何工作的。

本文的目的不是要进行一个完美和安全的Uniswap实现。而是为了以最简化的方式展示其机制,你可以在文末查看到本文的完整代码。

我们假定你对以太坊有基本了解,例如了解 Solidity、智能合约、交易和代币。

如果还不了解,订阅全面掌握Solidity智能合约开发专栏全面学习。

Pool(流动性资金池)

Uniswap的故事从Pool(以下简称:流动池)开始。流动池是一个智能合约,它储备了两个代币的token0token1

contract LooneySwapPool is ERC20 {   address public token0;   address public token1;    // Reserve of token 0   uint public reserve0;    // Reserve of token 1   uint public reserve1;   ... }

创建一个流动池很简单:只需要指定这个流动池可以存储的2个代币:

constructor(address _token0, address _token1) ERC20("LiquidityProvider", "LP") {   token0 = _token0;   token1 = _token1; }

合约创建后,它将在状态变量reserve0reserve1中分别记录token0token1的数量余额。

请注意,该合约也扩展了ERC20。这是因为,除了计算每个代币的储备量之外,它本身也是一个代币,正如你从名字中可以看出,该代币代表了流动性提供者的余额。

增加流动性资金

为了将流动性添加到我们的资金池中,必须调用add函数,指定我们要存入的每个代币的数量:

function add(uint amount0, uint amount1)

首先我们把代币转移到流动池(本身)里:

assert(IERC20(token0).transferFrom(msg.sender, address(this), amount0)); assert(IERC20(token1).transferFrom(msg.sender, address(this), amount1));

由于用户不再拥有这些代币的控制权,我们需要一种方法来给他们一个对象,代表他们在流动池中的所占的份额。这就是流动池代币的作用!

我们按照用户在资金池中的份额,铸造新的流动池代币。

如果这是第一个提供流动资金的用户,我们会铸造一个初始金额,有效地给他们一个100%的份额。

_mint(msg.sender, INITIAL_SUPPLY);

否则,我们将计算出按比例的份额,并铸造出等值的LP代币:

uint reserve0After = reserve0 + amount0; uint reserve1After = reserve1 + amount1;  ...  uint currentSupply = totalSupply(); // Current supply of LP tokens uint newSupplyGivenReserve0Ratio = reserve0After * currentSupply / reserve0; uint newSupplyGivenReserve1Ratio = reserve1After * currentSupply / reserve1; uint newSupply = Math.min(newSupplyGivenReserve0Ratio, newSupplyGivenReserve1Ratio); _mint(msg.sender, newSupply - currentSupply);

很好!我们的流动池现在有一个代币的比例,我们可以说明谁提供了这些代币。我们现在可以开始实现兑换了!

神奇的公式

在我们执行兑换之前,我们需要得出一个价格。

在传统的交易所模式中,流动性提供者明确规定了价格和规模,例如:卖出2.4ETH @ $2210/ETH。这就要求参与者积极参与交易所的运作,不断调整/补充。在区块链的背景下,它会带来一系列的问题,因为每次调整都需要提交交易,订单簿往往会变得低效。而如果订单簿作为一个中心化的服务来提供,就会产生了信任问题。

Uniswap没有明确的定价,而是用一个公式来推导价格。

x * y = k

它看起来很抽象,但通过一些例子来演示,你就会明白它是直截了当的,公式中

xreserve0(流动池token0的储备量)
yreserve1(流动池token1的储备量)

因此,k的值成为 reserve0 * reserve1。而且在确定价格时k必须保持不变。

k保持不变意味着:

  • 如果你减少reserve0,你必须增加reserve1
  • 如果你减少reserve1,你必须增加reserve0

写成代码后,看起来是这样:

“`
function getAmountOut(uint amountIn, address fromToken) {

uint k = reserve0 * reserve1;

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 从零开始了解 Uniswap求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们