Search code examples
ethereumethers.jserc20

Calculate ERC20 token buy/sell tax


I am trying to implement a method for calculating token buy/sell tax. The one that devs implement it in the transfer() function.

I've done some research and there are 2 options.

  1. eth_call - simulate a swap, calculate the difference
  2. deploy the ERC20 smart contract on a local hardhat/ganache, execute swap and see the difference

The eth_call seems to be better for me but I'm facing some issues.

 // Encode function data
        const encodedData = router.interface.encodeFunctionData('swapExactETHForTokens', [
            0,
            path,
            to,
            deadline,
        ]);

        // Get amountsOut using eth_call, performs a SIMULATION
        const callResult = await this.provider.call({
            data: encodedData,
            value: parseUnits('2', 18),
            to: constants.UNISWAP_ROUTER_ADDRESS,
        });

        console.log('callResult', callResult);

        // Decode result
        const decodedResult = router.interface.decodeFunctionResult(
            'swapExactETHForTokens',
            callResult
        );

it does not return the actual amount including taxes, the response is just an array of the amounts out first is amount of ETH and second is the token amount. if I set the amountIn 0, then I get 0% tax, if I increase it then the amountOut of token decreases.


Solution

  • To get a more accurate representation of the tax, you might need to make use of the Uniswap V2 Router's getAmountsOut function instead of swapExactETHForTokens. getAmountsOut is designed to get the expected output amounts given an input amount and the token path. You can then compare the estimated output amount with the actual output amount after the swap to determine the tax.

    const uniswapV2Router = new ethers.Contract(
      constants.UNISWAP_ROUTER_ADDRESS,
      ['function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)'],
      this.provider
    );
    
    // Replace 'tokenAmount' and 'path' with appropriate values
    const amountsOut = await uniswapV2Router.getAmountsOut(tokenAmount, path);
    
    console.log('Estimated output amount:', amountsOut[amountsOut.length - 1]);