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!

  • 1
    can you explain in your question using those "various examples" why that equation that includes the tax does not yield the correct amount_out
    – MShakeG
    Commented Sep 11, 2023 at 11:38
  • @MShakeG Provided an example just now
    – galpo
    Commented Sep 11, 2023 at 23:19
  • 1
    I think the formula which implement tax is wrong. Commented Sep 12, 2023 at 10:45

1 Answer 1


Actually the formula in my question is correct. What I didn't realize is that a lot of contracts implement logic in transfer() whereby if the number of tokens (of itself) that the contract itself owns is sufficiently high (usually accumulated through transfer taxes), then the contract swaps those tokens for ETH. And because transfer() is actually called BEFORE the Uniswap math is done in the implementation of swapExactTokensForTokensSupportingFeeOnTransferTokens() (and the other *SupportingFeeOnTransferTokens functions), the address calling swapExactTokensForTokensSupportingFeeOnTransferTokens gets a slightly worse price than expected based on the pool reserves and tax rate, as that swap occurs AFTER the other swap done in the code of transfer().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.