Skip to content

Commit

Permalink
new snapshots, optimized eth calls, gasused
Browse files Browse the repository at this point in the history
  • Loading branch information
kalinbas committed Jul 31, 2024
1 parent d3c2c45 commit 7bd2624
Show file tree
Hide file tree
Showing 9 changed files with 2,187 additions and 1,421 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"scripts": {
"codegen": "graph codegen --output-dir src/types/",
"build": "graph build",
"deploy": "graph deploy --product hosted-service revert-finance/uniswap-v3-mainnet"
"deploy": "graph deploy --product subgraph-studio uniswap-v3-mainnet"
},
"devDependencies": {
"@graphprotocol/graph-cli": "^0.21.1",
"@graphprotocol/graph-ts": "^0.20.0",
"@graphprotocol/graph-cli": "^0.70.0",
"@graphprotocol/graph-ts": "^0.35.0",
"@typescript-eslint/eslint-plugin": "^2.0.0",
"@typescript-eslint/parser": "^2.0.0",
"eslint": "^6.2.2",
Expand Down
6 changes: 6 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ type PositionSnapshot @entity {
# internal vars needed for fee computation
feeGrowthInside0LastX128: BigInt!
feeGrowthInside1LastX128: BigInt!

# current price values for quick querying
ethPriceUSD: BigDecimal
derivedETHToken0: BigDecimal
derivedETHToken1: BigDecimal
derivedETHNative: BigDecimal
}

type Transaction @entity {
Expand Down
97 changes: 57 additions & 40 deletions src/mappings/core.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable prefer-const */
import { Bundle, Burn, Collect, Factory, Mint, Pool, Token } from '../types/schema'
import { Bundle, Burn, Collect, Factory, Mint, Pool, Token } from '../types/schema'
import { Pool as PoolABI } from '../types/Factory/Pool'
import { BigDecimal, BigInt, ethereum } from '@graphprotocol/graph-ts'
import { BigDecimal, BigInt, ethereum, log } from '@graphprotocol/graph-ts'
import {
Burn as BurnEvent,
Flash as FlashEvent,
Expand All @@ -15,17 +16,17 @@ import { FACTORY_ADDRESS, ONE_BI, ZERO_BD, ZERO_BI } from '../utils/constants'
import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices } from '../utils/pricing'

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)
pool.save()

// update token prices
let token0 = Token.load(pool.token0)
let token1 = Token.load(pool.token1)
let token0 = Token.load(pool.token0)!
let token1 = Token.load(pool.token1)!

// update ETH price now that prices could have changed
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!
bundle.ethPriceUSD = getEthPriceInUSD()
bundle.save()

Expand All @@ -37,13 +38,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 @@ -117,13 +118,13 @@ export function handleMint(event: MintEvent): void {
}

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 All @@ -150,6 +151,17 @@ export function handleBurn(event: BurnEvent): void {
// update token1 data
token1.txCount = token1.txCount.plus(ONE_BI)

// pool data
pool.txCount = pool.txCount.plus(ONE_BI)
// update globals
factory.txCount = factory.txCount.plus(ONE_BI)

// update token0 data
token0.txCount = token0.txCount.plus(ONE_BI)

// update token1 data
token1.txCount = token1.txCount.plus(ONE_BI)

// pool data
pool.txCount = pool.txCount.plus(ONE_BI)

Expand Down Expand Up @@ -181,17 +193,14 @@ 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)
Expand All @@ -212,6 +221,7 @@ export function handleSwap(event: SwapEvent): void {
let amount0USD = amount0ETH.times(bundle.ethPriceUSD)
let amount1USD = amount1ETH.times(bundle.ethPriceUSD)


// get amount that should be tracked only - div 2 because cant count both input and output as volume
let amountTotalUSDTracked = getTrackedAmountUSD(amount0Abs, token0 as Token, amount1Abs, token1 as Token).div(
BigDecimal.fromString('2')
Expand Down Expand Up @@ -244,7 +254,7 @@ export function handleSwap(event: SwapEvent): void {

// Update the pool with the new active liquidity, price, and tick.
pool.liquidity = event.params.liquidity
pool.tick = BigInt.fromI32(event.params.tick as i32)
pool.tick = BigInt.fromI32(event.params.tick)
pool.sqrtPrice = event.params.sqrtPriceX96
pool.totalValueLockedToken0 = pool.totalValueLockedToken0.plus(amount0)
pool.totalValueLockedToken1 = pool.totalValueLockedToken1.plus(amount1)
Expand Down Expand Up @@ -274,9 +284,11 @@ export function handleSwap(event: SwapEvent): void {
// update USD pricing
bundle.ethPriceUSD = getEthPriceInUSD()
bundle.save()

token0.derivedETH = findEthPerToken(token0 as Token, token1 as Token)
token1.derivedETH = findEthPerToken(token1 as Token, token0 as Token)


/**
* Things afffected by new USD rates
*/
Expand All @@ -293,10 +305,13 @@ export function handleSwap(event: SwapEvent): void {

// update fee growth
let poolContract = PoolABI.bind(event.address)
let feeGrowthGlobal0X128 = poolContract.feeGrowthGlobal0X128()
let feeGrowthGlobal1X128 = poolContract.feeGrowthGlobal1X128()
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128 as BigInt
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128 as BigInt

let feeGrowthGlobal0X128 = poolContract.try_feeGrowthGlobal0X128()
let feeGrowthGlobal1X128 = poolContract.try_feeGrowthGlobal1X128()
if (!feeGrowthGlobal0X128.reverted && !feeGrowthGlobal1X128.reverted) {
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128.value
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128.value
}

factory.save()
pool.save()
Expand All @@ -306,11 +321,11 @@ export function handleSwap(event: SwapEvent): void {

export function handleCollect(event: CollectEvent): void {

let pool = Pool.load(event.address.toHexString())
let factory = Factory.load(FACTORY_ADDRESS)
let bundle = Bundle.load('1')
let token0 = Token.load(pool.token0)
let token1 = Token.load(pool.token1)
let pool = Pool.load(event.address.toHexString())!
let factory = Factory.load(FACTORY_ADDRESS)!
let bundle = Bundle.load('1')!
let token0 = Token.load(pool.token0)!
let token1 = Token.load(pool.token1)!
let transaction = loadTransaction(event)

let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
Expand Down Expand Up @@ -369,11 +384,13 @@ export function handleCollect(event: CollectEvent): void {

export function handleFlash(event: FlashEvent): void {
// update fee growth
let pool = Pool.load(event.address.toHexString())
let pool = Pool.load(event.address.toHexString())!
let poolContract = PoolABI.bind(event.address)
let feeGrowthGlobal0X128 = poolContract.feeGrowthGlobal0X128()
let feeGrowthGlobal1X128 = poolContract.feeGrowthGlobal1X128()
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128 as BigInt
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128 as BigInt
pool.save()
let feeGrowthGlobal0X128 = poolContract.try_feeGrowthGlobal0X128()
let feeGrowthGlobal1X128 = poolContract.try_feeGrowthGlobal1X128()
if (!feeGrowthGlobal0X128.reverted && !feeGrowthGlobal1X128.reverted) {
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128.value
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128.value
pool.save()
}
}
64 changes: 28 additions & 36 deletions src/mappings/position-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@ import { Bundle, Position, PositionSnapshot, Token } from '../types/schema'
import { ADDRESS_ZERO, factoryContract, ZERO_BD, ZERO_BI } from '../utils/constants'
import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'
import { convertTokenToDecimal, loadTransaction } from '../utils'
import { getNativePriceInETH } from '../utils/pricing'

function getPosition(event: ethereum.Event, tokenId: BigInt): Position | null {
let position = Position.load(tokenId.toString())
if (position === null) {
let contract = NonfungiblePositionManager.bind(event.address)
let positionCall = contract.try_positions(tokenId)

// the following call reverts in situations where the position is minted
// and deleted in the same block - from my investigation this happens
// in calls from BancorSwap
// (e.g. 0xf7867fa19aa65298fadb8d4f72d0daed5e836f3ba01f0b9b9631cdc6c36bed40)

if (!positionCall.reverted) {
let positionResult = positionCall.value
let poolAddress = factoryContract.getPool(positionResult.value2, positionResult.value3, positionResult.value4)
Expand Down Expand Up @@ -65,7 +63,7 @@ function updateFeeVars(position: Position, event: ethereum.Event, tokenId: BigIn
return position
}

function savePositionSnapshot(position: Position, event: ethereum.Event): void {
function savePositionSnapshot(position: Position, event: ethereum.Event, bundle: Bundle, token0: Token, token1: Token): void {
let positionSnapshot = new PositionSnapshot(position.id.concat('#').concat(event.block.number.toString()))
positionSnapshot.owner = position.owner
positionSnapshot.pool = position.pool
Expand All @@ -82,6 +80,10 @@ function savePositionSnapshot(position: Position, event: ethereum.Event): void {
positionSnapshot.transaction = loadTransaction(event).id
positionSnapshot.feeGrowthInside0LastX128 = position.feeGrowthInside0LastX128
positionSnapshot.feeGrowthInside1LastX128 = position.feeGrowthInside1LastX128
positionSnapshot.ethPriceUSD = bundle.ethPriceUSD
positionSnapshot.derivedETHToken0 = token0.derivedETH
positionSnapshot.derivedETHToken1 = token1.derivedETH
positionSnapshot.derivedETHNative = getNativePriceInETH()
positionSnapshot.save()
}

Expand All @@ -93,14 +95,10 @@ export function handleIncreaseLiquidity(event: IncreaseLiquidity): void {
return
}

// temp fix
if (Address.fromString(position.pool).equals(Address.fromHexString('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248'))) {
return
}
let bundle = Bundle.load('1')
let bundle = Bundle.load('1')!

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

let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)
Expand All @@ -114,9 +112,9 @@ export function handleIncreaseLiquidity(event: IncreaseLiquidity): void {
.plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD)))
position.amountDepositedUSD = position.amountDepositedUSD.plus(newDepositUSD)

position = updateFeeVars(position!, event, event.params.tokenId)
position = updateFeeVars(position, event, event.params.tokenId)
position.save()
savePositionSnapshot(position!, event)
savePositionSnapshot(position, event, bundle, token0, token1)
}

export function handleDecreaseLiquidity(event: DecreaseLiquidity): void {
Expand All @@ -127,14 +125,9 @@ export function handleDecreaseLiquidity(event: DecreaseLiquidity): void {
return
}

// temp fix
if (Address.fromString(position.pool).equals(Address.fromHexString('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248'))) {
return
}

let bundle = Bundle.load('1')
let token0 = Token.load(position.token0)
let token1 = Token.load(position.token1)
let bundle = Bundle.load('1')!
let token0 = Token.load(position.token0)!
let token1 = Token.load(position.token1)!
let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)

Expand All @@ -147,9 +140,9 @@ export function handleDecreaseLiquidity(event: DecreaseLiquidity): void {
.plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD)))
position.amountWithdrawnUSD = position.amountWithdrawnUSD.plus(newWithdrawUSD)

position = updateFeeVars(position!, event, event.params.tokenId)
position = updateFeeVars(position, event, event.params.tokenId)
position.save()
savePositionSnapshot(position!, event)
savePositionSnapshot(position, event, bundle, token0, token1)
}

export function handleCollect(event: Collect): void {
Expand All @@ -158,13 +151,11 @@ export function handleCollect(event: Collect): void {
if (position == null) {
return
}
if (Address.fromString(position.pool).equals(Address.fromHexString('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248'))) {
return
}

let bundle = Bundle.load('1')
let token0 = Token.load(position.token0)
let token1 = Token.load(position.token1)

let bundle = Bundle.load('1')!
let token0 = Token.load(position.token0)!
let token1 = Token.load(position.token1)!
let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals)
position.collectedToken0 = position.collectedToken0.plus(amount0)
Expand All @@ -178,21 +169,22 @@ export function handleCollect(event: Collect): void {
.plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD)))
position.amountCollectedUSD = position.amountCollectedUSD.plus(newCollectUSD)

position = updateFeeVars(position!, event, event.params.tokenId)
position = updateFeeVars(position, event, event.params.tokenId)
position.save()
savePositionSnapshot(position!, event)
savePositionSnapshot(position, event, bundle, token0, token1)
}

export function handleTransfer(event: Transfer): void {
let position = getPosition(event, event.params.tokenId)

// position was not able to be fetched
if (position == null) {
if (position === null) {
return
}

position.owner = event.params.to
position.save()

savePositionSnapshot(position!, event)
let bundle = Bundle.load('1')!
let token0 = Token.load(position.token0)!
let token1 = Token.load(position.token1)!
savePositionSnapshot(position, event, bundle, token0, token1)
}
6 changes: 5 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ export function loadTransaction(event: ethereum.Event): Transaction {
}
transaction.blockNumber = event.block.number
transaction.timestamp = event.block.timestamp
transaction.gasUsed = event.transaction.gasUsed
if (event.receipt) {
transaction.gasUsed = event.receipt!.gasUsed
} else {
transaction.gasUsed = ZERO_BI
}
transaction.gasPrice = event.transaction.gasPrice
transaction.save()
return transaction as Transaction
Expand Down
Loading

0 comments on commit 7bd2624

Please sign in to comment.