better overflow protection
This commit is contained in:
parent
b243874f02
commit
84999fc90a
1 changed files with 32 additions and 27 deletions
|
|
@ -51,6 +51,8 @@ contract LiquidityManager {
|
|||
// creating a security margin for attacks on liquidity
|
||||
uint256 internal constant MIN_CAPITAL_INEFFICIENCY = 100; // 120 = 20%
|
||||
uint256 internal constant MAX_CAPITAL_INEFFICIENCY = 200;
|
||||
// used to double-check price with uni oracle
|
||||
uint32 internal constant PRICE_STABILITY_INTERVAL = 300; // 5 minutes in seconds
|
||||
|
||||
// the address of the Uniswap V3 factory
|
||||
address private immutable factory;
|
||||
|
|
@ -330,6 +332,26 @@ contract LiquidityManager {
|
|||
}
|
||||
}
|
||||
|
||||
function _recordVolumeAndPrice(uint256 currentPrice, uint256 fee) internal {
|
||||
// assuming FEE is 1%
|
||||
uint256 volume = fee * 100;
|
||||
uint256 volumeWeightedPrice = currentPrice * volume;
|
||||
// Check for potential overflow. 10**70 is close to 2^256
|
||||
if (cumulativeVolumeWeightedPrice > 10**70) {
|
||||
uint256 zipFactor = 10**35;
|
||||
uint256 desiredPrecision = 10**5;
|
||||
while (zipFactor * desiredPrecision > cumulativeVolume) {
|
||||
zipFactor /= desiredPrecision;
|
||||
}
|
||||
// Handle overflow: zip historic trade data
|
||||
cumulativeVolumeWeightedPrice = cumulativeVolumeWeightedPrice / zipFactor;
|
||||
// cumulativeVolume should be well higer than zipFactor
|
||||
cumulativeVolume = cumulativeVolume / zipFactor;
|
||||
}
|
||||
cumulativeVolumeWeightedPrice += volumeWeightedPrice;
|
||||
cumulativeVolume += volume;
|
||||
}
|
||||
|
||||
function _scrape() internal {
|
||||
uint256 fee0 = 0;
|
||||
uint256 fee1 = 0;
|
||||
|
|
@ -350,6 +372,7 @@ contract LiquidityManager {
|
|||
fee0 += collected0 - amount0;
|
||||
fee1 += collected1 - amount1;
|
||||
if (i == uint256(Stage.ANCHOR)) {
|
||||
// the historic archor position is only an approximation for the price
|
||||
int24 tick = token0isWeth ? -1 * (position.tickLower + ANCHOR_SPACING): position.tickUpper - ANCHOR_SPACING;
|
||||
currentPrice = tickToPrice(tick);
|
||||
}
|
||||
|
|
@ -361,17 +384,7 @@ contract LiquidityManager {
|
|||
if (fee0 > 0) {
|
||||
if (token0isWeth) {
|
||||
IERC20(address(weth)).transfer(feeDestination, fee0);
|
||||
uint256 volume = fee0 * 100;
|
||||
uint256 volumeWeightedPrice = currentPrice * volume;
|
||||
// Check for potential overflow
|
||||
if (cumulativeVolumeWeightedPrice > type(uint256).max - volumeWeightedPrice) {
|
||||
// Handle overflow: reset
|
||||
cumulativeVolumeWeightedPrice = volumeWeightedPrice;
|
||||
cumulativeVolume = volume;
|
||||
} else {
|
||||
cumulativeVolumeWeightedPrice += volumeWeightedPrice;
|
||||
cumulativeVolume += volume;
|
||||
}
|
||||
_recordVolumeAndPrice(currentPrice, fee0);
|
||||
} else {
|
||||
IERC20(address(harb)).transfer(feeDestination, fee0);
|
||||
}
|
||||
|
|
@ -381,35 +394,27 @@ contract LiquidityManager {
|
|||
IERC20(address(harb)).transfer(feeDestination, fee1);
|
||||
} else {
|
||||
IERC20(address(weth)).transfer(feeDestination, fee1);
|
||||
uint256 volume = fee1 * 100;
|
||||
uint256 volumeWeightedPrice = currentPrice * volume;
|
||||
// Check for potential overflow
|
||||
if (cumulativeVolumeWeightedPrice > type(uint256).max - volumeWeightedPrice) {
|
||||
// Handle overflow: reset
|
||||
cumulativeVolumeWeightedPrice = volumeWeightedPrice;
|
||||
cumulativeVolume = volume;
|
||||
} else {
|
||||
cumulativeVolumeWeightedPrice += volumeWeightedPrice;
|
||||
cumulativeVolume += volume;
|
||||
}
|
||||
_recordVolumeAndPrice(currentPrice, fee1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _isPriceStable(int24 currentTick) internal view returns (bool) {
|
||||
uint32 timeInterval = 300; // 5 minutes in seconds
|
||||
uint32[] memory secondsAgo = new uint32[](2);
|
||||
secondsAgo[0] = timeInterval; // 5 minutes ago
|
||||
secondsAgo[0] = PRICE_STABILITY_INTERVAL; // 5 minutes ago
|
||||
secondsAgo[1] = 0; // current block timestamp
|
||||
|
||||
int56 tickCumulativeDiff;
|
||||
int24 averageTick;
|
||||
try pool.observe(secondsAgo) returns (int56[] memory tickCumulatives, uint160[] memory) {
|
||||
tickCumulativeDiff = tickCumulatives[1] - tickCumulatives[0];
|
||||
averageTick = int24(tickCumulativeDiff / int56(int32(timeInterval)));
|
||||
averageTick = int24(tickCumulativeDiff / int56(int32(PRICE_STABILITY_INTERVAL)));
|
||||
} catch {
|
||||
// TODO:
|
||||
return false;
|
||||
// try with a higher timeframe
|
||||
secondsAgo[0] = PRICE_STABILITY_INTERVAL * 200;
|
||||
(int56[] memory tickCumulatives, ) = pool.observe(secondsAgo);
|
||||
tickCumulativeDiff = tickCumulatives[1] - tickCumulatives[0];
|
||||
averageTick = int24(tickCumulativeDiff / int56(int32(PRICE_STABILITY_INTERVAL)));
|
||||
}
|
||||
|
||||
return (currentTick >= averageTick - MAX_TICK_DEVIATION && currentTick <= averageTick + MAX_TICK_DEVIATION);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue