your deploy script fails at:
await router.addLiquidity(...)
while making a call to addLiquidity(), when it reaches:
(uint reserveA, uint reserveB) = PancakeLibrary.getReserves(factory, tokenA, tokenB);
which in turn fails at:
(uint reserve0, uint reserve1,) = IPancakePair(pairFor(factory, tokenA, tokenB)).getReserves();
here the output of pairFor for tokenA and tokenB is 0x78715162d94936c07d811a03e3e0411a4270bf6c
while your tokens pair is deployed at 0xb8c774F637C2B40d2a834Bb6c1EecD7c96166Cf9
. _addLiquidity
fucntion of router creates the pair if it doesn't exists (checks by calling getPair() == 0x000...0
) and if pair exists then calls getReserves()
which in turn calls pairFor()
. If you have made changes to PancakePair then init_hash might change and address calculated by pairFor()
to find pair might be different. You can try removing createPair call to factory and check without it.
There's no predefined order for transactions in a block. The only requirement is for transactions from the same address to be sorted by the transaction's nonce but transactions from different addresses can be in any order.
In Ethereum mainnet miners will sort by gas price because they will get a larger reward. But it is not always the case, search for "Miner Extractable Value" and the Flashbot project, some times miners will get a bigger reward by including a group of transactions.
Unfortunately I don't know a solution that will work in a PoA network like BSC.
Best Answer
Disclaimer: I don't think this is the correct method to calculate the price impact but it's almost 100% accurate for price impacts of less than 1%. This calculation method assumes that multi-hop is disabled i.e. swapping is restricted to direct pairs. I've only tested this calculation method on PancakeSwap and it is less accurate for larger trade sizes compared to what is shown on their website. Attempting to calculate trade sizes for a 2% price impact, showed 1.99% on the PancakeSwap UI, 5% showed 4.99%, and 10% showed 9.97%. While these discrepancies could be attributed to the user interface lagging, I'm not confident that's the only reason. If anyone can better explain what's happening, I'd be very eager to know.
Short answer
Given a liquidity pool with token A and token B, let:
reserve_a_initial
be the amount of token A in the liquidity pool before the tradereserve_b_initial
be the amount of token B in the liquidity pool before the trade (not required to calculate the price impact)fee
be the trading fee. For PancakeSwap, this is0.0025
amount_traded
be the amount of token A tradedTo calculate the price impact:
Explanation
This article explains how to calculate the price impact. However, please note that what the article refers to as the "current market price" or "market rate", I refer to as the
mid_price
. Now, let's calculate theprice_impact
:Before substituting and simplifying, let:
reserve_a_initial
bereserve_b_initial
bereserve_b_after_execution
beamount_traded
befee
beamountInWithFee
beconstant_product
beamountOut
bemarket_price
bemid_price
beprice_impact
beNow for the math:
I found this mind-blowing, but the amount of token B in the pool doesn't affect the
price_impact
. However,reserve_b_initial
will affectamount_out
.Calculating
amount_traded
given theprice_impact
Rearranging the
price_impact
equation, it is possible to calculateamount_traded
for a givenprice_impact
:Slippage and minimum amount received
To account for slippage,
s
, and calculate the minimum received,amount_out_min
:Slippage does not affect
price_impact
.Sample code
I don't know if there's a function in a PancakeSwap contract that will directly return the
price_impact
, but you can get the reserves of a pool and then calculate it. Let's take CAKE-USDT as an example:Sample results:
Please note that the price shown on the PancakeSwap UI is the
execution_price
: