-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Strange behaviour fees in range #573
Comments
The contract implicitly relies on int256 underflow/overflow. Python won't do this for you. Make sure to mimic the SDK found here: https://discord.com/channels/597638925346930701/607978109089611786/1009532714862522450 |
Ok, another details: I implemented formula range fees calculation on solidity and get another strange results:
Why it is strange? Because fees inside range much greater than all fees in pool. Here is code (copy paste of getFeeGrowthInside + wrapper function): pragma solidity >=0.5.0;
pragma abicoder v2;
interface IUniswapV3PoolState {
function feeGrowthGlobal0X128() external view returns (uint256);
function feeGrowthGlobal1X128() external view returns (uint256);
function ticks(int24 tick)
external
view
returns (TestTick.Info memory);
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
}
contract TestTick {
IUniswapV3PoolState pool = IUniswapV3PoolState(0xDaC8A8E6DBf8c690ec6815e0fF03491B2770255D);
event Log(uint256, uint256);
struct Info {
uint128 liquidityGross;
int128 liquidityNet;
uint256 feeGrowthOutside0X128;
uint256 feeGrowthOutside1X128;
int56 tickCumulativeOutside;
uint160 secondsPerLiquidityOutsideX128;
uint32 secondsOutside;
bool initialized;
}
function getFeeGrowthInside(
int24 tickLower,
int24 tickUpper,
int24 tickCurrent,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128
) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {
Info memory lower = pool.ticks(tickLower);
Info memory upper = pool.ticks(tickUpper);
uint256 feeGrowthBelow0X128;
uint256 feeGrowthBelow1X128;
if (tickCurrent >= tickLower) {
feeGrowthBelow0X128 = lower.feeGrowthOutside0X128;
feeGrowthBelow1X128 = lower.feeGrowthOutside1X128;
} else {
feeGrowthBelow0X128 = feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128;
feeGrowthBelow1X128 = feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128;
}
// calculate fee growth above
uint256 feeGrowthAbove0X128;
uint256 feeGrowthAbove1X128;
if (tickCurrent < tickUpper) {
feeGrowthAbove0X128 = upper.feeGrowthOutside0X128;
feeGrowthAbove1X128 = upper.feeGrowthOutside1X128;
} else {
feeGrowthAbove0X128 = feeGrowthGlobal0X128 - upper.feeGrowthOutside0X128;
feeGrowthAbove1X128 = feeGrowthGlobal1X128 - upper.feeGrowthOutside1X128;
}
feeGrowthInside0X128 = feeGrowthGlobal0X128 - feeGrowthBelow0X128 - feeGrowthAbove0X128;
feeGrowthInside1X128 = feeGrowthGlobal1X128 - feeGrowthBelow1X128 - feeGrowthAbove1X128;
}
function run() external {
int24 tickLower = -6;
int24 tickUpper = -2;
(, int24 tickCurrent, , , , ,) = pool.slot0();
(uint256 feeGrowthInside0X128, uint256 feeGrowthAbove1X128) = getFeeGrowthInside(
tickLower,
tickUpper,
tickCurrent,
pool.feeGrowthGlobal0X128(),
pool.feeGrowthGlobal1X128()
);
emit Log(feeGrowthInside0X128, feeGrowthAbove1X128);
}
} |
Also reproduced this bug with uniswap sdk: import JSBI from 'jsbi';
import { TickLibrary } from '@uniswap/v3-sdk';
console.log(
TickLibrary.getFeeGrowthInside(
{
feeGrowthOutside0X128: JSBI.BigInt("48464060636512038136115728978196309"),
feeGrowthOutside1X128: JSBI.BigInt("155431297820226069518189999139402599")
},
{
feeGrowthOutside0X128: JSBI.BigInt("2001227920504599228768954726169803"),
feeGrowthOutside1X128: JSBI.BigInt("1998401698250741836755495414347981")
},
-6,
-2,
-2,
JSBI.BigInt("52059057655713157425077904244139302"),
JSBI.BigInt("158999387230287332017750457411857410")
).toString()
) Output
exact as solidity code |
Ok, for history - here is a rigth formula. |
@Whynot63 I am running into the exact same issue as you where the underflowed result is way too big. In your next comment you seemed to say "here is a right formula" but no formula was included, could you possibly share this formula? |
Preamble
According uniswap whitepaper v3, we could calculate fees per share in the price range between two ticks with formulas 6.17 - 6.19:
feeGrowthGlobal0X128
/feeGrowthGlobal1X128
in pool smart contract)feeGrowthOutside0X128
/feeGrowthOutside1X128
in tick stateHere is simplified version of original code for calculation accumulated fees in range:
Problem
Ok, lets try to calculate fees for pool USDC/USDT - 0.01% on polygon.
Block: 31995913
Tick lower: -6
Tick upper: -2
Calculations for token0:
Python implementation of fees calculation
It uses my wrapper for web3 - web3 premium, but nothing rocket science here is
So, the problem is that fees could not be negative.
Question
So, I calculate fees with formula from whitepaper and get negative fees.
It is the bug or error in my calculations?
The text was updated successfully, but these errors were encountered: