Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Position Manager #120

Closed

Conversation

saucepoint
Copy link
Collaborator

@saucepoint saucepoint commented Jun 7, 2024

Related Issue

Which issue does this pull request resolve?

Description of changes

The initial position manager. The incomplete items below to be made into new issues/PRs

  • Base functionality: mint/burn/increaseLiquidity/decreaseLiquidity/collect
  • proper fee accounting
  • recipient behavior (specify destination when withdrawing tokens)
  • operator/delegate functionality + tests
  • NFT transfer tests (transfer and burn, transfer and increase/decrease liquidity, transfer and collect)
  • ERC721Permit tests
  • deadline checks + tests
  • slippage checks + tests
  • advanced liquidity mangement (moving to a new pool, adjusting range, etc)
  • exposing arbitrary batch and call operations
  • initialize pool if it doesnt exist

saucepoint and others added 30 commits February 22, 2024 22:23
* chore: update v4-core:latest (Uniswap#105)

* update core

* rename lockAcquired to unlockCallback

* update core; temporary path hack in remappings

* update v4-core; remove remapping

* wip: fix compatibility

* update core; fix renaming of swap fee to lp fee

* update core; fix events

* update core; address liquidity salt and modify liquidity return values

* fix incorrect delta accounting when modifying liquidity

* fix todo, use CurrencySettleTake

* remove deadcode

* update core; use StateLibrary; update sqrtRatio to sqrtPrice

* fix beforeSwap return signatures

* forge fmt; remove commented out code

* update core (wow gas savings)

* update core

* update core

* update core; hook flags LSB

* update core

* update core

* chore: update v4 core (Uniswap#115)

* Update v4-core

* CurrencySettleTake -> CurrencySettler

* Snapshots

* compiling but very broken

* replace PoolStateLibrary

* update currency settle take

* compiling

* wip

* use v4-core's forge-std

* test liquidity increase

* additional fixes for collection and liquidity decrease

* test migration

* replace old implementation with new

---------

Signed-off-by: saucepoint <[email protected]>
Co-authored-by: 0x57 <[email protected]>
@saucepoint saucepoint marked this pull request as ready for review June 12, 2024 14:18
Comment on lines -1 to -3
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
Copy link
Collaborator Author

@saucepoint saucepoint Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of maintaining two versions of forge-std, figured we can just use v4-core's forge-std. its a bit more up to update with some of the cheatcodes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {ERC721} from "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

want to make sure we support permit on ERC721, we'll have to roll our own like we did in V3

also would say in general we're moving towards using more solmate dependencies

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied ERC721Permit from v3. Stuck with OZ for now since they have helpful modifiers and their _beforeTokenTransfer is a bit easier to use than overriding transfer

using LiquidityRangeIdLibrary for LiquidityRange;
using StateLibrary for IPoolManager;

/// @dev The ID of the next token that will be minted. Skips 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a particular reason we skip 0? maybe v3 did something similar but I don't know why?

Comment on lines -1 to -3
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense


import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";

struct LiquidityRange {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion to move this into IPositionManager.sol.. in core most (if not all?) of struct definitions are in respective interfaces

contracts/NonfungiblePositionManager.sol Outdated Show resolved Hide resolved
constructor(IPoolManager _poolManager) ImmutableState(_poolManager) {}

function _unlockCallback(bytes calldata data) internal override returns (bytes memory) {
(bool success, bytes memory returnData) = address(this).call(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come we aren't supporting batched calls under the lock?

contracts/base/BaseLiquidityHandler.sol Outdated Show resolved Hide resolved
LiquidityRange range;
}

mapping(uint256 tokenId => TokenPosition position) public tokenPositions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this will become more clear to me.. but its not clear why we have this mapping and the positions mapping? seems like this just stores LiquidityRange? ... is that really necessary? can we not just pass that in?

and then we only need one mapping:
positions[msg.sender][rangeId]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a Position is keyed by its owner and the range

some interfaces (increaseLiquidity, decreaseLiquidity, and collect) operate on tokenId, so we need a way to recover Position from tokenId

}

modifier isAuthorizedForToken(uint256 tokenId) {
require(_isApprovedOrOwner(msg.sender, tokenId), "Not approved");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm I think _isApprovedOrOwner actually got deprecated in the most up to date version of the OZ ERC721 contracts.

solmates version also doesnt use this

so we should look into updating? or is there a specific reason to still use this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can look into updating -- grabbed it from v3

contracts/libraries/CurrencySenderLibrary.sol Outdated Show resolved Hide resolved
delta = toBalanceDelta(int128(token0Owed), int128(token1Owed));

// sending tokens to the owner
if (token0Owed > 0) range.key.currency0.send(poolManager, owner, token0Owed, useClaims);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i personally dont think we need to support sending 6909 to user.

i do think this contract could keep them as 6909s though (& maybe just by default it should? i think it would be cheaper)

saucepoint and others added 2 commits June 12, 2024 17:37
* wip: consolidation

* further consolidation

* consolidate to single file

* yay no more stack too deep

* some code comments
Copy link

@gabririgo gabririgo Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maintaining the same naming as in the v3 NPM will result in selector clash for contracts/protocols that map selectors to target applications, i.e. diamond pattern. Would it be possible to rename the methods to something like "methodV4", so to allow external protocols to easily interact with v3 and v4?

UPDATE: as the input parameters are different, the resulting function hashes will be different as well. The Uni V4 input bytes calldata hookData does not exist in v3, which should guarantee that the v4 selectors be different. However, it would be nice to assert that there is no clashing possibility with v3.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its something we can keep in mind, but we expect to keep the interfaces as clean as possible

@saucepoint
Copy link
Collaborator Author

replaced by #124

@saucepoint saucepoint closed this Jun 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants