forked from Uniswap/v4-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPosition.sol
77 lines (69 loc) · 3.42 KB
/
Position.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
import {FullMath} from "./FullMath.sol";
import {FixedPoint128} from "./FixedPoint128.sol";
/// @title Position
/// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary
/// @dev Positions store additional state for tracking fees owed to the position
library Position {
/// @notice Cannot update a position with no liquidity
error CannotUpdateEmptyPosition();
// info stored for each user's position
struct Info {
// the amount of liquidity owned by this position
uint128 liquidity;
// fee growth per unit of liquidity as of the last update to liquidity or fees owed
uint256 feeGrowthInside0LastX128;
uint256 feeGrowthInside1LastX128;
}
/// @notice Returns the Info struct of a position, given an owner and position boundaries
/// @param self The mapping containing all user positions
/// @param owner The address of the position owner
/// @param tickLower The lower tick boundary of the position
/// @param tickUpper The upper tick boundary of the position
/// @return position The position info struct of the given owners' position
function get(mapping(bytes32 => Info) storage self, address owner, int24 tickLower, int24 tickUpper)
internal
view
returns (Position.Info storage position)
{
position = self[keccak256(abi.encodePacked(owner, tickLower, tickUpper))];
}
/// @notice Credits accumulated fees to a user's position
/// @param self The individual position to update
/// @param liquidityDelta The change in pool liquidity as a result of the position update
/// @param feeGrowthInside0X128 The all-time fee growth in currency0, per unit of liquidity, inside the position's tick boundaries
/// @param feeGrowthInside1X128 The all-time fee growth in currency1, per unit of liquidity, inside the position's tick boundaries
/// @return feesOwed0 The amount of currency0 owed to the position owner
/// @return feesOwed1 The amount of currency1 owed to the position owner
function update(
Info storage self,
int128 liquidityDelta,
uint256 feeGrowthInside0X128,
uint256 feeGrowthInside1X128
) internal returns (uint256 feesOwed0, uint256 feesOwed1) {
Info memory _self = self;
uint128 liquidityNext;
if (liquidityDelta == 0) {
if (_self.liquidity == 0) revert CannotUpdateEmptyPosition(); // disallow pokes for 0 liquidity positions
liquidityNext = _self.liquidity;
} else {
liquidityNext = liquidityDelta < 0
? _self.liquidity - uint128(-liquidityDelta)
: _self.liquidity + uint128(liquidityDelta);
}
// calculate accumulated fees. overflow in the subtraction of fee growth is expected
unchecked {
feesOwed0 = FullMath.mulDiv(
feeGrowthInside0X128 - _self.feeGrowthInside0LastX128, _self.liquidity, FixedPoint128.Q128
);
feesOwed1 = FullMath.mulDiv(
feeGrowthInside1X128 - _self.feeGrowthInside1LastX128, _self.liquidity, FixedPoint128.Q128
);
}
// update the position
if (liquidityDelta != 0) self.liquidity = liquidityNext;
self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
}
}