2

I was reimplementing the Uniswap v2 contracts and I just could not figure this out.

https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol

So, from what I understand :

If a pair exchange / liquidity pool doesn't exist upon adding liquidity, the UniswapFactory.sol creates a new LP pool contract.

This pool contract UniswapV2pair.sol itself is an ERC20 contract. However, I have some questions about the UniswapV2ERC20 contract it inherits from.

https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2ERC20.sol

It seems like the name and symbol are hard coded into the contract with

string public constant name = "Uniswap V2;

string public constant symbol = 'UNI-V2';

, so when "name" is called from a frontend to the liquidity pool contract, it will always return the string" Uniswap V2" , regardless of what the underlying LP token is (like DAI- ETH, USDC-ETH.. etc).

Is my understanding of this correct? I know the functionality should be fine regardless as all these Pair Liquidity pool contracts are deployed as separate contracts but it seemed a little odd to me that the name and symbol couldn't just be set as something like "DAI-ETH LP" in the constructor rather than all as the same "uniswap v2".

Thanks

1 Answers1

3

You're reading the code correctly. Uniswap has decided to set the same name for all LP token contracts (i.e. pair contracts).

This approach puts more emphasis on the actual pair token addresses, rather than names.

If a pair name contained the token names, a dishonest author could create a custom token named USDT, a Uniswap pair named "ETH-USDT LP", and lure users who won't check the token address into selling their ETH for an otherwise worthless token (instead of the "real" USDT).

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • That makes perfect sense, thank you. It also seems like the UniswapV2ERC20 contract is written slightly differently from the Openzeppelin implementation. For example, the OpenZeppelin version has explicit functions like totalSupply(), balanceOf(address account)... etc while this version keeps it as constants. Would you be able to give some insight as to why they are doing this or if it makes any difference at all? I know that the functionality should be the same when interacting with it. – pentatonictritones Feb 19 '22 at 15:44
  • @pentatonictritones Both approaches (functions and constants) produce the same behavior and bytecode by default... But the OZ implementation allows to overwrite the functions (while it's not possible to overwrite constants), which allows developers extending the OZ contract to produce an extended or different behavior. – Petr Hejda Feb 19 '22 at 16:41
  • Ah perfect, thank you very much. – pentatonictritones Feb 19 '22 at 17:10