forked from Uniswap/v3-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTickOverflowSafetyEchidnaTest.sol
111 lines (98 loc) · 3.58 KB
/
TickOverflowSafetyEchidnaTest.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.7.6;
import '../libraries/Tick.sol';
contract TickOverflowSafetyEchidnaTest {
using Tick for mapping(int24 => Tick.Info);
int24 private constant MIN_TICK = -16;
int24 private constant MAX_TICK = 16;
uint128 private constant MAX_LIQUIDITY = type(uint128).max / 32;
mapping(int24 => Tick.Info) private ticks;
int24 private tick = 0;
// used to track how much total liquidity has been added. should never be negative
int256 totalLiquidity = 0;
// half the cap of fee growth has happened, this can overflow
uint256 private feeGrowthGlobal0X128 = type(uint256).max / 2;
uint256 private feeGrowthGlobal1X128 = type(uint256).max / 2;
// how much total growth has happened, this cannot overflow
uint256 private totalGrowth0 = 0;
uint256 private totalGrowth1 = 0;
function increaseFeeGrowthGlobal0X128(uint256 amount) external {
require(totalGrowth0 + amount > totalGrowth0); // overflow check
feeGrowthGlobal0X128 += amount; // overflow desired
totalGrowth0 += amount;
}
function increaseFeeGrowthGlobal1X128(uint256 amount) external {
require(totalGrowth1 + amount > totalGrowth1); // overflow check
feeGrowthGlobal1X128 += amount; // overflow desired
totalGrowth1 += amount;
}
function setPosition(
int24 tickLower,
int24 tickUpper,
int128 liquidityDelta
) external {
require(tickLower > MIN_TICK);
require(tickUpper < MAX_TICK);
require(tickLower < tickUpper);
bool flippedLower =
ticks.update(
tickLower,
tick,
liquidityDelta,
feeGrowthGlobal0X128,
feeGrowthGlobal1X128,
0,
0,
uint32(block.timestamp),
false,
MAX_LIQUIDITY
);
bool flippedUpper =
ticks.update(
tickUpper,
tick,
liquidityDelta,
feeGrowthGlobal0X128,
feeGrowthGlobal1X128,
0,
0,
uint32(block.timestamp),
true,
MAX_LIQUIDITY
);
if (flippedLower) {
if (liquidityDelta < 0) {
assert(ticks[tickLower].liquidityGross == 0);
ticks.clear(tickLower);
} else assert(ticks[tickLower].liquidityGross > 0);
}
if (flippedUpper) {
if (liquidityDelta < 0) {
assert(ticks[tickUpper].liquidityGross == 0);
ticks.clear(tickUpper);
} else assert(ticks[tickUpper].liquidityGross > 0);
}
totalLiquidity += liquidityDelta;
// requires should have prevented this
assert(totalLiquidity >= 0);
if (totalLiquidity == 0) {
totalGrowth0 = 0;
totalGrowth1 = 0;
}
}
function moveToTick(int24 target) external {
require(target > MIN_TICK);
require(target < MAX_TICK);
while (tick != target) {
if (tick < target) {
if (ticks[tick + 1].liquidityGross > 0)
ticks.cross(tick + 1, feeGrowthGlobal0X128, feeGrowthGlobal1X128, 0, 0, uint32(block.timestamp));
tick++;
} else {
if (ticks[tick].liquidityGross > 0)
ticks.cross(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128, 0, 0, uint32(block.timestamp));
tick--;
}
}
}
}