本文主要是介绍Solidity Uniswap V2 Pair中移除流动性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
移除流动性与提供流动性是截然相反的一个动作。从Pool中移除流动性意味着烧销毁LP-Token,以换取pair中相应数量的Token。返回的token数量与提供的流动性是这样计算的:
简而言之,返回的Token数量,与持有的LP-Token数量与LP-Token总供应量成正比。你的LP-Token份额越大,你在burn后从reserve获得的份额就越大。
这就是我们实现burn函数所需要知道的:
当有人向池提供流动性时,他们会得到 LP-token作为回报。当流动性被移除时,这些 LP-token会被兑换成池流动性并被销毁。让用户向合约发送一定数量的 LP-token,在合约中计算出用户可以获取的token后,销毁 LP-token。
function burn(address to) public returns (uint256 amount0, uint256 amount1) {uint256 balance0 = IERC20(token0).balanceOf(address(this));uint256 balance1 = IERC20(token1).balanceOf(address(this));uint256 liquidity = balanceOf[address(this)];uint256 amount0 = (liquidity * balance0) / totalSupply;uint256 amount1 = (liquidity * balance1) / totalSupply;if (amount0 <= 0 || amount1 <= 0) revert InsufficientLiquidityBurned();_burn(address(this), liquidity);bool success0 = IERC20(token0).transfer(to, amount0);if (!success0)revert TransferFailed();bool success1 = IERC20(token1).transfer(to, amount1);if (!success1)revert TransferFailed();balance0 = IERC20(token0).balanceOf(address(this));balance1 = IERC20(token1).balanceOf(address(this));(uint112 reserve0_, uint112 reserve1_, ) = getReserves();_update(balance0, balance1, reserve0_, reserve1_);emit Burn(msg.sender, amount0, amount1);}
接下来测试一下:
function testBurn() public {token0.transfer(address(pair), 1 ether);token1.transfer(address(pair), 1 ether);pair.mint(address(this));uint256 liquidity = pair.balanceOf(address(this));pair.transfer(address(pair), liquidity);pair.burn(address(this));assertEq(pair.balanceOf(address(this)), 0);assertReserves(1000, 1000);assertEq(pair.totalSupply(), 1000);assertEq(token0.balanceOf(address(this)), 10 ether - 1000);assertEq(token1.balanceOf(address(this)), 10 ether - 1000);}
我们可以看到,除了发送到零地址的最低流动性外,Pool又回到了未初始化的状态。
现在,让我们看看在提供不平衡的流动性后会发生什么:
function testBurnUnbalanced() public {token0.transfer(address(pair), 1 ether);token1.transfer(address(pair), 1 ether);pair.mint(address(this));token0.transfer(address(pair), 2 ether);token1.transfer(address(pair), 1 ether);pair.mint(address(this)); // + 1 LPuint256 liquidity = pair.balanceOf(address(this));pair.transfer(address(pair), liquidity);pair.burn(address(this));assertEq(pair.balanceOf(address(this)), 0);assertReserves(1500, 1000);assertEq(pair.totalSupply(), 1000);assertEq(token0.balanceOf(address(this)), 10 ether - 1500);assertEq(token1.balanceOf(address(this)), 10 ether - 1000);}
我们在这里看到的是,我们损失了 500 wei的Token 0!这就是上文提到的对价格操纵的惩罚。但这个数额小得离谱,看起来一点都不重要。这是因为我们当前的用户是唯一的流动性提供者。如果我们向另一个用户初始化的池提供了不平衡的流动性,会怎么样呢?让我们来看看:
function testBurnUnbalancedDifferentUsers() public {testUser.provideLiquidity(address(pair),address(token0),address(token1),1 ether,1 ether);assertEq(pair.balanceOf(address(this)), 0);assertEq(pair.balanceOf(address(testUser)), 1 ether - 1000);assertEq(pair.totalSupply(), 1 ether);token0.transfer(address(pair), 2 ether);token1.transfer(address(pair), 1 ether);pair.mint(address(this)); // + 1 LPuint256 liquidity = pair.balanceOf(address(this));pair.transfer(address(pair), liquidity);pair.burn(address(this));// this user is penalized for providing unbalanced liquidityassertEq(pair.balanceOf(address(this)), 0);assertReserves(1.5 ether, 1 ether);assertEq(pair.totalSupply(), 1 ether);assertEq(token0.balanceOf(address(this)), 10 ether - 0.5 ether);assertEq(token1.balanceOf(address(this)), 10 ether);testUser.removeLiquidity(address(pair));// testUser receives the amount collected from this userassertEq(pair.balanceOf(address(testUser)), 0);assertReserves(1500, 1000);assertEq(pair.totalSupply(), 1000);assertEq(token0.balanceOf(address(testUser)),10 ether + 0.5 ether - 1500);assertEq(token1.balanceOf(address(testUser)), 10 ether - 1000);}
现在看起来完全不同了!我们现在损失了 0.5 ether 的 token0,相当于我们存入资金的 1/4 。这可是一笔不小的数目!
想一想,是谁最终得到了这 0.5 个以太币:合约还是用户?
这篇关于Solidity Uniswap V2 Pair中移除流动性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!