From 3006864d7fe2f518205e125cec52af419effcea5 Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 6 Aug 2023 22:42:27 -0400 Subject: [PATCH] track tokenIds in bucket; test DrawDebtNFT --- schema.graphql | 6 +- src/erc-721-pool.ts | 24 +++--- src/utils/pool/bucket.ts | 1 + tests/erc-721-pool.test.ts | 131 ++++++++++++++++++++++++++++-- tests/utils/erc-721-pool-utils.ts | 4 + 5 files changed, 147 insertions(+), 19 deletions(-) diff --git a/schema.graphql b/schema.graphql index 39fe844..c7c8dc8 100644 --- a/schema.graphql +++ b/schema.graphql @@ -149,6 +149,8 @@ type Bucket @entity { pool: Pool! # total collateral available in the bucket collateral: BigDecimal! + # tokenIds added to the bucket + tokenIds: [BigInt!]! # total quote tokens deposited in the bucket, inclusive of interest deposit: BigDecimal! # total LP for all lenders in the bucket @@ -677,9 +679,9 @@ type DrawDebtNFT @entity(immutable: true) { id: Bytes! pool: Pool! # Pool from which quote was withdrawn borrower: Bytes! # address - amountBorrowed: BigInt! # uint256 + amountBorrowed: BigDecimal! # uint256 tokenIdsPledged: [BigInt!]! # uint256[] - lup: BigInt! # uint256 + lup: BigDecimal! # uint256 blockNumber: BigInt! blockTimestamp: BigInt! transactionHash: Bytes! diff --git a/src/erc-721-pool.ts b/src/erc-721-pool.ts index 1dbebc5..2b9ceb2 100644 --- a/src/erc-721-pool.ts +++ b/src/erc-721-pool.ts @@ -31,7 +31,6 @@ import { getLiquidationAuctionId, getAuctionInfoERC20Pool, loadOrCreateLiquidati import { getBurnInfo, updatePool, addLiquidationToPool, addReserveAuctionToPool, getLenderInfo, getRatesAndFees, calculateLendRate } from "./utils/pool/pool" import { lpbValueInQuote } from "./utils/common" -// TODO: track tokenIds in the bucket entity? export function handleAddCollateralNFT(event: AddCollateralNFTEvent): void { const addCollateralNFT = new AddCollateralNFT( event.transaction.hash.concatI32(event.logIndex.toI32()) @@ -60,6 +59,8 @@ export function handleAddCollateralNFT(event: AddCollateralNFTEvent): void { bucket.deposit = wadToDecimal(bucketInfo.quoteTokens) bucket.lpb = wadToDecimal(bucketInfo.lpb) bucket.exchangeRate = wadToDecimal(bucketInfo.exchangeRate) + bucket.tokenIds = bucket.tokenIds.concat(event.params.tokenIds) + // TODO: should these tokenIds be added to the pool entity here as well? // update account state const accountId = addressToBytes(event.params.actor) @@ -82,7 +83,6 @@ export function handleAddCollateralNFT(event: AddCollateralNFTEvent): void { lend.save() pool.save() - // BELOW LOGIC IS CUSTOM TO ERC721 POOLS // update tx count for a pools tokens incrementTokenTxCount(pool) @@ -155,9 +155,9 @@ export function handleDrawDebtNFT(event: DrawDebtNFTEvent): void { event.transaction.hash.concatI32(event.logIndex.toI32()) ) drawDebtNFT.borrower = event.params.borrower - drawDebtNFT.amountBorrowed = event.params.amountBorrowed + drawDebtNFT.amountBorrowed = wadToDecimal(event.params.amountBorrowed) + drawDebtNFT.lup = wadToDecimal(event.params.lup) drawDebtNFT.tokenIdsPledged = event.params.tokenIdsPledged - drawDebtNFT.lup = event.params.lup drawDebtNFT.blockNumber = event.block.number drawDebtNFT.blockTimestamp = event.block.timestamp @@ -215,18 +215,18 @@ export function handleDrawDebtNFT(event: DrawDebtNFTEvent): void { export function handleMergeOrRemoveCollateralNFT( event: MergeOrRemoveCollateralNFTEvent ): void { - let entity = new MergeOrRemoveCollateralNFT( + const mergeOrRemove = new MergeOrRemoveCollateralNFT( event.transaction.hash.concatI32(event.logIndex.toI32()) ) - entity.actor = event.params.actor - entity.collateralMerged = event.params.collateralMerged - entity.toIndexLps = event.params.toIndexLps + mergeOrRemove.actor = event.params.actor + mergeOrRemove.collateralMerged = event.params.collateralMerged + mergeOrRemove.toIndexLps = event.params.toIndexLps - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash + mergeOrRemove.blockNumber = event.block.number + mergeOrRemove.blockTimestamp = event.block.timestamp + mergeOrRemove.transactionHash = event.transaction.hash - entity.save() + mergeOrRemove.save() } // export function handleAuctionNFTSettle(event: AuctionNFTSettleEvent): void { diff --git a/src/utils/pool/bucket.ts b/src/utils/pool/bucket.ts index 87c2af0..7d17ba4 100644 --- a/src/utils/pool/bucket.ts +++ b/src/utils/pool/bucket.ts @@ -61,6 +61,7 @@ export function loadOrCreateBucket(poolId: Bytes, bucketId: Bytes, index: u32): bucket.deposit = ZERO_BD bucket.exchangeRate = ONE_BD bucket.lpb = ZERO_BD + bucket.tokenIds = [] } return bucket } diff --git a/tests/erc-721-pool.test.ts b/tests/erc-721-pool.test.ts index e20a9b7..ed27553 100644 --- a/tests/erc-721-pool.test.ts +++ b/tests/erc-721-pool.test.ts @@ -10,15 +10,18 @@ import { logStore, } from "matchstick-as/assembly/index" import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts" -import { AddCollateralNFT } from "../generated/schema" +import { Account, AddCollateralNFT, Loan } from "../generated/schema" import { AddCollateralNFT as AddCollateralNFTEvent } from "../generated/templates/ERC721Pool/ERC721Pool" -import { handleAddCollateralNFT, handleAddQuoteToken } from "../src/erc-721-pool" -import { createAddCollateralNFTEvent, createAddQuoteTokenEvent } from "./utils/erc-721-pool-utils" +import { handleAddCollateralNFT, handleAddQuoteToken, handleDrawDebtNFT } from "../src/erc-721-pool" +import { createAddCollateralNFTEvent, createAddQuoteTokenEvent, createDrawDebtNFTEvent } from "./utils/erc-721-pool-utils" import { FIVE_PERCENT_BI, MAX_PRICE, MAX_PRICE_BI, MAX_PRICE_INDEX, ONE_BI, ONE_PERCENT_BI, ONE_WAD_BI, ZERO_ADDRESS, ZERO_BD, ZERO_BI } from "../src/utils/constants" -import { create721Pool, createPool, mockGetBucketInfo, mockGetLPBValueInQuote, mockGetRatesAndFees, mockPoolInfoUtilsPoolUpdateCalls, mockTokenBalance } from "./utils/common" +import { create721Pool, createPool, mockGetBorrowerInfo, mockGetBucketInfo, mockGetDebtInfo, mockGetLPBValueInQuote, mockGetRatesAndFees, mockPoolInfoUtilsPoolUpdateCalls, mockTokenBalance } from "./utils/common" import { BucketInfo } from "../src/utils/pool/bucket" -import { wadToDecimal } from "../src/utils/convert" +import { addressToBytes, wadToDecimal } from "../src/utils/convert" +import { DebtInfo } from "../src/utils/pool/pool" +import { BorrowerInfo, getLoanId } from "../src/utils/pool/loan" +import { wdiv } from "../src/utils/math" // Tests structure (matchstick-as >=0.5.0) // https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 @@ -239,4 +242,122 @@ describe("Describe entity assertions", () => { ) }) + test("DrawDebtNFT", () => { + // check entity is unavailable prior to storage + assert.entityCount("DrawDebtNFT", 0) + + // mock parameters + const poolAddress = Address.fromString("0x0000000000000000000000000000000000000001") + const borrower = Address.fromString("0x0000000000000000000000000000000000000003") + const amountBorrowed = BigInt.fromString("567529276179422528643") // 567.529276179422528643 * 1e18 + const tokenIdsPledged = [BigInt.fromI32(234), BigInt.fromI32(345)] + const amountPledged = BigInt.fromString("2000000000000000000") + const lup = BigInt.fromString("9529276179422528643") // 9.529276179422528643 * 1e18 + + // mock required contract calls + const expectedPoolDebtInfo = new DebtInfo(amountBorrowed, ZERO_BI, ZERO_BI, ZERO_BI) + mockGetDebtInfo(poolAddress, expectedPoolDebtInfo) + + const inflator = BigInt.fromString("1002804000000000000") + const expectedBorrowerInfo = new BorrowerInfo( + wdiv(amountBorrowed, inflator), + amountPledged, + BigInt.fromString("8766934085068726351")) + mockGetBorrowerInfo(poolAddress, borrower, expectedBorrowerInfo) + + const newDrawDebtEvent = createDrawDebtNFTEvent( + poolAddress, + borrower, + amountBorrowed, + tokenIdsPledged, + lup + ) + handleDrawDebtNFT(newDrawDebtEvent) + + // check DrawDebtNFT entity + assert.entityCount("DrawDebtNFT", 1) + assert.fieldEquals( + "DrawDebtNFT", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "borrower", + "0x0000000000000000000000000000000000000003" + ) + assert.fieldEquals( + "DrawDebtNFT", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "lup", + `${wadToDecimal(lup)}` + ) + assert.fieldEquals( + "DrawDebtNFT", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "tokenIdsPledged", + "[234, 345]" + ) + assert.fieldEquals( + "DrawDebtNFT", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "amountBorrowed", + `${wadToDecimal(amountBorrowed)}` + ) + + // check Account attributes updated + const accountId = addressToBytes(borrower) + const loadedAccount = Account.load(accountId)! + assert.bytesEquals(addressToBytes(poolAddress), loadedAccount.pools[0]) + assert.fieldEquals( + "Account", + `${accountId.toHexString()}`, + "txCount", + `${ONE_BI}` + ) + + // check Loan entity + const loanId = getLoanId(addressToBytes(poolAddress), accountId) + const loadedLoan = Loan.load(loanId)! + assert.bytesEquals(addressToBytes(poolAddress), loadedLoan.pool) + assert.fieldEquals( + "Loan", + `${loanId.toHexString()}`, + "collateralPledged", + `${wadToDecimal(amountPledged)}` + ) + assert.fieldEquals( + "Loan", + `${loanId.toHexString()}`, + "tokenIdsPledged", + "[234, 345]" + ) + assert.fieldEquals( + "Loan", + `${loanId.toHexString()}`, + "t0debt", + `${wadToDecimal(wdiv(amountBorrowed, inflator))}` + ) + + // check pool attributes updated + // not dividing by inflator because the PoolInfoUtils mock sets inflator to 1 + assert.fieldEquals( + "Pool", + `${addressToBytes(poolAddress).toHexString()}`, + "t0debt", + `${wadToDecimal(amountBorrowed)}` + ) + assert.fieldEquals( + "Pool", + `${addressToBytes(poolAddress).toHexString()}`, + "lup", + "9.529276179422528643" + ) + assert.fieldEquals( + "Pool", + `${addressToBytes(poolAddress).toHexString()}`, + "txCount", + `${ONE_BI}` + ) + + }) + + // TODO: test token and pool tx count incrementing in more thorough own unit test + }) diff --git a/tests/utils/erc-721-pool-utils.ts b/tests/utils/erc-721-pool-utils.ts index d4cb290..70ea1f1 100644 --- a/tests/utils/erc-721-pool-utils.ts +++ b/tests/utils/erc-721-pool-utils.ts @@ -84,6 +84,7 @@ export function createAddQuoteTokenEvent( } export function createDrawDebtNFTEvent( + pool: Address, borrower: Address, amountBorrowed: BigInt, tokenIdsPledged: Array, @@ -112,6 +113,9 @@ export function createDrawDebtNFTEvent( new ethereum.EventParam("lup", ethereum.Value.fromUnsignedBigInt(lup)) ) + // update transaction target to the expected pool address + drawDebtNftEvent.address = pool + return drawDebtNftEvent }