Skip to content

Commit

Permalink
Merge pull request sushiswap#77 from sushiswap/feature/v3-collect-fix
Browse files Browse the repository at this point in the history
fix: protocol fee
  • Loading branch information
OlaStenberg authored Apr 19, 2024
2 parents 880caae + ca1967f commit d491b69
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 4 deletions.
13 changes: 13 additions & 0 deletions subgraphs/v3/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ type Pool @entity {
totalValueLockedUSD: BigDecimal!
# TVL derived in USD untracked
totalValueLockedUSDUntracked: BigDecimal!
# protocol fee
isProtocolFeeEnabled: Boolean!
# Fields used to help derived relationship
liquidityProviderCount: BigInt! # used to detect new exchanges
# hourly snapshots of pool data
Expand Down Expand Up @@ -691,4 +693,15 @@ type DecreaseEvent @entity {
token1: Token!
timeStamp: BigInt!
transaction: Transaction!
}

type SetProtocolFeeEvent @entity {
id: ID!
pool: Pool!
logIndex: BigInt!
new0: BigInt!
new1: BigInt!
old0: BigInt!
old1: BigInt!
timestamp: BigInt!
}
119 changes: 115 additions & 4 deletions subgraphs/v3/src/mappings/core.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable prefer-const */
import { Bundle, Burn, Collect, Factory, Mint, Pool, Swap, Tick, Token } from '../../generated/schema'
import { Bundle, Burn, Collect, Factory, Mint, Pool, SetProtocolFeeEvent, Swap, Tick, Token } from '../../generated/schema'
import { Pool as PoolABI } from '../../generated/Factory/Pool'
import { BigDecimal, BigInt, ethereum, log } from '@graphprotocol/graph-ts'
import {
Expand All @@ -8,7 +8,9 @@ import {
Initialize,
Mint as MintEvent,
Swap as SwapEvent,
Collect as CollectEvent
Collect as CollectEvent,
CollectProtocol as CollectProtocolEvent,
SetFeeProtocol as ProtocolFeeEvent
} from '../../generated/templates/Pool/Pool'
import { convertTokenToDecimal, loadTransaction, safeDiv } from '../utils'
import { FACTORY_ADDRESS, ONE_BI, ZERO_BD, ZERO_BI } from '../constants'
Expand Down Expand Up @@ -286,7 +288,7 @@ export function handleSwap(event: SwapEvent): void {
let amountTotalUSDTracked = safeDiv(getTrackedAmountUSD(amount0Abs, token0, amount1Abs, token1), BigDecimal.fromString('2'))
let amountTotalETHTracked = safeDiv(amountTotalUSDTracked, bundle.ethPriceUSD)
let amountTotalUSDUntracked = safeDiv(amount0USD.plus(amount1USD), BigDecimal.fromString('2'))

let feesETH = amountTotalETHTracked.times(pool.feeTier.toBigDecimal()).div(BigDecimal.fromString('1000000'))
let feesUSD = amountTotalUSDTracked.times(pool.feeTier.toBigDecimal()).div(BigDecimal.fromString('1000000'))

Expand Down Expand Up @@ -334,7 +336,7 @@ export function handleSwap(event: SwapEvent): void {
token1.txCount = token1.txCount.plus(ONE_BI)

// updated pool ratess

let prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token)
pool.token0Price = prices[0]
pool.token1Price = prices[1]
Expand Down Expand Up @@ -574,6 +576,115 @@ export function handlePoolCollect(event: CollectEvent): void {
return
}


export function handleProtocolCollect(event: CollectProtocolEvent): void {
const bundle = Bundle.load('1')!
const pool = Pool.load(event.address.toHexString())
if (pool == null) {
return
}
const transaction = loadTransaction(event)
const factory = Factory.load(FACTORY_ADDRESS.toHex())!

const token0 = Token.load(pool.token0)
const token1 = Token.load(pool.token1)
if (token0 == null || token1 == null) {
return
}

// Get formatted amounts collected.
const collectedAmountToken0 = convertTokenToDecimal(event.params.amount0, token0.decimals)
const collectedAmountToken1 = convertTokenToDecimal(event.params.amount1, token1.decimals)
const trackedCollectedAmountUSD = getTrackedAmountUSD(
collectedAmountToken0,
token0 as Token,
collectedAmountToken1,
token1 as Token
)

// Reset tvl aggregates until new amounts calculated
factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH)

// Update globals
factory.txCount = factory.txCount.plus(ONE_BI)

// update token data
token0.txCount = token0.txCount.plus(ONE_BI)
token0.totalValueLocked = token0.totalValueLocked.minus(collectedAmountToken0)
token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD))

token1.txCount = token1.txCount.plus(ONE_BI)
token1.totalValueLocked = token1.totalValueLocked.minus(collectedAmountToken1)
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD))

// Adjust pool TVL based on amount collected.
pool.txCount = pool.txCount.plus(ONE_BI)
pool.totalValueLockedToken0 = pool.totalValueLockedToken0.minus(collectedAmountToken0)
pool.totalValueLockedToken1 = pool.totalValueLockedToken1.minus(collectedAmountToken1)
pool.totalValueLockedETH = pool.totalValueLockedToken0
.times(token0.derivedETH)
.plus(pool.totalValueLockedToken1.times(token1.derivedETH))
pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD)

// Update aggregate fee collection values.
pool.collectedFeesToken0 = pool.collectedFeesToken0.plus(collectedAmountToken0)
pool.collectedFeesToken1 = pool.collectedFeesToken1.plus(collectedAmountToken1)
pool.collectedFeesUSD = pool.collectedFeesUSD.plus(trackedCollectedAmountUSD)

// reset aggregates with new amounts
factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH)
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD)

const collect = new Collect(transaction.id + '-' + event.logIndex.toString())
collect.transaction = transaction.id
collect.timestamp = event.block.timestamp
collect.pool = pool.id
collect.owner = event.params.recipient
collect.amount0 = collectedAmountToken0
collect.amount1 = collectedAmountToken1
collect.amountUSD = trackedCollectedAmountUSD
collect.tickLower = ZERO_BI
collect.tickUpper = ZERO_BI
collect.logIndex = event.logIndex

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)

token0.save()
token1.save()
factory.save()
pool.save()
collect.save()

return
}

export function handleSetProtocolFee(event: ProtocolFeeEvent): void {
const pool = Pool.load(event.address.toHexString())
if (pool == null) {
return
}

pool.isProtocolFeeEnabled = (event.params.feeProtocol0New > 0 || event.params.feeProtocol1New > 0)
pool.save()

const protocolFeeEvent = new SetProtocolFeeEvent(event.transaction.hash.toHexString() + '-' + event.logIndex.toString())
protocolFeeEvent.pool = pool.id
protocolFeeEvent.logIndex = event.logIndex
protocolFeeEvent.timestamp = event.block.timestamp
protocolFeeEvent.pool = pool.id
protocolFeeEvent.new0 = BigInt.fromI32(event.params.feeProtocol0New)
protocolFeeEvent.new1 = BigInt.fromI32(event.params.feeProtocol1New)
protocolFeeEvent.old0 = BigInt.fromI32(event.params.feeProtocol0Old)
protocolFeeEvent.old1 = BigInt.fromI32(event.params.feeProtocol1Old)
protocolFeeEvent.save()
}

function updateTickFeeVarsAndSave(tick: Tick, event: ethereum.Event): void {
let poolAddress = event.address
// not all ticks are initialized so obtaining null is expected behavior
Expand Down
1 change: 1 addition & 0 deletions subgraphs/v3/src/mappings/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export function handlePoolCreated(event: PoolCreated): void {
pool.collectedFeesToken0 = ZERO_BD
pool.collectedFeesToken1 = ZERO_BD
pool.collectedFeesUSD = ZERO_BD
pool.isProtocolFeeEnabled = false

pool.save()
// create the tracked contract based on the template
Expand Down
4 changes: 4 additions & 0 deletions subgraphs/v3/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,7 @@ templates:
handler: handleFlash
- event: Collect(indexed address,address,indexed int24,indexed int24,uint128,uint128)
handler: handlePoolCollect
- event: CollectProtocol(indexed address,indexed address,uint128,uint128)
handler: handleProtocolCollect
- event: SetFeeProtocol(uint8,uint8,uint8,uint8)
handler: handleSetProtocolFee

0 comments on commit d491b69

Please sign in to comment.