# Balancer Concentrated Liquidity Proposal Liquidity concentration was introduced as one of the main features in Uniswap V3. Our objective is to incorporate Uniswap's concentrated liquidity functionality into the Balancer Pool ecosystem. ## How it works Implementation of this functionality will come via a new "Pool Type". We plan to introduce 4 new contracts: - ConcentratedLiquidityPoolFactory - ConcentratedLiquidityPool - ConcentratedLiquidityPositionRegistry(ERC1155) - RewardDistributor ### Pool Creation Creation of the new pool type will require us to reuse the UniswapV3Pool.sol contract. Contract code will be modified to adhere to Balancer architecture. Overall code estimations would be around 2-3k LOC. This new pool type will use `userData` to pass all information needed by the pool ```solidity function onJoinPool( bytes32 poolId, address sender, address recipient, uint256[] memory balances, uint256 lastChangeBlock, uint256 protocolSwapFeePercentage, bytes memory userData ) external returns (uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts); ``` ### Fees We could send protocol fees & user fees to `ProtocolFeesCollector` via the Fees collector contract using the `_payFeeAmount` function. This would require an additional smart contract that would be authorized to withdraw tokens from `ProtocolFeesCollector`. (`RewardDistributor`) LP providers would then withdraw collected fees from the (`RewardDistributor`) Smart contract. It would lookup the correct pool, check what is owed to that user, and transfer the tokens from `ProtocolFeesCollector` to the user. Balancer pools would be responsible for storing the user's positions, and managing record keeping. Pools would issue an NFT representing a liquidity position, and handle all concentrated liquidity mechanics. ### NFT Management Uniswap v3 has a native `NonfungiblePositionManager` that we will leverage (but with ERC1155 instead of ERC721) for NFT management. *Utilizing ERC1155 due to `batchTransfer` functionality* ## Diagram of User Experience 1. Join pool - an LP provider providing liquidity into a pool 2. Swap - a user executing a swap 3. Rewards collction - an LP Provider collecting their share of swap fees for providing liquidity ![](https://i.imgur.com/K6PBZbZ.png) ## Topics we considered ### Code reusability Restrictions around Code Reusability from Uniswap: 1. Uniswap license is expiring on [2023-04-01](https://github.com/Uniswap/v3-core/blob/main/LICENSE). 2. Overall difference between Uniswap and Balancer architecture. Support of multiple tokens will significantly increase the complexity of the developed contract. Also some issues might arrive during the preparation of the architecture and code. The best approach would be to implement an analogue Uniswap V3 in the Balancer repo and release it to production after the expiration date of the license. #### We can take over this component from Uniswap: - Interfaces. We'll need to import all of the interfaces. - Library contracts. We can import all of the contracts in libraries, it may save time, but maybe we can use balancer libraries for some of the files that are already in balancer. We will 100% need to import the following files: - Tick - TickBitmap - TickMath - Position - Oracle(If we want same kind of observation as Balancer) We don't need to import contracts(due to analogues in Balancer): - LowGasSafeMath(Math.sol from balancer is good enough) - FullMath.col - UnsafeMath It makes sense to take a closer look, to verify that we can interchange Math in the library and Balancer math. - Pool Factory/Deployer. These contracts can be imported with minimal changes - Pool. - NFTPositionDescriptor. This contract and the contracts below will be taken from the v3-periphery repo. - NF Position Manager - SwapRouter - Lens - Base Those imports should be split into two parts, because NFTs/SwapRouter architecture are just a utility for the Pool. #### Necessary adaptations - Pool Factory: Make it permissionless. Factories in Balancer do not have owners. Factory and Deployer can be merged in a single contract, to save a bit of gas. - Library contracts. Go through them, pick only the ones that are actually needed, not to create duplicates with Balancer. - Pool. There are a lot of changes involved, due to the difference in Balancer/Uniswap architecture. The main concern is around where funds are stored, unlike uniswap the tokens will be stored in the Vault. - PositionRegistry. Adapt and use ERC1155 instead of ERC721. #### Gas cost estimations for trades They should be more or less the same as in Balancer. Maybe a slight increase due to the interactions with the Vault. #### How to deal with the challenge of calling the Vault rather than calling registries It seems doable, at this point we will need to transfer tokens received to the Vault, and change 'Transfer' library (token transfers will no longer happen from the contract itself). #### Challenge of providing traders experience close to Uniswap v3 That's more to the UI experience. If our developed contracts will allow the same functionality, then this shouldn't be a problem. #### Wrapper registry contracts around the pool to call Vault?* As I understand registry and Factory is the same thing in Uniswap. One approach would be to actually do some code changes to interact with Balancer directly, without intermediary wrapper.