From c9da759d5a096eaef80733430949e4c643d0b33e Mon Sep 17 00:00:00 2001 From: Mike Hathaway Date: Tue, 19 Sep 2023 09:01:20 -0400 Subject: [PATCH] Refactoring (#70) --- src/mappings/base/base-pool.ts | 21 +- src/mappings/erc-20-pool.ts | 655 +++++++++++++++++---------------- src/mappings/erc-721-pool.ts | 18 +- 3 files changed, 351 insertions(+), 343 deletions(-) diff --git a/src/mappings/base/base-pool.ts b/src/mappings/base/base-pool.ts index 94cd2c0..a9194cb 100644 --- a/src/mappings/base/base-pool.ts +++ b/src/mappings/base/base-pool.ts @@ -1,5 +1,5 @@ import { Address, BigInt, Bytes, ethereum, log } from "@graphprotocol/graph-ts" -import { Account, AddQuoteToken, Bucket, BucketBankruptcy, Flashloan, Lend, LoanStamped, MoveQuoteToken, Pool, PositionLend, RemoveQuoteToken, ReserveAuctionKick, ReserveAuctionTake, Token, TransferLP, UpdateInterestRate } from "../../../generated/schema" +import { Account, AddQuoteToken, BondWithdrawn, Bucket, BucketBankruptcy, Flashloan, Lend, LoanStamped, MoveQuoteToken, Pool, PositionLend, RemoveQuoteToken, ReserveAuctionKick, ReserveAuctionTake, Token, TransferLP, UpdateInterestRate } from "../../../generated/schema" import { AddQuoteToken as AddQuoteTokenERC20Event, MoveQuoteToken as MoveQuoteTokenERC20Event, @@ -572,6 +572,25 @@ export function _handleRevokeLPTransferors(event: ethereum.Event, lender: Addres entity.save() } +/**********************************/ +/*** Liquidation Event Handlers ***/ +/**********************************/ + +export function _handleBondWithdrawn(event: ethereum.Event, kicker: Address, reciever: Address, amount: BigInt): void { + const entity = new BondWithdrawn( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + entity.kicker = kicker + entity.reciever = reciever + entity.amount = wadToDecimal(amount) + + entity.blockNumber = event.block.number + entity.blockTimestamp = event.block.timestamp + entity.transactionHash = event.transaction.hash + + entity.save() +} + /*******************************/ /*** Reserves Event Handlers ***/ /*******************************/ diff --git a/src/mappings/erc-20-pool.ts b/src/mappings/erc-20-pool.ts index b2efd64..00b490d 100644 --- a/src/mappings/erc-20-pool.ts +++ b/src/mappings/erc-20-pool.ts @@ -32,7 +32,6 @@ import { import { AddCollateral, AuctionSettle, - BondWithdrawn, BucketTake, BucketTakeLPAwarded, DrawDebt, @@ -56,7 +55,125 @@ import { getLiquidationAuctionId, getAuctionInfoERC20Pool, loadOrCreateLiquidati import { updatePool, addLiquidationToPool } from "../utils/pool/pool" import { lpbValueInQuote } from "../utils/pool/lend" import { incrementTokenTxCount } from "../utils/token-erc20" -import { _handleAddQuoteToken, _handleApproveLPTransferors, _handleBucketBankruptcy, _handleDecreaseLPAllowance, _handleFlashLoan, _handleIncreaseLPAllowance, _handleInterestRateEvent, _handleLoanStamped, _handleMoveQuoteToken, _handleRemoveQuoteToken, _handleReserveAuctionKick, _handleReserveAuctionTake, _handleRevokeLPAllowance, _handleRevokeLPTransferors, _handleTransferLP } from "./base/base-pool" +import { _handleAddQuoteToken, _handleApproveLPTransferors, _handleBondWithdrawn, _handleBucketBankruptcy, _handleDecreaseLPAllowance, _handleFlashLoan, _handleIncreaseLPAllowance, _handleInterestRateEvent, _handleLoanStamped, _handleMoveQuoteToken, _handleRemoveQuoteToken, _handleReserveAuctionKick, _handleReserveAuctionTake, _handleRevokeLPAllowance, _handleRevokeLPTransferors, _handleTransferLP } from "./base/base-pool" + + +/*******************************/ +/*** Borrower Event Handlers ***/ +/*******************************/ + +export function handleDrawDebt(event: DrawDebtEvent): void { + const drawDebt = new DrawDebt( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + drawDebt.borrower = event.params.borrower + drawDebt.amountBorrowed = wadToDecimal(event.params.amountBorrowed) + drawDebt.collateralPledged = wadToDecimal(event.params.collateralPledged) + drawDebt.lup = wadToDecimal(event.params.lup) + + drawDebt.blockNumber = event.block.number + drawDebt.blockTimestamp = event.block.timestamp + drawDebt.transactionHash = event.transaction.hash + + // update entities + const pool = Pool.load(addressToBytes(event.address)) + if (pool != null) { + // update pool state + pool.pledgedCollateral = pool.pledgedCollateral.plus(wadToDecimal(event.params.collateralPledged)) + updatePool(pool) + pool.txCount = pool.txCount.plus(ONE_BI) + + // update tx count for a pools tokens + incrementTokenTxCount(pool) + + // update account state + const accountId = addressToBytes(event.params.borrower) + const account = loadOrCreateAccount(accountId) + account.txCount = account.txCount.plus(ONE_BI) + + // update loan state + const loanId = getLoanId(pool.id, accountId) + const loan = loadOrCreateLoan(loanId, pool.id, drawDebt.borrower) + const borrowerInfo = getBorrowerInfo(addressToBytes(event.params.borrower), pool.id) + loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) + loan.t0debt = wadToDecimal(borrowerInfo.t0debt) + + // update account's list of pools and loans if necessary + updateAccountPools(account, pool) + updateAccountLoans(account, loan) + + // save entities to store + pool.save() + account.save() + loan.save() + + drawDebt.pool = pool.id + } + + drawDebt.save() +} + +export function handleRepayDebt(event: RepayDebtEvent): void { + const repayDebt = new RepayDebt( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + repayDebt.borrower = event.params.borrower + repayDebt.quoteRepaid = wadToDecimal(event.params.quoteRepaid) + repayDebt.collateralPulled = wadToDecimal(event.params.collateralPulled) + repayDebt.lup = wadToDecimal(event.params.lup) + + repayDebt.blockNumber = event.block.number + repayDebt.blockTimestamp = event.block.timestamp + repayDebt.transactionHash = event.transaction.hash + + // update entities + const pool = Pool.load(addressToBytes(event.address)) + if (pool != null) { + // update pool state + pool.pledgedCollateral = pool.pledgedCollateral.minus(wadToDecimal(event.params.collateralPulled)) + updatePool(pool) + pool.txCount = pool.txCount.plus(ONE_BI) + repayDebt.pool = pool.id + + // update tx count for a pools tokens + incrementTokenTxCount(pool) + + // update account state + const accountId = addressToBytes(event.params.borrower) + const account = loadOrCreateAccount(accountId) + account.txCount = account.txCount.plus(ONE_BI) + + // update loan state + const loanId = getLoanId(pool.id, accountId) + const loan = loadOrCreateLoan(loanId, pool.id, repayDebt.borrower) + const borrowerInfo = getBorrowerInfo(accountId, pool.id) + loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) + loan.t0debt = wadToDecimal(borrowerInfo.t0debt) + + // update account loans if necessary + updateAccountLoans(account, loan) + // remove loan from store if necessary + saveOrRemoveLoan(loan) + + // save entities to store + account.save() + pool.save() + } + + repayDebt.save() +} + +export function handleFlashloan(event: FlashloanEvent): void { + _handleFlashLoan(event, event.params.token, event.params.receiver, event.params.amount) +} + +export function handleLoanStamped(event: LoanStampedEvent): void { + _handleLoanStamped(event, event.params.borrower) +} + +/*****************************/ +/*** Lender Event Handlers ***/ +/*****************************/ export function handleAddCollateral(event: AddCollateralEvent): void { const addCollateral = new AddCollateral( @@ -126,251 +243,97 @@ export function handleAddQuoteToken(event: AddQuoteTokenEvent): void { _handleAddQuoteToken(event, null) } -// ERC20Pool only -// emitted in conjunction with Settle -export function handleAuctionSettle(event: AuctionSettleEvent): void { - const auctionSettle = new AuctionSettle( - event.transaction.hash.concatI32(event.logIndex.toI32()) - ) - auctionSettle.borrower = event.params.borrower - auctionSettle.collateral = wadToDecimal(event.params.collateral) - - auctionSettle.blockNumber = event.block.number - auctionSettle.blockTimestamp = event.block.timestamp - auctionSettle.transactionHash = event.transaction.hash - - // update entities - const pool = Pool.load(addressToBytes(event.address))! - // pool doesn't need to be updated here as it was already updated in the concurrent Settle event - - // update auction state - const loanId = getLoanId(pool.id, addressToBytes(event.params.borrower)) - const loan = Loan.load(loanId)! - const auctionId = loan.liquidationAuction! - const auction = LiquidationAuction.load(auctionId)! - auction.settle = auctionSettle.id - auction.settleTime = auctionSettle.blockTimestamp - auction.settled = true - auction.save() - - // update loan state - loan.t0debt = ZERO_BD - loan.collateralPledged = auctionSettle.collateral - loan.inLiquidation = false - - // remove loan from store if necessary - saveOrRemoveLoan(loan) - - // update auctionSettle pointers and save to store - auctionSettle.pool = pool.id - auctionSettle.loan = loan.id - auctionSettle.save() -} - -export function handleBondWithdrawn(event: BondWithdrawnEvent): void { - const entity = new BondWithdrawn( - event.transaction.hash.concatI32(event.logIndex.toI32()) - ) - entity.kicker = event.params.kicker - entity.reciever = event.params.reciever - entity.amount = wadToDecimal(event.params.amount) - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - export function handleBucketBankruptcy(event: BucketBankruptcyEvent): void { _handleBucketBankruptcy(event, event.params.index, event.params.lpForfeited) } -export function handleBucketTake(event: BucketTakeEvent): void { - 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() - bucketTake.amount = wadToDecimal(event.params.amount) - bucketTake.collateral = wadToDecimal(event.params.collateral) - bucketTake.auctionPrice = bucketTake.amount.div(bucketTake.collateral) - bucketTake.bondChange = wadToDecimal(event.params.bondChange) - bucketTake.isReward = event.params.isReward - - bucketTake.blockNumber = event.block.number - bucketTake.blockTimestamp = event.block.timestamp - bucketTake.transactionHash = event.transaction.hash - - // update entities - const pool = Pool.load(addressToBytes(event.address))! - - // update pool state - updatePool(pool) - pool.txCount = pool.txCount.plus(ONE_BI) - incrementTokenTxCount(pool) - - // update taker account state - const account = loadOrCreateAccount(bucketTake.taker) - account.txCount = account.txCount.plus(ONE_BI) - updateAccountTakes(account, bucketTake.id) - updateAccountPools(account, pool) - - // update loan state - const loanId = getLoanId(pool.id, addressToBytes(event.params.borrower)) - const loan = loadOrCreateLoan(loanId, pool.id, addressToBytes(event.params.borrower)) - const borrowerInfo = getBorrowerInfo(addressToBytes(event.params.borrower), pool.id) - loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) - loan.t0debt = wadToDecimal(borrowerInfo.t0debt) - - // retrieve auction information on the take's auction - const auctionInfo = getAuctionInfoERC20Pool(bucketTake.borrower, pool) - const auctionStatus = getAuctionStatus(pool, event.params.borrower) - - // update liquidation auction state - const auctionId = loan.liquidationAuction! - const auction = LiquidationAuction.load(auctionId)! - updateLiquidationAuction(auction, auctionInfo, auctionStatus, bucketTake.auctionPrice) - auction.bucketTakes = auction.bucketTakes.concat([bucketTake.id]) - - // update kick and pool for the change in bond as a result of the take - const kick = Kick.load(auction.kick)! - if (bucketTake.isReward) { - // reward kicker if take is below neutral price - pool.totalBondEscrowed = pool.totalBondEscrowed.plus(wadToDecimal(event.params.bondChange)) - kick.locked = kick.locked.plus(wadToDecimal(event.params.bondChange)) - } else { - // penalize kicker if take is above neutral price - pool.totalBondEscrowed = pool.totalBondEscrowed.minus(wadToDecimal(event.params.bondChange)) - 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, bucket.bucketIndex, bucketTakeLpAwarded.kicker) - kickerLend.depositTime = bucketTake.blockTimestamp - kickerLend.lpb = kickerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedKicker) - kickerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, kickerLend.lpb) - updateBucketLends(bucket, kickerLend) - - // 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, bucket.bucketIndex, bucketTakeLpAwarded.taker) - takerLend.depositTime = bucketTake.blockTimestamp - takerLend.lpb = takerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker) - takerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, takerLend.lpb) - updateBucketLends(bucket, takerLend) - - // update bucketTake pointers - bucketTake.liquidationAuction = auction.id - bucketTake.loan = loanId - bucketTake.pool = pool.id - - // save entities to the store - account.save() - auction.save() - bucket.save() - bucketTake.save() - loan.save() - pool.save() - kick.save() - kickerAccount.save() - kickerLend.save() - takerLend.save() -} - -export function handleBucketTakeLPAwarded( - event: BucketTakeLPAwardedEvent -): void { - 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.transactionHash = event.transaction.hash - 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 handleMoveQuoteToken(event: MoveQuoteTokenEvent): void { + // TODO: get compiler to ignore this line's INFO output + event = changetype(event)! + _handleMoveQuoteToken(event, null) } -export function handleDrawDebt(event: DrawDebtEvent): void { - const drawDebt = new DrawDebt( +export function handleRemoveCollateral(event: RemoveCollateralEvent): void { + const removeCollateral = new RemoveCollateral( event.transaction.hash.concatI32(event.logIndex.toI32()) ) - drawDebt.borrower = event.params.borrower - drawDebt.amountBorrowed = wadToDecimal(event.params.amountBorrowed) - drawDebt.collateralPledged = wadToDecimal(event.params.collateralPledged) - drawDebt.lup = wadToDecimal(event.params.lup) + removeCollateral.claimer = event.params.claimer + removeCollateral.index = event.params.index.toU32() + removeCollateral.amount = wadToDecimal(event.params.amount) + removeCollateral.lpRedeemed = wadToDecimal(event.params.lpRedeemed) - drawDebt.blockNumber = event.block.number - drawDebt.blockTimestamp = event.block.timestamp - drawDebt.transactionHash = event.transaction.hash + removeCollateral.blockNumber = event.block.number + removeCollateral.blockTimestamp = event.block.timestamp + removeCollateral.transactionHash = event.transaction.hash // update entities const pool = Pool.load(addressToBytes(event.address)) if (pool != null) { // update pool state - pool.pledgedCollateral = pool.pledgedCollateral.plus(wadToDecimal(event.params.collateralPledged)) updatePool(pool) pool.txCount = pool.txCount.plus(ONE_BI) // update tx count for a pools tokens incrementTokenTxCount(pool) + // update bucket state + const bucketId = getBucketId(pool.id, event.params.index.toU32()) + const bucket = loadOrCreateBucket(pool.id, bucketId, event.params.index.toU32()) + 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 account state - const accountId = addressToBytes(event.params.borrower) + const accountId = removeCollateral.claimer const account = loadOrCreateAccount(accountId) account.txCount = account.txCount.plus(ONE_BI) - // update loan state - const loanId = getLoanId(pool.id, accountId) - const loan = loadOrCreateLoan(loanId, pool.id, drawDebt.borrower) - const borrowerInfo = getBorrowerInfo(addressToBytes(event.params.borrower), pool.id) - loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) - loan.t0debt = wadToDecimal(borrowerInfo.t0debt) + // update lend state + const lendId = getLendId(bucketId, accountId) + const lend = loadOrCreateLend(bucketId, lendId, pool.id, bucket.bucketIndex, removeCollateral.claimer) + if (removeCollateral.lpRedeemed.le(lend.lpb)) { + lend.lpb = lend.lpb.minus(removeCollateral.lpRedeemed) + } else { + log.warning('handleRemoveCollateral: claimer {} redeemed more LP ({}) than Lend entity was aware of ({}); resetting to 0', + [removeCollateral.claimer.toHexString(), removeCollateral.lpRedeemed.toString(), lend.lpb.toString()]) + lend.lpb = ZERO_BD + } + lend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, lend.lpb) - // update account's list of pools and loans if necessary + // update bucket and account's list of pools and lends if necessary + updateBucketLends(bucket, lend) updateAccountPools(account, pool) - updateAccountLoans(account, loan) + updateAccountLends(account, lend) + + // remove lend from store if necessary + saveOrRemoveLend(lend) // save entities to store - pool.save() account.save() - loan.save() + bucket.save() + pool.save() - drawDebt.pool = pool.id + removeCollateral.bucket = bucket.id + removeCollateral.pool = pool.id } - drawDebt.save() + removeCollateral.save() } -export function handleFlashloan(event: FlashloanEvent): void { - _handleFlashLoan(event, event.params.token, event.params.receiver, event.params.amount) +export function handleRemoveQuoteToken(event: RemoveQuoteTokenEvent): void { + // TODO: get compiler to ignore this line's INFO output + event = changetype(event)! + _handleRemoveQuoteToken(event, null) +} + +/**********************************/ +/*** Liquidation Event Handlers ***/ +/**********************************/ + +export function handleBondWithdrawn(event: BondWithdrawnEvent): void { + _handleBondWithdrawn(event, event.params.kicker, event.params.reciever, event.params.amount) } export function handleKick(event: KickEvent): void { @@ -439,139 +402,136 @@ export function handleKick(event: KickEvent): void { kick.save() } -export function handleLoanStamped(event: LoanStampedEvent): void { - _handleLoanStamped(event, event.params.borrower) -} - -export function handleMoveQuoteToken(event: MoveQuoteTokenEvent): void { - // TODO: get compiler to ignore this line's INFO output - event = changetype(event)! - _handleMoveQuoteToken(event, null) -} - -export function handleRemoveCollateral(event: RemoveCollateralEvent): void { - const removeCollateral = new RemoveCollateral( - event.transaction.hash.concatI32(event.logIndex.toI32()) - ) - removeCollateral.claimer = event.params.claimer - removeCollateral.index = event.params.index.toU32() - removeCollateral.amount = wadToDecimal(event.params.amount) - removeCollateral.lpRedeemed = wadToDecimal(event.params.lpRedeemed) +export function handleBucketTake(event: BucketTakeEvent): void { + 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() + bucketTake.amount = wadToDecimal(event.params.amount) + bucketTake.collateral = wadToDecimal(event.params.collateral) + bucketTake.auctionPrice = bucketTake.amount.div(bucketTake.collateral) + bucketTake.bondChange = wadToDecimal(event.params.bondChange) + bucketTake.isReward = event.params.isReward - removeCollateral.blockNumber = event.block.number - removeCollateral.blockTimestamp = event.block.timestamp - removeCollateral.transactionHash = event.transaction.hash + bucketTake.blockNumber = event.block.number + bucketTake.blockTimestamp = event.block.timestamp + bucketTake.transactionHash = event.transaction.hash // update entities - const pool = Pool.load(addressToBytes(event.address)) - if (pool != null) { - // update pool state - updatePool(pool) - pool.txCount = pool.txCount.plus(ONE_BI) - - // update tx count for a pools tokens - incrementTokenTxCount(pool) - - // update bucket state - const bucketId = getBucketId(pool.id, event.params.index.toU32()) - const bucket = loadOrCreateBucket(pool.id, bucketId, event.params.index.toU32()) - 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) + const pool = Pool.load(addressToBytes(event.address))! - // update account state - const accountId = removeCollateral.claimer - const account = loadOrCreateAccount(accountId) - account.txCount = account.txCount.plus(ONE_BI) + // update pool state + updatePool(pool) + pool.txCount = pool.txCount.plus(ONE_BI) + incrementTokenTxCount(pool) - // update lend state - const lendId = getLendId(bucketId, accountId) - const lend = loadOrCreateLend(bucketId, lendId, pool.id, bucket.bucketIndex, removeCollateral.claimer) - if (removeCollateral.lpRedeemed.le(lend.lpb)) { - lend.lpb = lend.lpb.minus(removeCollateral.lpRedeemed) - } else { - log.warning('handleRemoveCollateral: claimer {} redeemed more LP ({}) than Lend entity was aware of ({}); resetting to 0', - [removeCollateral.claimer.toHexString(), removeCollateral.lpRedeemed.toString(), lend.lpb.toString()]) - lend.lpb = ZERO_BD - } - lend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, lend.lpb) + // update taker account state + const account = loadOrCreateAccount(bucketTake.taker) + account.txCount = account.txCount.plus(ONE_BI) + updateAccountTakes(account, bucketTake.id) + updateAccountPools(account, pool) - // update bucket and account's list of pools and lends if necessary - updateBucketLends(bucket, lend) - updateAccountPools(account, pool) - updateAccountLends(account, lend) + // update loan state + const loanId = getLoanId(pool.id, addressToBytes(event.params.borrower)) + const loan = loadOrCreateLoan(loanId, pool.id, addressToBytes(event.params.borrower)) + const borrowerInfo = getBorrowerInfo(addressToBytes(event.params.borrower), pool.id) + loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) + loan.t0debt = wadToDecimal(borrowerInfo.t0debt) - // remove lend from store if necessary - saveOrRemoveLend(lend) + // retrieve auction information on the take's auction + const auctionInfo = getAuctionInfoERC20Pool(bucketTake.borrower, pool) + const auctionStatus = getAuctionStatus(pool, event.params.borrower) - // save entities to store - account.save() - bucket.save() - pool.save() + // update liquidation auction state + const auctionId = loan.liquidationAuction! + const auction = LiquidationAuction.load(auctionId)! + updateLiquidationAuction(auction, auctionInfo, auctionStatus, bucketTake.auctionPrice) + auction.bucketTakes = auction.bucketTakes.concat([bucketTake.id]) - removeCollateral.bucket = bucket.id - removeCollateral.pool = pool.id + // update kick and pool for the change in bond as a result of the take + const kick = Kick.load(auction.kick)! + if (bucketTake.isReward) { + // reward kicker if take is below neutral price + pool.totalBondEscrowed = pool.totalBondEscrowed.plus(wadToDecimal(event.params.bondChange)) + kick.locked = kick.locked.plus(wadToDecimal(event.params.bondChange)) + } else { + // penalize kicker if take is above neutral price + pool.totalBondEscrowed = pool.totalBondEscrowed.minus(wadToDecimal(event.params.bondChange)) + kick.locked = kick.locked.minus(wadToDecimal(event.params.bondChange)) } - removeCollateral.save() -} - -export function handleRemoveQuoteToken(event: RemoveQuoteTokenEvent): void { - // TODO: get compiler to ignore this line's INFO output - event = changetype(event)! - _handleRemoveQuoteToken(event, null) -} - -export function handleRepayDebt(event: RepayDebtEvent): void { - const repayDebt = new RepayDebt( - event.transaction.hash.concatI32(event.logIndex.toI32()) - ) - repayDebt.borrower = event.params.borrower - repayDebt.quoteRepaid = wadToDecimal(event.params.quoteRepaid) - repayDebt.collateralPulled = wadToDecimal(event.params.collateralPulled) - repayDebt.lup = wadToDecimal(event.params.lup) + // 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) - repayDebt.blockNumber = event.block.number - repayDebt.blockTimestamp = event.block.timestamp - repayDebt.transactionHash = event.transaction.hash + // 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, bucket.bucketIndex, bucketTakeLpAwarded.kicker) + kickerLend.depositTime = bucketTake.blockTimestamp + kickerLend.lpb = kickerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedKicker) + kickerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, kickerLend.lpb) + updateBucketLends(bucket, kickerLend) - // update entities - const pool = Pool.load(addressToBytes(event.address)) - if (pool != null) { - // update pool state - pool.pledgedCollateral = pool.pledgedCollateral.minus(wadToDecimal(event.params.collateralPulled)) - updatePool(pool) - pool.txCount = pool.txCount.plus(ONE_BI) - repayDebt.pool = pool.id + // update kicker account state if they weren't a lender already + const kickerAccountId = bucketTakeLpAwarded.kicker + const kickerAccount = loadOrCreateAccount(kickerAccountId) + updateAccountLends(kickerAccount, kickerLend) - // update tx count for a pools tokens - incrementTokenTxCount(pool) + // update lend state for taker + const takerLendId = getLendId(bucketId, bucketTakeLpAwarded.taker) + const takerLend = loadOrCreateLend(bucketId, takerLendId, pool.id, bucket.bucketIndex, bucketTakeLpAwarded.taker) + takerLend.depositTime = bucketTake.blockTimestamp + takerLend.lpb = takerLend.lpb.plus(bucketTakeLpAwarded.lpAwardedTaker) + takerLend.lpbValueInQuote = lpbValueInQuote(pool.id, bucket.bucketIndex, takerLend.lpb) + updateBucketLends(bucket, takerLend) - // update account state - const accountId = addressToBytes(event.params.borrower) - const account = loadOrCreateAccount(accountId) - account.txCount = account.txCount.plus(ONE_BI) + // update bucketTake pointers + bucketTake.liquidationAuction = auction.id + bucketTake.loan = loanId + bucketTake.pool = pool.id - // update loan state - const loanId = getLoanId(pool.id, accountId) - const loan = loadOrCreateLoan(loanId, pool.id, repayDebt.borrower) - const borrowerInfo = getBorrowerInfo(accountId, pool.id) - loan.collateralPledged = wadToDecimal(borrowerInfo.collateral) - loan.t0debt = wadToDecimal(borrowerInfo.t0debt) + // save entities to the store + account.save() + auction.save() + bucket.save() + bucketTake.save() + loan.save() + pool.save() + kick.save() + kickerAccount.save() + kickerLend.save() + takerLend.save() +} - // update account loans if necessary - updateAccountLoans(account, loan) - // remove loan from store if necessary - saveOrRemoveLoan(loan) +export function handleBucketTakeLPAwarded( + event: BucketTakeLPAwardedEvent +): void { + 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) - // save entities to store - account.save() - pool.save() - } + bucketTakeLpAwarded.blockNumber = event.block.number + bucketTakeLpAwarded.blockTimestamp = event.block.timestamp + bucketTakeLpAwarded.transactionHash = event.transaction.hash + bucketTakeLpAwarded.save() - repayDebt.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 handleTake(event: TakeEvent): void { @@ -692,6 +652,47 @@ export function handleSettle(event: SettleEvent): void { settle.save() } +// ERC20Pool only +// emitted in conjunction with Settle +export function handleAuctionSettle(event: AuctionSettleEvent): void { + const auctionSettle = new AuctionSettle( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + auctionSettle.borrower = event.params.borrower + auctionSettle.collateral = wadToDecimal(event.params.collateral) + + auctionSettle.blockNumber = event.block.number + auctionSettle.blockTimestamp = event.block.timestamp + auctionSettle.transactionHash = event.transaction.hash + + // update entities + const pool = Pool.load(addressToBytes(event.address))! + // pool doesn't need to be updated here as it was already updated in the concurrent Settle event + + // update auction state + const loanId = getLoanId(pool.id, addressToBytes(event.params.borrower)) + const loan = Loan.load(loanId)! + const auctionId = loan.liquidationAuction! + const auction = LiquidationAuction.load(auctionId)! + auction.settle = auctionSettle.id + auction.settleTime = auctionSettle.blockTimestamp + auction.settled = true + auction.save() + + // update loan state + loan.t0debt = ZERO_BD + loan.collateralPledged = auctionSettle.collateral + loan.inLiquidation = false + + // remove loan from store if necessary + saveOrRemoveLoan(loan) + + // update auctionSettle pointers and save to store + auctionSettle.pool = pool.id + auctionSettle.loan = loan.id + auctionSettle.save() +} + /*************************************/ /*** LPB Management Event Handlers ***/ /*************************************/ diff --git a/src/mappings/erc-721-pool.ts b/src/mappings/erc-721-pool.ts index 2fce19e..8d4a332 100644 --- a/src/mappings/erc-721-pool.ts +++ b/src/mappings/erc-721-pool.ts @@ -34,7 +34,6 @@ import { AuctionNFTSettle, BucketTake, BucketTakeLPAwarded, - BondWithdrawn, DrawDebtNFT, LiquidationAuction, Loan, @@ -57,7 +56,8 @@ import { getBorrowerInfoERC721Pool, getLoanId, loadOrCreateLoan, saveOrRemoveLoa import { getLiquidationAuctionId, loadOrCreateLiquidationAuction, updateLiquidationAuction, getAuctionStatus, loadOrCreateBucketTake, getAuctionInfoERC721Pool } from "../utils/pool/liquidation" import { updatePool, addLiquidationToPool, getLenderInfoERC721Pool } from "../utils/pool/pool" import { lpbValueInQuote } from "../utils/pool/lend" -import { _handleAddQuoteToken, _handleApproveLPTransferors, _handleBucketBankruptcy, _handleDecreaseLPAllowance, _handleFlashLoan, _handleIncreaseLPAllowance, _handleInterestRateEvent, _handleLoanStamped, _handleMoveQuoteToken, _handleRemoveQuoteToken, _handleReserveAuctionKick, _handleReserveAuctionTake, _handleRevokeLPAllowance, _handleRevokeLPTransferors, _handleTransferLP } from "./base/base-pool" +import { _handleAddQuoteToken, _handleApproveLPTransferors, _handleBondWithdrawn, _handleBucketBankruptcy, _handleDecreaseLPAllowance, _handleFlashLoan, _handleIncreaseLPAllowance, _handleInterestRateEvent, _handleLoanStamped, _handleMoveQuoteToken, _handleRemoveQuoteToken, _handleReserveAuctionKick, _handleReserveAuctionTake, _handleRevokeLPAllowance, _handleRevokeLPTransferors, _handleTransferLP } from "./base/base-pool" + /*******************************/ /*** Borrower Event Handlers ***/ @@ -419,20 +419,8 @@ export function handleMergeOrRemoveCollateralNFT( /*** Liquidation Event Handlers ***/ /**********************************/ -// identical to ERC20Pool export function handleBondWithdrawn(event: BondWithdrawnEvent): void { - const entity = new BondWithdrawn( - event.transaction.hash.concatI32(event.logIndex.toI32()) - ) - entity.kicker = event.params.kicker - entity.reciever = event.params.reciever - entity.amount = wadToDecimal(event.params.amount) - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() + _handleBondWithdrawn(event, event.params.kicker, event.params.reciever, event.params.amount) } // emitted concurrently with `Settle`