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

Arbitrum minimal - Decimal Fix & Graph-ts Upgade #198

Merged
merged 7 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion abis/ERC20.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"outputs": [
{
"name": "",
"type": "uint8"
"type": "uint32"
}
],
"payable": false,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"watch-local": "graph deploy ianlapham/uniswap-v3 --watch --debug --node http://127.0.0.1:8020/ --ipfs http://localhost:5001"
},
"devDependencies": {
"@graphprotocol/graph-cli": "^0.20.1",
"@graphprotocol/graph-ts": "^0.20.0",
"@graphprotocol/graph-cli": "^0.64.1",
"@graphprotocol/graph-ts": "^0.32.0",
"@typescript-eslint/eslint-plugin": "^2.0.0",
"@typescript-eslint/parser": "^2.0.0",
"eslint": "^6.2.2",
Expand Down
109 changes: 58 additions & 51 deletions src/mappings/core.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable prefer-const */
import { Bundle, Burn, Factory, Mint, Pool, Swap, Tick, Token } from '../types/schema'
import { Pool as PoolABI } from '../types/Factory/Pool'
import { BigDecimal, BigInt, ethereum, } from '@graphprotocol/graph-ts'
import { BigDecimal, BigInt, ethereum } from '@graphprotocol/graph-ts'
import {
Burn as BurnEvent,
Flash as FlashEvent,
Expand All @@ -23,7 +23,7 @@ import {
import { createTick, feeTierToTickSpacing } from '../utils/tick'

export function handleInitialize(event: Initialize): void {
let pool = Pool.load(event.address.toHexString())
let pool = Pool.load(event.address.toHexString())!
pool.sqrtPrice = event.params.sqrtPriceX96
pool.tick = BigInt.fromI32(event.params.tick)
// update token prices
Expand All @@ -33,13 +33,13 @@ export function handleInitialize(event: Initialize): void {
}

export function handleMint(event: MintEvent): void {
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
let poolAddress = event.address.toHexString()
let pool = Pool.load(poolAddress)
let factory = Factory.load(FACTORY_ADDRESS)
let pool = Pool.load(poolAddress)!
let factory = Factory.load(FACTORY_ADDRESS)!

let token0 = Token.load(pool.token0)
let token1 = Token.load(pool.token1)
let token0 = Token.load(pool.token0)!
let token1 = Token.load(pool.token1)!
let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)

Expand Down Expand Up @@ -145,18 +145,18 @@ export function handleMint(event: MintEvent): void {
factory.save()
mint.save()

updateTickFeeVarsAndSave(lowerTick!, event)
updateTickFeeVarsAndSave(upperTick!, event)
updateTickFeeVarsAndSave(lowerTick, event)
updateTickFeeVarsAndSave(upperTick, event)
}

export function handleBurn(event: BurnEvent): void {
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
let poolAddress = event.address.toHexString()
let pool = Pool.load(poolAddress)
let factory = Factory.load(FACTORY_ADDRESS)
let pool = Pool.load(poolAddress)!
let factory = Factory.load(FACTORY_ADDRESS)!

let token0 = Token.load(pool.token0)
let token1 = Token.load(pool.token1)
let token0 = Token.load(pool.token0)!
let token1 = Token.load(pool.token1)!
let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)

Expand Down Expand Up @@ -226,21 +226,24 @@ export function handleBurn(event: BurnEvent): void {
let upperTickId = poolAddress + '#' + BigInt.fromI32(event.params.tickUpper).toString()
let lowerTick = Tick.load(lowerTickId)
let upperTick = Tick.load(upperTickId)
let amount = event.params.amount
lowerTick.liquidityGross = lowerTick.liquidityGross.minus(amount)
lowerTick.liquidityNet = lowerTick.liquidityNet.minus(amount)
upperTick.liquidityGross = upperTick.liquidityGross.minus(amount)
upperTick.liquidityNet = upperTick.liquidityNet.plus(amount)

if (lowerTick && upperTick) {
let amount = event.params.amount
lowerTick.liquidityGross = lowerTick.liquidityGross.minus(amount)
lowerTick.liquidityNet = lowerTick.liquidityNet.minus(amount)
upperTick.liquidityGross = upperTick.liquidityGross.minus(amount)
upperTick.liquidityNet = upperTick.liquidityNet.plus(amount)

updateTickFeeVarsAndSave(lowerTick, event)
updateTickFeeVarsAndSave(upperTick, event)
}
updateUniswapDayData(event)
updatePoolDayData(event)
updatePoolHourData(event)
updateTokenDayData(token0 as Token, event)
updateTokenDayData(token1 as Token, event)
updateTokenHourData(token0 as Token, event)
updateTokenHourData(token1 as Token, event)
updateTickFeeVarsAndSave(lowerTick!, event)
updateTickFeeVarsAndSave(upperTick!, event)

token0.save()
token1.save()
Expand All @@ -250,23 +253,23 @@ export function handleBurn(event: BurnEvent): void {
}

export function handleSwap(event: SwapEvent): void {
let bundle = Bundle.load('1')
let factory = Factory.load(FACTORY_ADDRESS)
let pool = Pool.load(event.address.toHexString())
let bundle = Bundle.load('1')!
let factory = Factory.load(FACTORY_ADDRESS)!
let pool = Pool.load(event.address.toHexString())!

// hot fix for bad pricing
if (pool.id == '0x9663f2ca0454accad3e094448ea6f77443880454') {
return
}

let token0 = Token.load(pool.token0)
let token1 = Token.load(pool.token1)
let token0 = Token.load(pool.token0)!
let token1 = Token.load(pool.token1)!

// amounts - 0/1 are token deltas: can be positive or negative
let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)

let oldTick = pool.tick!
let oldTick = pool.tick

// need absolute amounts for volume
let amount0Abs = amount0
Expand Down Expand Up @@ -429,6 +432,7 @@ export function handleSwap(event: SwapEvent): void {
token1DayData.save()
uniswapDayData.save()
poolDayData.save()
poolHourData.save()
factory.save()
pool.save()
token0.save()
Expand All @@ -443,33 +447,36 @@ export function handleSwap(event: SwapEvent): void {
loadTickUpdateFeeVarsAndSave(newTick.toI32(), event)
}

let numIters = oldTick
.minus(newTick)
.abs()
.div(tickSpacing)

if (numIters.gt(BigInt.fromI32(100))) {
// In case more than 100 ticks need to be updated ignore the update in
// order to avoid timeouts. From testing this behavior occurs only upon
// pool initialization. This should not be a big issue as the ticks get
// updated later. For early users this error also disappears when calling
// collect
} else if (newTick.gt(oldTick)) {
let firstInitialized = oldTick.plus(tickSpacing.minus(modulo))
for (let i = firstInitialized; i.le(newTick); i = i.plus(tickSpacing)) {
loadTickUpdateFeeVarsAndSave(i.toI32(), event)
}
} else if (newTick.lt(oldTick)) {
let firstInitialized = oldTick.minus(modulo)
for (let i = firstInitialized; i.ge(newTick); i = i.minus(tickSpacing)) {
loadTickUpdateFeeVarsAndSave(i.toI32(), event)
if (oldTick) {
let numIters = oldTick
.minus(newTick)
.abs()
.div(tickSpacing)

if (numIters.gt(BigInt.fromI32(100))) {
// In case more than 100 ticks need to be updated ignore the update in
// order to avoid timeouts. From testing this behavior occurs only upon
// pool initialization. This should not be a big issue as the ticks get
// updated later. For early users this error also disappears when calling
// collect
} else if (newTick.gt(oldTick)) {
let firstInitialized = oldTick.plus(tickSpacing.minus(modulo))
for (let i = firstInitialized; i.le(newTick); i = i.plus(tickSpacing)) {
loadTickUpdateFeeVarsAndSave(i.toI32(), event)
}
} else if (newTick.lt(oldTick)) {
let firstInitialized = oldTick.minus(modulo)
for (let i = firstInitialized; i.ge(newTick); i = i.minus(tickSpacing)) {
loadTickUpdateFeeVarsAndSave(i.toI32(), event)
}
}
}
}

export function handleFlash(event: FlashEvent): void {
// update fee growth
let pool = Pool.load(event.address.toHexString())

let pool = Pool.load(event.address.toHexString())!
pool.save()
}

Expand All @@ -482,7 +489,7 @@ function updateTickFeeVarsAndSave(tick: Tick, event: ethereum.Event): void {
// tick.feeGrowthOutside1X128 = tickResult.value3
tick.save()

updateTickDayData(tick!, event)
updateTickDayData(tick, event)
}

function loadTickUpdateFeeVarsAndSave(tickId: i32, event: ethereum.Event): void {
Expand All @@ -494,6 +501,6 @@ function loadTickUpdateFeeVarsAndSave(tickId: i32, event: ethereum.Event): void
.concat(tickId.toString())
)
if (tick !== null) {
updateTickFeeVarsAndSave(tick!, event)
updateTickFeeVarsAndSave(tick, event)
}
}
}
22 changes: 5 additions & 17 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable prefer-const */
import { BigInt, BigDecimal, ethereum } from '@graphprotocol/graph-ts'
import { Transaction } from '../types/schema'
import { ONE_BI, ZERO_BI, ZERO_BD, ONE_BD, TWO_BI, } from '../utils/constants'
import { ONE_BI, ZERO_BI, ZERO_BD, ONE_BD, TWO_BI } from '../utils/constants'

export function exponentToBigDecimal(decimals: BigInt): BigDecimal {
let bd = BigDecimal.fromString('1')
Expand All @@ -24,25 +24,13 @@ export function bigDecimalExponated(value: BigDecimal, power: BigInt): BigDecima
if (power.equals(ZERO_BI)) {
return ONE_BD
}

let negativePower = power.lt(ZERO_BI)
let evenPower = ZERO_BD.plus(value)
let result = ZERO_BD.plus(value)
let powerAbs = power.abs()
let oddPower = ONE_BD

while (powerAbs.lt(ONE_BI)) {
if (powerAbs % TWO_BI == ZERO_BI) {
evenPower = evenPower * evenPower
powerAbs = powerAbs/TWO_BI
} else {
oddPower = evenPower * oddPower
evenPower = evenPower * evenPower
powerAbs = (powerAbs - ONE_BI) / TWO_BI
}
for (let i = ONE_BI; i.lt(powerAbs); i = i.plus(ONE_BI)) {
result = result.times(value)
}

let result = evenPower * oddPower

if (negativePower) {
result = safeDiv(ONE_BD, result)
}
Expand Down Expand Up @@ -99,7 +87,7 @@ export function loadTransaction(event: ethereum.Event): Transaction {
}
transaction.blockNumber = event.block.number
transaction.timestamp = event.block.timestamp
transaction.gasUsed = event.transaction.gasUsed
transaction.gasUsed = BigInt.zero() //needs to be moved to transaction receipt
transaction.gasPrice = event.transaction.gasPrice
transaction.save()
return transaction as Transaction
Expand Down
10 changes: 5 additions & 5 deletions src/utils/intervalUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ethereum } from '@graphprotocol/graph-ts'
* @param event
*/
export function updateUniswapDayData(event: ethereum.Event): UniswapDayData {
let uniswap = Factory.load(FACTORY_ADDRESS)
let uniswap = Factory.load(FACTORY_ADDRESS)!
let timestamp = event.block.timestamp.toI32()
let dayID = timestamp / 86400 // rounded
let dayStartTimestamp = dayID * 86400
Expand All @@ -48,7 +48,7 @@ export function updatePoolDayData(event: ethereum.Event): PoolDayData {
.toHexString()
.concat('-')
.concat(dayID.toString())
let pool = Pool.load(event.address.toHexString())
let pool = Pool.load(event.address.toHexString())!
let poolDayData = PoolDayData.load(dayPoolID)
if (poolDayData === null) {
poolDayData = new PoolDayData(dayPoolID)
Expand Down Expand Up @@ -93,7 +93,7 @@ export function updatePoolHourData(event: ethereum.Event): PoolHourData {
.toHexString()
.concat('-')
.concat(hourIndex.toString())
let pool = Pool.load(event.address.toHexString())
let pool = Pool.load(event.address.toHexString())!
let poolHourData = PoolHourData.load(hourPoolID)
if (poolHourData === null) {
poolHourData = new PoolHourData(hourPoolID)
Expand Down Expand Up @@ -133,7 +133,7 @@ export function updatePoolHourData(event: ethereum.Event): PoolHourData {
}

export function updateTokenDayData(token: Token, event: ethereum.Event): TokenDayData {
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
let timestamp = event.block.timestamp.toI32()
let dayID = timestamp / 86400
let dayStartTimestamp = dayID * 86400
Expand Down Expand Up @@ -176,7 +176,7 @@ export function updateTokenDayData(token: Token, event: ethereum.Event): TokenDa
}

export function updateTokenHourData(token: Token, event: ethereum.Event): TokenHourData {
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
let timestamp = event.block.timestamp.toI32()
let hourIndex = timestamp / 3600 // get unique hour within unix history
let hourStartUnix = hourIndex * 3600 // want the rounded effect
Expand Down
51 changes: 29 additions & 22 deletions src/utils/pricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ export let WHITELIST_TOKENS: string[] = [
'0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9' // USDT
]

let MINIMUM_ETH_LOCKED = BigDecimal.fromString('4')
let MINIMUM_ETH_LOCKED = BigDecimal.fromString('60')

let Q192 = BigInt.fromI32(2).pow(192 as u8)

let Q192 = 2 ** 192
export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, token1: Token): BigDecimal[] {
let num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal()
let denom = BigDecimal.fromString(Q192.toString())
Expand Down Expand Up @@ -61,26 +62,32 @@ export function findEthPerToken(token: Token): BigDecimal {
for (let i = 0; i < whiteList.length; ++i) {
let poolAddress = whiteList[i]
let pool = Pool.load(poolAddress)
if (pool.liquidity.gt(ZERO_BI)) {
if (pool.token0 == token.id) {
// whitelist token is token1
let token1 = Token.load(pool.token1)
// get the derived ETH in pool
let ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) {
largestLiquidityETH = ethLocked
// token1 per our token * Eth per token1
priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal)
if (pool) {
if (pool.liquidity.gt(ZERO_BI)) {
if (pool.token0 == token.id) {
// whitelist token is token1
let token1 = Token.load(pool.token1)
// get the derived ETH in pool
if (token1) {
let ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) {
largestLiquidityETH = ethLocked
// token1 per our token * Eth per token1
priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal)
}
}
}
}
if (pool.token1 == token.id) {
let token0 = Token.load(pool.token0)
// get the derived ETH in pool
let ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) {
largestLiquidityETH = ethLocked
// token0 per our token * ETH per token0
priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal)
if (pool.token1 == token.id) {
let token0 = Token.load(pool.token0)
// get the derived ETH in pool
if (token0) {
let ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) {
largestLiquidityETH = ethLocked
// token0 per our token * ETH per token0
priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal)
}
}
}
}
}
Expand All @@ -100,7 +107,7 @@ export function getTrackedAmountUSD(
tokenAmount1: BigDecimal,
token1: Token
): BigDecimal {
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
let price0USD = token0.derivedETH.times(bundle.ethPriceUSD)
let price1USD = token1.derivedETH.times(bundle.ethPriceUSD)

Expand Down
Loading
Loading