The normal question to get the amount of token received when doing a Uniswap V2 swap is
amount_out = 0.997 * amount_in * reserves_out / (reserves_in + 0.997 * amount_in)
I want to adjust this equation to account for transfer taxes on the input token, which some tokens implement. Let's assume that this transfer tax is a fixed constant. I would think that the updated equation should be
amount_out = 0.997 * (1 - tax) * amount_in * reserves_out / (reserves_in + 0.997 * (1 - tax) * amount_in)
That is, the input amount is simply reduced by one minus the tax rate before using it in the original equation. However, this does not seem to be correct, from looking at various examples. In particular, it seems correct when the value of amount_in is small (relative to reserves_in), but when that value is larger, the equation fails to hold for some reason.
As an example, I was looking at the Uniswap V2 pair with WETH and 0x005dfe17019636776bdd0ac454e856f4b99b337d (call it Token A) right after block 16000544. If I, using eth_call, send 0.0929664 ETH into the pool (via swapExactETHForTokensSupportingFeeOnTransferTokens), I get back some amount X of Token A back. Using the pool reserves before the swap along with the aforementioned amount_in and amount_out, I compute the buy tax to be exactly 0.06 using the above equation. At this point, I checked the pool reserves again, and then sent X back into the pool (via swapExactTokensForETHSupportingFeeOnTransferTokens), thereby getting some amount Y of ETH back. Using these updated reserve values, as well as the values of X and Y, the above equation implies that the sell tax is also 0.06. This all seems nice and clean. However, if I start over and now send in 0.0929665 ETH (instead of 0.0929664 ETH) and repeat the above calculations, I find that the buy tax is still 0.06, but the sell tax is now 0.07150068620959504. Trying different values, it seems that any time I send in an amount of ETH less than or equal to 0.0929664 ETH, I get the same sell tax of 0.06, but if I send in 0.0929665 ETH or more, I get a different sell tax. One could argue that this is because of some nuance in the implementation of transfer() in the 0x005dfe17019636776bdd0ac454e856f4b99b337d contract, but I have noticed the same phenomenon with many contracts I have done these calculations on.
Does anyone know why? Thanks!
amount_out