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

Fix issue handling bucketTake events #30

Merged
merged 3 commits into from
Jul 13, 2023
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 clean-container.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
docker-compose down -v
docker compose down -v
docker rm ajna-testnet-subgraph
sudo rm -rf data
3 changes: 2 additions & 1 deletion schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,18 @@ type BucketBankruptcy @entity(immutable: true) {

type BucketTake @entity(immutable: true) {
id: Bytes!
borrower: Bytes! # address
taker: Bytes! # address of the taker
liquidationAuction: LiquidationAuction! # liquidation auction in which the take is occuring
loan: Loan! # loan which was taken
pool: Pool! # pool in which the take is occuring
borrower: Bytes! # address
index: Int! # uint256
auctionPrice: BigDecimal! # price of auction when taken
amount: BigDecimal! # uint256
collateral: BigDecimal! # uint256
bondChange: BigDecimal! # uint256
isReward: Boolean! # bool
lpAwarded: BucketTakeLPAwarded!
blockNumber: BigInt!
blockTimestamp: BigInt!
transactionHash: Bytes!
Expand Down
109 changes: 50 additions & 59 deletions src/erc-20-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import { loadOrCreateAccount, updateAccountLends, updateAccountLoans, updateAcco
import { getBucketId, getBucketInfo, loadOrCreateBucket } from "./utils/bucket"
import { getLendId, loadOrCreateLend } from "./utils/lend"
import { getBorrowerInfo, getLoanId, loadOrCreateLoan } from "./utils/loan"
import { getBucketTakeLPAwardedId, getLiquidationAuctionId, getAuctionInfoERC20Pool, loadOrCreateLiquidationAuction, updateLiquidationAuction, getAuctionStatus } from "./utils/liquidation"
import { getLiquidationAuctionId, getAuctionInfoERC20Pool, loadOrCreateLiquidationAuction, updateLiquidationAuction, getAuctionStatus, loadOrCreateBucketTake } from "./utils/liquidation"
import { getBurnInfo, updatePool, addLiquidationToPool, addReserveAuctionToPool, getLenderInfo, getRatesAndFees } from "./utils/pool"
import { lpbValueInQuote } from "./utils/common"
import { loadOrCreateReserveAuction, reserveAuctionKickerReward } from "./utils/reserve-auction"
Expand Down Expand Up @@ -313,9 +313,8 @@ export function handleBucketBankruptcy(event: BucketBankruptcyEvent): void {
}

export function handleBucketTake(event: BucketTakeEvent): void {
const bucketTake = new BucketTake(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to assume the next log index at all? Shouldn't the transaction hash and block number concat still work for the ID?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how block number helps us. A transaction hash may contain multiple bucketTake actions. As such, we need the log index. The LP award should always be followed by the bucket take event.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm, I had the issue backwards - this makes sense

event.transaction.hash.concatI32(event.block.number.toI32())
)
const bucketTakeId = event.transaction.hash.concatI32(event.logIndex.toI32());
const bucketTake = BucketTake.load(bucketTakeId)!
bucketTake.borrower = event.params.borrower
bucketTake.taker = event.transaction.from
bucketTake.index = event.params.index.toU32()
Expand Down Expand Up @@ -373,6 +372,34 @@ export function handleBucketTake(event: BucketTakeEvent): void {
kick.locked = kick.locked.minus(wadToDecimal(event.params.bondChange))
}

// update bucket state
const bucketId = getBucketId(pool.id, bucketTake.index)
const bucket = loadOrCreateBucket(pool.id, bucketId, bucketTake.index)
const bucketInfo = getBucketInfo(pool.id, bucket.bucketIndex)
bucket.collateral = wadToDecimal(bucketInfo.collateral)
bucket.deposit = wadToDecimal(bucketInfo.quoteTokens)
bucket.lpb = wadToDecimal(bucketInfo.lpb)
bucket.exchangeRate = wadToDecimal(bucketInfo.exchangeRate)

// update lend state for kicker
const lpAwardedId = event.transaction.hash.concatI32(event.logIndex.toI32() - 1);
const bucketTakeLpAwarded = BucketTakeLPAwarded.load(lpAwardedId)!
const kickerLendId = getLendId(bucketId, bucketTakeLpAwarded.kicker)
const kickerLend = loadOrCreateLend(bucketId, kickerLendId, pool.id, bucketTakeLpAwarded.kicker)
kickerLend.lpb = kickerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker)
kickerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, kickerLend.lpb)

// update kicker account state if they weren't a lender already
const kickerAccountId = bucketTakeLpAwarded.kicker
const kickerAccount = loadOrCreateAccount(kickerAccountId)
updateAccountLends(kickerAccount, kickerLend)

// update lend state for taker
const takerLendId = getLendId(bucketId, bucketTakeLpAwarded.taker)
const takerLend = loadOrCreateLend(bucketId, takerLendId, pool.id, bucketTakeLpAwarded.taker)
takerLend.lpb = takerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker)
takerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, takerLend.lpb)

// update bucketTake pointers
bucketTake.liquidationAuction = auction.id
bucketTake.loan = loanId
Expand All @@ -381,72 +408,37 @@ export function handleBucketTake(event: BucketTakeEvent): void {
// save entities to the store
account.save()
auction.save()
bucket.save()
bucketTake.save()
loan.save()
pool.save()
bucketTake.save()
kickerAccount.save()
kickerLend.save()
takerLend.save()
}

export function handleBucketTakeLPAwarded(
event: BucketTakeLPAwardedEvent
): void {
const bucketTakeLpAwarded = new BucketTakeLPAwarded(
event.transaction.hash.concatI32(event.logIndex.toI32())
)
bucketTakeLpAwarded.taker = event.params.taker
bucketTakeLpAwarded.kicker = event.params.kicker
bucketTakeLpAwarded.lpAwardedTaker = wadToDecimal(event.params.lpAwardedTaker)
const lpAwardedId = event.transaction.hash.concatI32(event.logIndex.toI32());
const bucketTakeLpAwarded = new BucketTakeLPAwarded(lpAwardedId)
bucketTakeLpAwarded.taker = event.params.taker
bucketTakeLpAwarded.pool = addressToBytes(event.address)
bucketTakeLpAwarded.kicker = event.params.kicker
bucketTakeLpAwarded.lpAwardedTaker = wadToDecimal(event.params.lpAwardedTaker)
bucketTakeLpAwarded.lpAwardedKicker = wadToDecimal(event.params.lpAwardedKicker)

bucketTakeLpAwarded.blockNumber = event.block.number
bucketTakeLpAwarded.blockTimestamp = event.block.timestamp
bucketTakeLpAwarded.blockNumber = event.block.number
bucketTakeLpAwarded.blockTimestamp = event.block.timestamp
bucketTakeLpAwarded.transactionHash = event.transaction.hash
bucketTakeLpAwarded.save()

// update entities
const pool = Pool.load(addressToBytes(event.address))
if (pool != null) {
// pool doesn't need to be updated as it was already updated in the concurrent BucketTake event

// load BucketTake entity to access the index used for bucketTake
const bucketTakeId = getBucketTakeLPAwardedId(event.transaction.hash, event.logIndex)
const bucketTake = BucketTake.load(bucketTakeId)!

// update bucket state
const bucketId = getBucketId(pool.id, bucketTake.index)
const bucket = loadOrCreateBucket(pool.id, bucketId, bucketTake.index)
const bucketInfo = getBucketInfo(pool.id, bucket.bucketIndex)
bucket.collateral = wadToDecimal(bucketInfo.collateral)
bucket.deposit = wadToDecimal(bucketInfo.quoteTokens)
bucket.lpb = wadToDecimal(bucketInfo.lpb)
bucket.exchangeRate = wadToDecimal(bucketInfo.exchangeRate)

// update lend state for kicker
const kickerLendId = getLendId(bucketId, bucketTakeLpAwarded.kicker)
const kickerLend = loadOrCreateLend(bucketId, kickerLendId, pool.id, bucketTakeLpAwarded.kicker)
kickerLend.lpb = kickerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker)
kickerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, kickerLend.lpb)

// update kicker account state if they weren't a lender already
const kickerAccountId = bucketTakeLpAwarded.kicker
const kickerAccount = loadOrCreateAccount(kickerAccountId)
updateAccountLends(kickerAccount, kickerLend)

// update lend state for taker
const takerLendId = getLendId(bucketId, bucketTakeLpAwarded.taker)
const takerLend = loadOrCreateLend(bucketId, takerLendId, pool.id, bucketTakeLpAwarded.taker)
takerLend.lpb = takerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker)
takerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, takerLend.lpb)

// save entities to store
bucket.save()
kickerAccount.save()
kickerLend.save()
takerLend.save()
pool.save()

bucketTakeLpAwarded.pool = pool.id
}

bucketTakeLpAwarded.save()
// since this is emitted immediately before BucketTakeEvent, create BucketTake entity to associate it with this LP award
const bucketTakeId = event.transaction.hash.concatI32(event.logIndex.toI32() + 1)
const bucketTake = loadOrCreateBucketTake(bucketTakeId)
bucketTake.lpAwarded = lpAwardedId
bucketTake.save()
}

export function handleDecreaseLPAllowance(event: DecreaseLPAllowanceEvent): void {
Expand Down Expand Up @@ -902,7 +894,6 @@ export function handleRepayDebt(event: RepayDebtEvent): void {
repayDebt.save()
}


// called on both start and take reserves
export function handleReserveAuctionKick(event: KickReserveAuctionEvent): void {
// create the ReserveAuctionKick entity (immutable) and ReserveAuction entity (mutable)
Expand Down
37 changes: 28 additions & 9 deletions src/utils/liquidation.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { Address, BigDecimal, BigInt, Bytes, Value, dataSource } from "@graphprotocol/graph-ts"

import { LiquidationAuction, Kick, Loan, Pool } from "../../generated/schema"
import { LiquidationAuction, Kick, Loan, Pool, BucketTake } from "../../generated/schema"
import { ERC20Pool } from '../../generated/templates/ERC20Pool/ERC20Pool'

import { wadToDecimal } from "./convert"
import { ONE_BI, ZERO_BD, poolInfoUtilsAddressTable } from "./constants"
import { ONE_BI, ZERO_ADDRESS, ZERO_BD, ZERO_BI, poolInfoUtilsAddressTable } from "./constants"
import { PoolInfoUtils } from "../../generated/templates/ERC20Pool/PoolInfoUtils"

export function getLiquidationAuctionId(poolId: Bytes, loanId: Bytes, kickBlock: BigInt): Bytes {
return poolId.concat(Bytes.fromUTF8('|' + loanId.toString() + '|' + kickBlock.toString()))
}

export function getBucketTakeLPAwardedId(transactionHash: Bytes, logIndex: BigInt): Bytes {
// assume that the logIndex is always one greater given the order of emitted events
// should handle case where multiple BucketTakes are performed in a single multicall TX
return transactionHash.concatI32(logIndex.toI32())
}

export function loadOrCreateLiquidationAuction(poolId: Bytes, liquidationAuctionId: Bytes, kick: Kick, loan: Loan): LiquidationAuction {
let liquidationAuction = LiquidationAuction.load(liquidationAuctionId)
if (liquidationAuction == null) {
Expand Down Expand Up @@ -134,4 +128,29 @@ export function getAuctionStatus(pool: Pool, borrower: Address): AuctionStatus {
result.value4,
result.value5
)
}
}

export function loadOrCreateBucketTake(id: Bytes): BucketTake {
let bucketTake = BucketTake.load(id)
if (bucketTake == null) {
// create new account if account hasn't already been stored
bucketTake = new BucketTake(id) as BucketTake

bucketTake.borrower = ZERO_ADDRESS
bucketTake.taker = ZERO_ADDRESS
bucketTake.liquidationAuction = Bytes.fromI32(0)
bucketTake.loan = Bytes.fromI32(0)
bucketTake.pool = Bytes.fromI32(0)
bucketTake.index = 0
bucketTake.auctionPrice = ZERO_BD
bucketTake.amount = ZERO_BD
bucketTake.collateral = ZERO_BD
bucketTake.bondChange = ZERO_BD
bucketTake.isReward = false
bucketTake.lpAwarded = Bytes.fromI32(0)
bucketTake.blockNumber = ZERO_BI
bucketTake.blockTimestamp = ZERO_BI
bucketTake.transactionHash = Bytes.fromI32(0)
}
return bucketTake;
}
32 changes: 16 additions & 16 deletions subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ dataSources:
name: PositionManager
source:
abi: PositionManager
address: "0x0000000000000000000000000000000000000000"
startBlock: 17622995
address: "0x37048D43A65748409B04f4051eEd9480BEf68c82"
startBlock: 9289397
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down Expand Up @@ -46,13 +46,13 @@ dataSources:
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
file: ./src/position-manager.ts
network: mainnet
network: goerli
- kind: ethereum
name: ERC20PoolFactory
source:
abi: ERC20PoolFactory
address: "0xe6F4d9711121e5304b30aC2Aae57E3b085ad3c4d"
startBlock: 17622995
address: "0x01Da8a85A5B525D476cA2b51e44fe7087fFafaFF"
startBlock: 9289397
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand All @@ -72,13 +72,13 @@ dataSources:
- event: PoolCreated(address)
handler: handlePoolCreated
file: ./src/erc-20-pool-factory.ts
network: mainnet
network: goerli
- kind: ethereum
name: RewardsManager
source:
abi: RewardsManager
address: "0x0000000000000000000000000000000000000000"
startBlock: 17622995
address: "0x994dE190dd763Af3126FcC8EdC139275937d800b"
startBlock: 9289397
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down Expand Up @@ -107,13 +107,13 @@ dataSources:
- event: UpdateExchangeRates(indexed address,indexed address,uint256[],uint256)
handler: handleUpdateExchangeRates
file: ./src/rewards-manager.ts
network: mainnet
network: goerli
- kind: ethereum
name: ERC721PoolFactory
source:
abi: ERC721PoolFactory
address: "0xb8DA113516bfb986B7b8738a76C136D1c16c5609"
startBlock: 17622995
address: "0x37048D43A65748409B04f4051eEd9480BEf68c82"
startBlock: 9289397
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand All @@ -131,13 +131,13 @@ dataSources:
- event: PoolCreated(address)
handler: handlePoolCreated
file: ./src/erc-721-pool-factory.ts
network: mainnet
network: goerli
- kind: ethereum
name: GrantFund
source:
abi: GrantFund
address: "0x0000000000000000000000000000000000000000"
startBlock: 17622995
address: "0x881b4dFF6C72babA6f5eA60f34A61410c1EA1ec2"
startBlock: 9297080
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down Expand Up @@ -169,7 +169,7 @@ dataSources:
- event: VoteCast(indexed address,uint256,uint8,uint256,string)
handler: handleVoteCast
file: ./src/grant-fund.ts
network: mainnet
network: goerli
templates:
- kind: ethereum
name: ERC20Pool
Expand Down Expand Up @@ -273,4 +273,4 @@ templates:
- event: UpdateInterestRate(uint256,uint256)
handler: handleUpdateInterestRate
file: ./src/erc-20-pool.ts
network: mainnet
network: goerli
Loading