I want to implement different behavior in the transfer function of an ERC20 token if the transaction is swapping the token for ETH on Uniswap. The straight forward approach is, to check whether the associated uniswap pool is the recipient of the transfer. But that would also hold true for liquidity providing, in which tokens get transfered to the same address (Uniswap pool) and I want to apply a different logic for liquidity providing. How can I achieve this?

One thing I thought of was an additional contract for liquidity providing that can act as a proxy. Users could call a function on said contract, which would do the liquidity providing. The transfer function could then check whether the sender of a transaction is that contract and apply different behavior. But I am not sure whether this would work out.

Edit: To explain the aim more precisely: I want to burn tokens on sells but not when liquidity is provided. Therefore I reworked the transfer function in my token:

function myTransfer(address sender, address recipient, uint256 amount) internal {
        if (sender == uniswapPool)
            _transfer(sender, recipient, amount); // no burn when buying
        else if(recipient == uniswapPool) // burn 10% for selling
            uint256 burn = amount.div(10);
            uint256 amountSent = amount.sub(burn);
            _transfer(sender, recipient, amountSent);
            _burnFrom(sender, burn);   

But with this code in case of liquidity providing, tokens would also be burned.

  • Is there a way I can find out in my transfer function whether we are sending tokens to the pool for selling/swapping them or for liquidity providing?
  • If not: How can I work around the problem?

2 Answers 2


Swapping and providing liquidity are two different things, and you have different functions in Router02 depending on what you need to achieve.

If you want to swap token for eth, you can use:

function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
  returns (uint[] memory amounts);

On the other hand, if you want to add liquidity to the pool, you can use:

function addLiquidityETH(
  address token,
  uint amountTokenDesired,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);

You can create a smart contract with the functions you need for calling the Uniswap router's one. The transfers of eth or tokens you refer to are already done when you call any of these functions.

Reminder: before transferring assets, you need to give the approval to the router.

  • Sorry, I think I did not explain my problem clearly, so I edited the question now. Feb 19, 2021 at 12:53

One possible way of executing this is using function selectors. This post can explain what a function signature is What is a function signature and function selector in solidity (and EVM languages)?

when executing the transfer functions you can edit the _beforeTokenTransfer hook provided by openzeppelin to check which function signature you're calling and implement the piece of code according to that function selector

You can check out hooks which are called before some particular action


  • How can you use the function selector? When the token transfer function is called you only have transfer function selector. A contract cannot inspect the call stack.
    – Ismael
    Dec 23, 2022 at 2:30

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