Skip to content

Commit

Permalink
Merge pull request #198 from Data-Nexus/arbitrum-minimal
Browse files Browse the repository at this point in the history
Arbitrum minimal - Decimal Fix & Graph-ts Upgade
  • Loading branch information
ianlapham authored Feb 26, 2024
2 parents ef57aad + e029aec commit f201897
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 148 deletions.
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

0 comments on commit f201897

Please sign in to comment.