先说有偿吧,我不知道这个问题的难度性,有可能很难也有可能简单。但是实在不好估价。反正最低两包九五至尊或者一个200的红包,如果是真的很难,可以在翻倍。 好了废话不多说,先看一下Pancake配对合约的代码swap函数有点疑问。下面提问。
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
require(amount0Out > 0 || amount1Out > 0, 'Pancake: INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Pancake: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{ // scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, 'Pancake: INVALID_TO');
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
if (data.length > 0) IPancakeCallee(to).pancakeCall(msg.sender, amount0Out, amount1Out, data);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'Pancake: INSUFFICIENT_INPUT_AMOUNT');
{ // scope for reserve{0,1}Adjusted, avoids stack too deep errors
uint balance0Adjusted = (balance0.mul(10000).sub(amount0In.mul(25)));
uint balance1Adjusted = (balance1.mul(10000).sub(amount1In.mul(25)));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(10000**2), 'Pancake: K');
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
问题:我对一个配对池子进行兑换结果是无法兑换,我按照代码中的公式去计算都无法成功。
说说我的流程吧
比如: token配对wbnb 这池子。token的数量是:124252217966379034361075。wbnb的数量是:8078327280467830906
我用3000wbnb转入到token_wbnb池子里面
IBEP20(wbnb).transfer(token_wbnb, 3000000000000000000000);
那么我要兑换多少个token出来呢。
我通过Pancake路由合约的getAmountsOut函数把3000wbnb传入进去可以计算出获得:123917699092823692200883
按照我理解的我用swap函数兑换出来,应该获取到123917699092823692200883个,但是兑换这个数值是错误的
IPair(pair_token_wbnb).swap(123917699092823692200883, 0, address(this), "");
我把getAmountsOut计算公式贴出来计算
(3000000000000000000000*9975*124252217966379034361075) / (8078327280467830906*10000+3000000000000000000000*9975)
然后在下面这三行代码计算后,用 require进行判断大小,如果小于肯定报错兑换是失败的,如果大于等于那么是正确更新一下池子。
uint balance0Adjusted = (balance0.mul(10000).sub(amount0In.mul(25)));
uint balance1Adjusted = (balance1.mul(10000).sub(amount1In.mul(25)));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(10000**2), 'Pancake: K'); }
balance0Adjusted:
(3000000000000000000000+8078327280467830906)*10000-3000000000000000000000*25)
balance1Adjusted:
((124252217966379034361075-189983480439537082)*10000-0*25)
uint(_reserve0).mul(_reserve1).mul(10000**2):
计算公式和数据
((124252217966379034361075-189983480439537082)*(3000000000000000000000+8078327280467830906))*(10000**2));
最后计算出来的结果是 37282794228613174704166295875255167555572765800000000 >= 37375983249600348650284290625255167555572765800000000
也就是下面balance0Adjusted >= (_reserve0).mul(_reserve1).mul(10000**2)
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(10000**2), 'Pancake: K'); }
结果计算出来的还是前者小于后者。
37282794228613174704166295875255167555572765800000000
37375983249600348650284290625255167555572765800000000
我也有考虑过滑点的问题,但是我循环计算滑点也没计算出来,下面是2%的滑点计算公式结果121439345110967218356865 = 123917699092823692200883–123917699092823692200883×2÷100
转出这个121439345110967218356865数也是错误的 IPair(pair_token_wbnb).swap(121439345110967218356865, 0, address(this), "");
但是我发现转出 121439181146345269899775 这个数是正确的。但是我怎么计算也计算不出来这个数值
现在我不知道哪个环节计算有问题,所以请大家帮帮看看计算一下
回复@zen的
emit log_named_address("pair_token_address:", IPair(pair_token_wbnb).token0());
emit log_named_address("pair_wbnb_address:", IPair(pair_token_wbnb).token1());
emit log_named_uint("pair_token_wei:", IBEP20(token).balanceOf(pair_token_wbnb)); //124252217966379034361075
emit log_named_uint("pair_wbnb_wei:", IBEP20(WBNB).balanceOf(pair_token_wbnb)); //8078327280467830906
emit log_named_uint("pair_wbnb_wei:", IBEP20(WBNB).balanceOf(address(this))); //3000000000000000000000
IBEP20(WBNB).transfer(pair_token_wbnb, IBEP20(WBNB).balanceOf(address(this)));
address[] memory path1 = new address[](2);
path1[0] = WBNB;
path1[1] = token;
uint256[] memory amounts = IPSR(PSR).getAmountsOut(IBEP20(WBNB).balanceOf(address(this)), path1);
//amounts = 3000000000000000000000 * 9975*124252217966379034361075 / (8078327280467830906*10000+3000000000000000000000*9975)
emit log_named_uint("amounts[0]:", amounts[0]); //3000000000000000000000
emit log_named_uint("amounts[1]:", amounts[1]); //123917699092823692200883
IPair(pair_token_wbnb).swap(amounts[1], 0, address(this), "");
token 合约转账
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
address sender = _msgSender();
require(blacklist[sender] == false, 'Error: sender is in the blacklist');
require(blacklist[recipient] == false, 'Error: recipient is in the blacklist');
if (sender == owner()) {
_transfer(sender, recipient, amount);
} else {
uint256 fee = amount / 100;
_transfer(sender, one, fee);
_transfer(sender, two, fee);
_transfer(sender, recipient, amount);
}
return true;
}