有偿、求助Pancake配对合约提问

先说有偿吧,我不知道这个问题的难度性,有可能很难也有可能简单。但是实在不好估价。反正最低两包九五至尊或者一个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;
    }
请先 登录 后评论

1 个回答

zen
请先 登录 后评论
  • 0 关注
  • 0 收藏,2843 浏览
  • Niko.Tesla 提出于 2022-05-13 11:55