From c456b2353fa0f8f3c42dd9514e0400c020011738 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:25:15 -0300 Subject: [PATCH 1/8] fix: use method for comparisons --- subgraphs/isolated-pools/src/mappings/vToken.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/subgraphs/isolated-pools/src/mappings/vToken.ts b/subgraphs/isolated-pools/src/mappings/vToken.ts index 468f5949..27a34c64 100644 --- a/subgraphs/isolated-pools/src/mappings/vToken.ts +++ b/subgraphs/isolated-pools/src/mappings/vToken.ts @@ -29,10 +29,7 @@ import { createTransferTransaction, } from '../operations/create'; import { getMarket } from '../operations/get'; -import { - getOrCreateAccount, - getOrCreateAccountVToken, -} from '../operations/getOrCreate'; +import { getOrCreateAccount, getOrCreateAccountVToken } from '../operations/getOrCreate'; import { recordLiquidatorAsSupplier } from '../operations/recordLiquidatorAsSupplier'; import { updateAccountVTokenAccrualBlockNumber, @@ -68,7 +65,7 @@ export function handleMint(event: Mint): void { event.block.number, suppliedTotal, ); - if (suppliedTotal == event.params.mintTokens) { + if (suppliedTotal.equals(event.params.mintTokens)) { // and if they are the same, it means it's a new supplier market.supplierCount = market.supplierCount.plus(oneBigInt); market.save(); @@ -99,7 +96,7 @@ export function handleRedeem(event: Redeem): void { event.block.number, currentBalance, ); - if (currentBalance == zeroBigInt32) { + if (currentBalance.equals(zeroBigInt32)) { // if the current balance is 0 then the user has withdrawn all their assets from this market market.supplierCount = market.supplierCount.minus(oneBigInt); market.save(); @@ -130,7 +127,7 @@ export function handleBorrow(event: Borrow): void { createBorrowTransaction(event); - if (event.params.accountBorrows == event.params.borrowAmount) { + if (event.params.accountBorrows.equals(event.params.borrowAmount)) { // if both the accountBorrows and the borrowAmount are the same, it means the account is a new borrower market.borrowerCount = market.borrowerCount.plus(oneBigInt); market.save(); @@ -166,7 +163,7 @@ export function handleRepayBorrow(event: RepayBorrow): void { createRepayBorrowTransaction(event); - if (event.params.accountBorrows == zeroBigInt32) { + if (event.params.accountBorrows.equals(zeroBigInt32)) { market.borrowerCount = market.borrowerCount.minus(oneBigInt); market.save(); } From 3475868e3aad85608e94ce172035a3b10b3f57a0 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:26:45 -0300 Subject: [PATCH 2/8] refactor: schema matches core pool subgraph --- subgraphs/isolated-pools/schema.graphql | 13 ++++--- subgraphs/isolated-pools/src/mappings/pool.ts | 4 +-- .../isolated-pools/src/mappings/vToken.ts | 18 +++++----- .../src/operations/getOrCreate.ts | 6 ++-- .../operations/recordLiquidatorAsSupplier.ts | 4 +-- .../isolated-pools/src/operations/update.ts | 12 +++---- .../isolated-pools/tests/VToken/index.test.ts | 34 +++++++------------ .../queries/accountFromMarket.graphql | 6 ++-- .../queries/accountPositions.graphql | 10 +++--- .../queries/accountVTokenByAccount.graphql | 6 ++-- .../accountVTokenByAccountAndMarket.graphql | 21 +++++++++--- .../queries/accountVTokens.graphql | 6 ++-- 12 files changed, 70 insertions(+), 70 deletions(-) diff --git a/subgraphs/isolated-pools/schema.graphql b/subgraphs/isolated-pools/schema.graphql index fa06175c..30c586ec 100644 --- a/subgraphs/isolated-pools/schema.graphql +++ b/subgraphs/isolated-pools/schema.graphql @@ -132,7 +132,7 @@ Account is an BNB address, with a list of all vToken markets the account has participated in, along with liquidation information. """ type Account @entity { - "User BNB address" + "User address" id: Bytes! "Pools the user is participating on" pools: [AccountPool!]! @derivedFrom(field: "account") @@ -172,17 +172,16 @@ type AccountVToken @entity { badDebt: [AccountVTokenBadDebt!]! @derivedFrom(field:"account") "Block number this asset was updated at in the contract" accrualBlockNumber: BigInt! + "Borrow Index this position last accrued interest" + borrowIndex: BigInt! "vToken balance representing underlying supplied to the market, underlying balance can be calculated with the exchange rate" - accountVTokenSupplyBalanceMantissa: BigInt! - "Current borrow balance stored in contract (exclusive of interest since accrualBlockNumber)" - accountBorrowBalanceMantissa: BigInt! + vTokenBalanceMantissa: BigInt! + "Stored borrow balance stored in contract (exclusive of interest since accrualBlockNumber)" + storedBorrowBalanceMantissa: BigInt! "True if user is entered, false if they are exited" enteredMarket: Boolean! - "Total amount of underlying redeemed" totalUnderlyingRedeemedMantissa: BigInt! - "The value of the borrow index upon users last interaction" - accountBorrowIndexMantissa: BigInt! "Total amount underlying repaid" totalUnderlyingRepaidMantissa: BigInt! } diff --git a/subgraphs/isolated-pools/src/mappings/pool.ts b/subgraphs/isolated-pools/src/mappings/pool.ts index ea208a9d..2a0d689a 100644 --- a/subgraphs/isolated-pools/src/mappings/pool.ts +++ b/subgraphs/isolated-pools/src/mappings/pool.ts @@ -14,7 +14,6 @@ import { NewRewardsDistributor, NewSupplyCap, } from '../../generated/PoolRegistry/Comptroller'; -import { VToken as VTokenContract } from '../../generated/PoolRegistry/VToken'; import { RewardsDistributor as RewardsDistributorDataSource } from '../../generated/templates'; import { zeroBigInt32 } from '../constants'; import { getMarket } from '../operations/get'; @@ -31,8 +30,7 @@ import { import Box from '../utilities/box'; export function handleMarketSupported(event: MarketSupported): void { - const vTokenContract = VTokenContract.bind(event.params.vToken); - const comptroller = vTokenContract.comptroller(); + const comptroller = event.address; const market = getOrCreateMarket(event.params.vToken, comptroller, event.block.timestamp); market.isListed = true; market.collateralFactorMantissa = zeroBigInt32; diff --git a/subgraphs/isolated-pools/src/mappings/vToken.ts b/subgraphs/isolated-pools/src/mappings/vToken.ts index 27a34c64..6651e9fd 100644 --- a/subgraphs/isolated-pools/src/mappings/vToken.ts +++ b/subgraphs/isolated-pools/src/mappings/vToken.ts @@ -209,8 +209,8 @@ export function handleLiquidateBorrow(event: LiquidateBorrow): void { const borrowerBorrowAccountVToken = borrowerBorrowAccountVTokenResult.entity; // Creation updates balance - borrowerBorrowAccountVToken.accountBorrowIndexMantissa = borrowedVTokenContract.borrowIndex(); - borrowerBorrowAccountVToken.accountBorrowBalanceMantissa = + borrowerBorrowAccountVToken.borrowIndex = borrowedVTokenContract.borrowIndex(); + borrowerBorrowAccountVToken.storedBorrowBalanceMantissa = borrowedVTokenContract.borrowBalanceStored(event.params.borrower); borrowerBorrowAccountVToken.save(); @@ -221,8 +221,8 @@ export function handleLiquidateBorrow(event: LiquidateBorrow): void { ); const borrowerSupplyAccountVToken = borrowerSupplyAccountVTokenResult.entity; - borrowerSupplyAccountVToken.accountVTokenSupplyBalanceMantissa = - borrowerSupplyAccountVToken.accountVTokenSupplyBalanceMantissa.minus(event.params.seizeTokens); + borrowerSupplyAccountVToken.vTokenBalanceMantissa = + borrowerSupplyAccountVToken.vTokenBalanceMantissa.minus(event.params.seizeTokens); borrowerSupplyAccountVToken.save(); const collateralBalance = collateralContract.balanceOf(event.params.borrower); @@ -298,8 +298,9 @@ export function handleTransfer(event: Transfer): void { // Creation updates balance if (!resultFrom.created) { - accountFromVToken.accountVTokenSupplyBalanceMantissa = - accountFromVToken.accountVTokenSupplyBalanceMantissa.minus(event.params.amount); + accountFromVToken.vTokenBalanceMantissa = accountFromVToken.vTokenBalanceMantissa.minus( + event.params.amount, + ); accountFromVToken.save(); } getOrCreateAccount(accountToAddress); @@ -319,8 +320,9 @@ export function handleTransfer(event: Transfer): void { // Creation updates balance if (!resultTo.created) { - accountToVToken.accountVTokenSupplyBalanceMantissa = - accountToVToken.accountVTokenSupplyBalanceMantissa.plus(event.params.amount); + accountToVToken.vTokenBalanceMantissa = accountToVToken.vTokenBalanceMantissa.plus( + event.params.amount, + ); accountToVToken.save(); } } diff --git a/subgraphs/isolated-pools/src/operations/getOrCreate.ts b/subgraphs/isolated-pools/src/operations/getOrCreate.ts index 66b72c3d..b3d1e44a 100644 --- a/subgraphs/isolated-pools/src/operations/getOrCreate.ts +++ b/subgraphs/isolated-pools/src/operations/getOrCreate.ts @@ -94,15 +94,15 @@ export const getOrCreateAccountVToken = ( const suppliedAmountMantissa = accountSnapshot.value1; const borrowedAmountMantissa = accountSnapshot.value2; - accountVToken.accountVTokenSupplyBalanceMantissa = suppliedAmountMantissa; - accountVToken.accountBorrowBalanceMantissa = borrowedAmountMantissa; + accountVToken.vTokenBalanceMantissa = suppliedAmountMantissa; + accountVToken.storedBorrowBalanceMantissa = borrowedAmountMantissa; // @TODO // accountVToken.vTokenBalanceMantissa = vTokenContract.balanceOf(accountId); // accountVToken.storedBorrowBalanceMantissa = zeroBigInt32; // accountVToken.borrowIndex = vTokenContract.borrowIndex(); accountVToken.totalUnderlyingRedeemedMantissa = zeroBigInt32; - accountVToken.accountBorrowIndexMantissa = zeroBigInt32; + accountVToken.borrowIndex = zeroBigInt32; accountVToken.totalUnderlyingRepaidMantissa = zeroBigInt32; accountVToken.enteredMarket = false; accountVToken.save(); diff --git a/subgraphs/isolated-pools/src/operations/recordLiquidatorAsSupplier.ts b/subgraphs/isolated-pools/src/operations/recordLiquidatorAsSupplier.ts index 68bf5efd..810dad0a 100644 --- a/subgraphs/isolated-pools/src/operations/recordLiquidatorAsSupplier.ts +++ b/subgraphs/isolated-pools/src/operations/recordLiquidatorAsSupplier.ts @@ -45,8 +45,8 @@ export const recordLiquidatorAsSupplier = (event: ProtocolSeize): void => { // Creation updates balance if (!liquidatorAccountVTokenResult.created) { - liquidatorAccountVToken.accountVTokenSupplyBalanceMantissa = - liquidatorAccountVToken.accountVTokenSupplyBalanceMantissa.plus(amount); + liquidatorAccountVToken.vTokenBalanceMantissa = + liquidatorAccountVToken.vTokenBalanceMantissa.plus(amount); } liquidatorAccountVToken.save(); // If the transfer amount equals balance it was a funding transfer diff --git a/subgraphs/isolated-pools/src/operations/update.ts b/subgraphs/isolated-pools/src/operations/update.ts index c32fa0cc..3e86c13e 100644 --- a/subgraphs/isolated-pools/src/operations/update.ts +++ b/subgraphs/isolated-pools/src/operations/update.ts @@ -34,7 +34,7 @@ export const updateAccountVTokenSupply = ( marketAddress, blockNumber, ); - accountVToken.accountVTokenSupplyBalanceMantissa = accountSupplyBalanceMantissa; + accountVToken.vTokenBalanceMantissa = accountSupplyBalanceMantissa; accountVToken.save(); return accountVToken as AccountVToken; }; @@ -53,8 +53,8 @@ export const updateAccountVTokenBorrow = ( marketAddress, blockNumber, ); - accountVToken.accountBorrowBalanceMantissa = accountBorrows; - accountVToken.accountBorrowIndexMantissa = borrowIndexMantissa; + accountVToken.storedBorrowBalanceMantissa = accountBorrows; + accountVToken.borrowIndex = borrowIndexMantissa; accountVToken.save(); return accountVToken as AccountVToken; }; @@ -73,8 +73,8 @@ export const updateAccountVTokenRepayBorrow = ( marketAddress, blockNumber, ); - accountVToken.accountBorrowBalanceMantissa = accountBorrows; - accountVToken.accountBorrowIndexMantissa = borrowIndexMantissa; + accountVToken.storedBorrowBalanceMantissa = accountBorrows; + accountVToken.borrowIndex = borrowIndexMantissa; accountVToken.save(); return accountVToken as AccountVToken; }; @@ -133,7 +133,7 @@ export const updateMarket = ( const marketContract = VToken.bind(vTokenAddress); const tokenPriceCents = getTokenPriceInCents( - marketContract.comptroller(), + Address.fromBytes(market.pool), vTokenAddress, market.underlyingDecimals, ); diff --git a/subgraphs/isolated-pools/tests/VToken/index.test.ts b/subgraphs/isolated-pools/tests/VToken/index.test.ts index 7d6df7ee..a61d0098 100644 --- a/subgraphs/isolated-pools/tests/VToken/index.test.ts +++ b/subgraphs/isolated-pools/tests/VToken/index.test.ts @@ -215,13 +215,13 @@ describe('VToken', () => { assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountVTokenSupplyBalanceMantissa', + 'vTokenBalanceMantissa', accountBalance.toString(), ); assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowBalanceMantissa', + 'storedBorrowBalanceMantissa', zeroBigInt32.toString(), ); assert.fieldEquals( @@ -230,12 +230,7 @@ describe('VToken', () => { 'totalUnderlyingRedeemedMantissa', zeroBigInt32.toString(), ); - assert.fieldEquals( - 'AccountVToken', - accountVTokenId, - 'accountBorrowIndexMantissa', - zeroBigInt32.toString(), - ); + assert.fieldEquals('AccountVToken', accountVTokenId, 'borrowIndex', zeroBigInt32.toString()); }); test('registers redeem event', () => { @@ -294,13 +289,13 @@ describe('VToken', () => { assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountVTokenSupplyBalanceMantissa', + 'vTokenBalanceMantissa', zeroBigInt32.toString(), ); assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowBalanceMantissa', + 'storedBorrowBalanceMantissa', zeroBigInt32.toString(), ); assert.fieldEquals( @@ -309,12 +304,7 @@ describe('VToken', () => { 'totalUnderlyingRedeemedMantissa', zeroBigInt32.toString(), ); - assert.fieldEquals( - 'AccountVToken', - accountVTokenId, - 'accountBorrowIndexMantissa', - zeroBigInt32.toString(), - ); + assert.fieldEquals('AccountVToken', accountVTokenId, 'borrowIndex', zeroBigInt32.toString()); }); test('registers borrow event', () => { @@ -386,13 +376,13 @@ describe('VToken', () => { assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowBalanceMantissa', + 'storedBorrowBalanceMantissa', accountBorrows.toString(), ); assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowIndexMantissa', + 'borrowIndex', market.borrowIndexMantissa.toString(), ); }); @@ -474,13 +464,13 @@ describe('VToken', () => { assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowBalanceMantissa', + 'storedBorrowBalanceMantissa', accountBorrows.toString(), ); assert.fieldEquals( 'AccountVToken', accountVTokenId, - 'accountBorrowIndexMantissa', + 'borrowIndex', market.borrowIndexMantissa.toString(), ); }); @@ -649,7 +639,7 @@ describe('VToken', () => { transferEvent.block.number.toString(), ); - assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); + assert.fieldEquals('AccountVToken', accountVTokenId, 'borrowIndex', '0'); assert.fieldEquals('AccountVToken', accountVTokenId, 'totalUnderlyingRedeemedMantissa', '0'); }); @@ -722,7 +712,7 @@ describe('VToken', () => { transferEvent.block.number.toString(), ); - assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); + assert.fieldEquals('AccountVToken', accountVTokenId, 'borrowIndex', '0'); }); test('registers new interest rate model', () => { diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountFromMarket.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountFromMarket.graphql index c54f7207..a897173f 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/accountFromMarket.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/accountFromMarket.graphql @@ -8,10 +8,10 @@ query AccountFromMarket($marketId: ID!, $accountId: Bytes!){ block } enteredMarket - accountVTokenSupplyBalanceMantissa - accountBorrowBalanceMantissa + vTokenBalanceMantissa + borrowIndex totalUnderlyingRedeemedMantissa - accountBorrowIndexMantissa + storedBorrowBalanceMantissa totalUnderlyingRepaidMantissa } } diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountPositions.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountPositions.graphql index dd7456a5..d8269cdf 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/accountPositions.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/accountPositions.graphql @@ -10,9 +10,9 @@ query AccountPositions($id: ID!) { closeFactorMantissa minLiquidatableCollateralMantissa } - collateral: tokens(where: { accountVTokenSupplyBalanceMantissa_gt: 0 }) { + supplies: tokens(where: { vTokenBalanceMantissa_gt: 0 }) { id - accountVTokenSupplyBalanceMantissa + vTokenBalanceMantissa market { id liquidationThresholdMantissa @@ -22,10 +22,10 @@ query AccountPositions($id: ID!) { underlyingDecimals } } - borrows: tokens(where: { accountBorrowBalanceMantissa_gt: 0 }) { + borrows: tokens(where: { storedBorrowBalanceMantissa_gt: 0 }) { id - accountBorrowBalanceMantissa - accountBorrowIndexMantissa + storedBorrowBalanceMantissa + borrowIndex market { id underlyingAddress diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccount.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccount.graphql index 7aa5baae..4cf3a6e9 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccount.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccount.graphql @@ -14,10 +14,10 @@ query AccountVTokenByAccountId($accountId: String!) { block } enteredMarket - accountVTokenSupplyBalanceMantissa - accountBorrowBalanceMantissa + vTokenBalanceMantissa + storedBorrowBalanceMantissa totalUnderlyingRedeemedMantissa - accountBorrowIndexMantissa + borrowIndex totalUnderlyingRepaidMantissa } } diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccountAndMarket.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccountAndMarket.graphql index 4b1aa3c0..9ee77dcf 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccountAndMarket.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/accountVTokenByAccountAndMarket.graphql @@ -1,6 +1,17 @@ -query AccountVTokenByAccountAndMarketQuery($accountId: String!, $marketId: String!) { - accountVTokens(where: { account: $accountId, market: $marketId }) { +query AccountVTokenByAccountAndMarket($id: ID!) { + accountVToken(id: $id) { id + accountPool { + pool { + id + } + account { + id + } + tokens { + id + } + } market { id } @@ -14,10 +25,10 @@ query AccountVTokenByAccountAndMarketQuery($accountId: String!, $marketId: Strin block } enteredMarket - accountVTokenSupplyBalanceMantissa - accountBorrowBalanceMantissa + vTokenBalanceMantissa + storedBorrowBalanceMantissa totalUnderlyingRedeemedMantissa - accountBorrowIndexMantissa + borrowIndex totalUnderlyingRepaidMantissa } } diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountVTokens.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountVTokens.graphql index 581291f9..1ca62e87 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/accountVTokens.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/accountVTokens.graphql @@ -14,10 +14,10 @@ query AccountVTokens { block } enteredMarket - accountVTokenSupplyBalanceMantissa - accountBorrowBalanceMantissa + vTokenBalanceMantissa + storedBorrowBalanceMantissa totalUnderlyingRedeemedMantissa - accountBorrowIndexMantissa + borrowIndex totalUnderlyingRepaidMantissa } } From db4d4b8b36a7934c76677757aece2a1024a91ffc Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:27:13 -0300 Subject: [PATCH 3/8] chore: update hardhat-dependency-compiler --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8893ae9b..118f49ea 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "graphql": "16.6.0", "graphql-tag": "2.12.6", "hardhat": "^2.16.1", - "hardhat-dependency-compiler": "^1.1.3", + "hardhat-dependency-compiler": "^1.2.1", "hardhat-deploy": "^0.11.15", "hardhat-deploy-ethers": "^0.3.0-beta.13", "hardhat-gas-reporter": "^1.0.8", diff --git a/yarn.lock b/yarn.lock index 48668b5c..46ba257b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8663,7 +8663,7 @@ __metadata: languageName: node linkType: hard -"hardhat-dependency-compiler@npm:^1.1.3": +"hardhat-dependency-compiler@npm:^1.2.1": version: 1.2.1 resolution: "hardhat-dependency-compiler@npm:1.2.1" peerDependencies: @@ -13231,7 +13231,7 @@ __metadata: graphql: 16.6.0 graphql-tag: 2.12.6 hardhat: ^2.16.1 - hardhat-dependency-compiler: ^1.1.3 + hardhat-dependency-compiler: ^1.2.1 hardhat-deploy: ^0.11.15 hardhat-deploy-ethers: ^0.3.0-beta.13 hardhat-gas-reporter: ^1.0.8 From 2809d3185b6e666664ef6d028049b752f64df50f Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:31:26 -0300 Subject: [PATCH 4/8] refactor: update and add graphql queries --- .../isolated-pools/subgraph-client/index.ts | 49 +++++++++++++------ ...accountVTokensWithBorrowByMarketId.graphql | 10 ++++ ...accountVTokensWithSupplyByMarketId.graphql | 9 ++++ .../queries/marketByIdQuery.graphql | 2 + .../integration/queries/marketsQuery.graphql | 1 + 5 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithBorrowByMarketId.graphql create mode 100644 subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithSupplyByMarketId.graphql diff --git a/subgraphs/isolated-pools/subgraph-client/index.ts b/subgraphs/isolated-pools/subgraph-client/index.ts index b447a963..6db780f7 100644 --- a/subgraphs/isolated-pools/subgraph-client/index.ts +++ b/subgraphs/isolated-pools/subgraph-client/index.ts @@ -1,16 +1,21 @@ import { DocumentNode } from 'graphql'; -import { OperationResult, Client as UrqlClient, createClient } from 'urql/core'; +import { Client as UrqlClient, createClient } from 'urql/core'; import { AccountByIdDocument, AccountFromMarketDocument, AccountPositionsDocument, - AccountVTokenByAccountAndMarketQueryDocument, - AccountVTokenByAccountAndMarketQueryQuery, + AccountVTokenByAccountAndMarketDocument, + AccountVTokenByAccountAndMarketQuery, AccountVTokenByAccountIdDocument, AccountVTokensDocument, + AccountVTokensQuery, + AccountVTokensWithBorrowByMarketIdDocument, + AccountVTokensWithSupplyByMarketIdDocument, + AccountVTokensWithSupplyByMarketIdQuery, MarketActionsDocument, MarketByIdDocument, + MarketByIdQuery, MarketsDocument, PoolByIdDocument, PoolsDocument, @@ -49,9 +54,9 @@ class SubgraphClient { return result; } - async getMarketById(id: string) { + async getMarketById(id: string): Promise { const result = await this.query(MarketByIdDocument, { id }); - return result; + return result.data; } async getAccountById(id: string) { @@ -59,9 +64,9 @@ class SubgraphClient { return result; } - async getAccountVTokens() { + async getAccountVTokens(): Promise { const result = await this.query(AccountVTokensDocument, {}); - return result; + return result.data; } async getMarketActions() { @@ -79,15 +84,31 @@ class SubgraphClient { return result; } - async getAccountVTokenByAccountAndMarket( - accountId: string, + async getAccountVTokensWithSupplyByMarketId( + marketId: string, + ): Promise { + const result = await this.query(AccountVTokensWithSupplyByMarketIdDocument, { marketId }); + return result.data; + } + + async getAccountVTokensWithBorrowByMarketId( marketId: string, - ): Promise> { - const result = await this.query(AccountVTokenByAccountAndMarketQueryDocument, { - accountId, - marketId, + ): Promise { + const result = await this.query(AccountVTokensWithBorrowByMarketIdDocument, { marketId }); + return result.data; + } + + async getAccountVTokenByAccountAndMarket({ + accountId, + marketId, + }: { + accountId: string; + marketId: string; + }): Promise { + const result = await this.query(AccountVTokenByAccountAndMarketDocument, { + id: `${marketId}${accountId.replace('0x', '')}`, }); - return result; + return result.data || { accountVToken: null }; } async getAccountPositions(id: string) { diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithBorrowByMarketId.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithBorrowByMarketId.graphql new file mode 100644 index 00000000..f0d87662 --- /dev/null +++ b/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithBorrowByMarketId.graphql @@ -0,0 +1,10 @@ +query AccountVTokensWithBorrowByMarketId($marketId: String!) { + accountVTokens(where: { market: $marketId, storedBorrowBalanceMantissa_gt: 0 }) { + id + account { + id + } + storedBorrowBalanceMantissa + borrowIndex + } +} diff --git a/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithSupplyByMarketId.graphql b/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithSupplyByMarketId.graphql new file mode 100644 index 00000000..3e96d252 --- /dev/null +++ b/subgraphs/isolated-pools/tests/integration/queries/accountVTokensWithSupplyByMarketId.graphql @@ -0,0 +1,9 @@ +query AccountVTokensWithSupplyByMarketId($marketId: String!) { + accountVTokens(where: { market: $marketId, vTokenBalanceMantissa_gt: 0 }) { + id + account { + id + } + vTokenBalanceMantissa + } +} diff --git a/subgraphs/isolated-pools/tests/integration/queries/marketByIdQuery.graphql b/subgraphs/isolated-pools/tests/integration/queries/marketByIdQuery.graphql index 94560c4d..fa91dc56 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/marketByIdQuery.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/marketByIdQuery.graphql @@ -29,5 +29,7 @@ query MarketById($id: ID!) { underlyingDecimals supplierCount borrowerCount + totalBorrowsMantissa + totalSupplyVTokenMantissa } } diff --git a/subgraphs/isolated-pools/tests/integration/queries/marketsQuery.graphql b/subgraphs/isolated-pools/tests/integration/queries/marketsQuery.graphql index 1721e371..594e5eb9 100644 --- a/subgraphs/isolated-pools/tests/integration/queries/marketsQuery.graphql +++ b/subgraphs/isolated-pools/tests/integration/queries/marketsQuery.graphql @@ -21,6 +21,7 @@ query Markets { accrualBlockNumber blockTimestamp borrowIndexMantissa + liquidationThresholdMantissa reserveFactorMantissa underlyingPriceCentsMantissa underlyingDecimals From 1992b4c832fc629e3afc1734c3332612fc575061 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:33:44 -0300 Subject: [PATCH 5/8] test: reset values after test --- .../isolated-pools/tests/integration/pool.ts | 66 ++++--------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/subgraphs/isolated-pools/tests/integration/pool.ts b/subgraphs/isolated-pools/tests/integration/pool.ts index 83d1220e..b5e353aa 100644 --- a/subgraphs/isolated-pools/tests/integration/pool.ts +++ b/subgraphs/isolated-pools/tests/integration/pool.ts @@ -1,6 +1,4 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { expect } from 'chai'; -import { Contract, Signer } from 'ethers'; import { ethers } from 'hardhat'; import { scaleValue, waitForSubgraphToBeSynced } from 'venus-subgraph-utils'; @@ -8,20 +6,9 @@ import subgraphClient from '../../subgraph-client'; import { defaultMarkets } from './constants'; describe('Pools', function () { - let acc1: Signer; - let _root: SignerWithAddress; - let poolRegistry: Contract; - let poolLens: Contract; - const syncDelay = 6000; before(async function () { - const signers = await ethers.getSigners(); - [_root, acc1] = signers; - - poolRegistry = await ethers.getContract('PoolRegistry'); - poolLens = await ethers.getContract('PoolLens'); - await waitForSubgraphToBeSynced(syncDelay); }); @@ -65,45 +52,6 @@ describe('Pools', function () { }); }); - it('handles MarketEntered and MarketExited events', async function () { - const pools = await poolLens.getAllPools(poolRegistry.address); - const pool1Comptroller = await ethers.getContractAt('Comptroller', pools[0].comptroller); - - await pool1Comptroller.connect(acc1).enterMarkets(pools[0].vTokens.map(m => m.vToken)); - const account1Address = await acc1.getAddress(); - await waitForSubgraphToBeSynced(syncDelay); - - // check account - const { data } = await subgraphClient.getAccountById(account1Address.toLowerCase()); - const { account } = data!; - expect(account?.id).to.equal(account1Address.toLowerCase()); - expect(account?.pools.length).to.equal(1); - expect(account?.countLiquidated).to.equal(0); - expect(account?.countLiquidator).to.equal(0); - expect(account?.hasBorrowed).to.equal(false); - - // check accountVTokens - const { data: accountVTokensData } = await subgraphClient.getAccountVTokensByAccountId( - account1Address.toLowerCase(), - ); - expect(accountVTokensData).to.not.be.equal(undefined); - const { accountVTokens } = accountVTokensData!; - - accountVTokens.forEach((avt, idx) => { - expect(avt.id).to.equal(account?.pools[0].tokens[idx].id); - const expectedMarketId = account?.pools[0].tokens[idx].id.slice(0, 42); - expect(avt.market.id).to.equal(expectedMarketId); - expect(avt.account.id).to.equal(account?.id); - - expect(avt.enteredMarket).to.equal(true); - expect(avt.accountVTokenSupplyBalanceMantissa).to.equal('0'); - expect(avt.totalUnderlyingRedeemedMantissa).to.equal('0'); - expect(avt.accountBorrowIndexMantissa).to.equal('0'); - expect(avt.totalUnderlyingRepaidMantissa).to.equal('0'); - expect(avt.accountBorrowBalanceMantissa).to.equal('0'); - }); - }); - it('handles NewCloseFactor event', async function () { const { data: dataBeforeUpdate } = await subgraphClient.getPools(); const { pools: poolsBeforeUpdate } = dataBeforeUpdate!; @@ -142,11 +90,17 @@ describe('Pools', function () { await tx.wait(1); await waitForSubgraphToBeSynced(4000); - const { data } = await subgraphClient.getMarketById(market.id); - const { market: marketNew } = data!; + const { market: marketNew } = await subgraphClient.getMarketById(market.id); expect(marketNew?.collateralFactorMantissa).to.equal('60000000000000'); expect(marketNew?.liquidationThresholdMantissa).to.equal('90000000000000'); + + // reset + await comptrollerProxy.setCollateralFactor( + marketsBeforeEvent[1].id, + market.collateralFactorMantissa.toString(), // collateral factor + market.liquidationThresholdMantissa.toString(), // liquidation threshold + ); }); it('handles NewLiquidationIncentive event', async function () { @@ -165,6 +119,8 @@ describe('Pools', function () { const { pools } = data!; expect(pools[0].liquidationIncentiveMantissa).to.equal('3000000000000000000'); + // reset + await comptrollerProxy.setLiquidationIncentive('1000000000000000000'); }); it('handles NewPriceOracle event', async function () { @@ -260,6 +216,8 @@ describe('Pools', function () { const { pools } = data!; expect(pools[0].minLiquidatableCollateralMantissa).to.equal('200000000000000000000'); + // reset + await comptrollerProxy.setMinLiquidatableCollateral('100000000000000000000'); }); it('handles NewSupplyCap event', async function () { From 0025d658031326bb129b85169f3ce3eabb7c2f99 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 17:34:08 -0300 Subject: [PATCH 6/8] chore: fix typos --- subgraphs/venus/tests/integration/vTokens.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subgraphs/venus/tests/integration/vTokens.ts b/subgraphs/venus/tests/integration/vTokens.ts index bf39b203..6966351f 100644 --- a/subgraphs/venus/tests/integration/vTokens.ts +++ b/subgraphs/venus/tests/integration/vTokens.ts @@ -564,13 +564,13 @@ describe('VToken events', function () { }); it('should handle accrue interest event with added reserves', async function () { - const fdusd50Usd = await oracle.getAssetTokenAmount( + const fdusd10Usd = await oracle.getAssetTokenAmount( vFdusdToken.address, parseUnits('10', 36), ); const doge50Usd = await oracle.getAssetTokenAmount(vDogeToken.address, parseUnits('50', 36)); for (const [vToken, amount] of [ - [vFdusdToken, fdusd50Usd], + [vFdusdToken, fdusd10Usd], [vDogeToken, doge50Usd], ]) { const borrowRateMantissaPrev = await vToken.borrowRatePerBlock(); @@ -809,7 +809,7 @@ describe('VToken events', function () { it('should not update the supplier count on the market when current accounts mint again', async function () { // Supply all accounts - const usdc100Usd = await oracle.getAssetTokenAmount( + const usdc1000Usd = await oracle.getAssetTokenAmount( vUsdcToken.address, parseUnits('1000', 36), ); @@ -823,7 +823,7 @@ describe('VToken events', function () { ); for (const account of suppliers) { - await vUsdcToken.connect(account).mint(usdc100Usd.toString()); + await vUsdcToken.connect(account).mint(usdc1000Usd.toString()); await vWBnbToken.connect(account).mint({ value: bnb1000Usd.toString() }); await vEthToken.connect(account).mint(eth2000Usd.toString()); } @@ -846,7 +846,7 @@ describe('VToken events', function () { } for (const account of borrowers) { - await vUsdcToken.connect(rootSigner).mintBehalf(account._address, usdc100Usd.toString()); + await vUsdcToken.connect(rootSigner).mintBehalf(account._address, usdc1000Usd.toString()); await vEthToken.connect(rootSigner).mintBehalf(account._address, eth2000Usd.toString()); } From 21253144c16f65cb6915a8786f59c784054bb777 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Tue, 1 Oct 2024 18:05:29 -0300 Subject: [PATCH 7/8] test: update isolated pools test --- .../tests/integration/checkEntities.ts | 48 ++ .../tests/integration/unlistMarkets.ts | 6 +- .../tests/integration/vTokens.ts | 472 +++++++++++------- 3 files changed, 336 insertions(+), 190 deletions(-) create mode 100644 subgraphs/isolated-pools/tests/integration/checkEntities.ts diff --git a/subgraphs/isolated-pools/tests/integration/checkEntities.ts b/subgraphs/isolated-pools/tests/integration/checkEntities.ts new file mode 100644 index 00000000..4d2c8271 --- /dev/null +++ b/subgraphs/isolated-pools/tests/integration/checkEntities.ts @@ -0,0 +1,48 @@ +import { TransactionResponse } from '@ethersproject/abstract-provider'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import subgraphClient from '../../subgraph-client'; + +export const checkMarket = async (marketAddress: string) => { + const vToken = await ethers.getContractAt('VToken', marketAddress); + const { accountVTokens: accountVTokensSupply } = + await subgraphClient.getAccountVTokensWithSupplyByMarketId(marketAddress.toLowerCase()); + const { accountVTokens: accountVTokensBorrow } = + await subgraphClient.getAccountVTokensWithBorrowByMarketId(marketAddress.toLowerCase()); + const { market } = await subgraphClient.getMarketById(marketAddress.toLowerCase()); + expect(market?.supplierCount).to.equal(accountVTokensSupply.length.toString()); + expect(market?.borrowerCount).to.equal(accountVTokensBorrow.length.toString()); + + expect(market?.totalBorrowsMantissa).to.equal(await vToken.totalBorrows()); + expect(market?.totalSupplyVTokenMantissa).to.equal(await vToken.totalSupply()); + + expect(market?.borrowIndexMantissa).to.equal(await vToken.borrowIndex()); + expect(market?.borrowRateMantissa).to.equal(await vToken.borrowRatePerBlock()); + expect(market?.supplyRateMantissa).to.equal(await vToken.supplyRatePerBlock()); + + expect(market?.cashMantissa).to.equal(await vToken.getCash()); + expect(market?.reservesMantissa).to.equal(await vToken.totalReserves()); + + return market; +}; + +export const checkAccountVToken = async ( + accountAddress: string, + marketAddress: string, + transaction: TransactionResponse, +) => { + const vToken = await ethers.getContractAt('VToken', marketAddress); + + const { accountVToken } = await subgraphClient.getAccountVTokenByAccountAndMarket({ + accountId: accountAddress.toLowerCase(), + marketId: marketAddress.toLowerCase(), + }); + expect(accountVToken!.accrualBlockNumber).to.equal(transaction.blockNumber); + expect(accountVToken!.vTokenBalanceMantissa).to.equal(await vToken.balanceOf(accountAddress)); + expect(accountVToken!.storedBorrowBalanceMantissa).to.equal( + await vToken.borrowBalanceStored(accountAddress), + ); + expect(accountVToken!.borrowIndex).to.equal(await vToken.borrowIndex()); + expect(accountVToken!.enteredMarket).to.equal(await vToken.checkMembership(accountAddress)); +}; diff --git a/subgraphs/isolated-pools/tests/integration/unlistMarkets.ts b/subgraphs/isolated-pools/tests/integration/unlistMarkets.ts index 0635dba3..aa33342e 100644 --- a/subgraphs/isolated-pools/tests/integration/unlistMarkets.ts +++ b/subgraphs/isolated-pools/tests/integration/unlistMarkets.ts @@ -48,11 +48,9 @@ describe('VToken events', function () { await waitForSubgraphToBeSynced(syncDelay); for (const market of markets) { - const { - data: { market: unlistedMarket }, - } = await subgraphClient.getMarketById(market.toLowerCase()); + const { market: unlistedMarket } = await subgraphClient.getMarketById(market.toLowerCase()); - expect(unlistedMarket.isListed).to.equal(false); + expect(unlistedMarket?.isListed).to.equal(false); } }); }); diff --git a/subgraphs/isolated-pools/tests/integration/vTokens.ts b/subgraphs/isolated-pools/tests/integration/vTokens.ts index e1a29878..11c7a51e 100644 --- a/subgraphs/isolated-pools/tests/integration/vTokens.ts +++ b/subgraphs/isolated-pools/tests/integration/vTokens.ts @@ -2,9 +2,10 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { expect } from 'chai'; import { Contract } from 'ethers'; import { ethers } from 'hardhat'; -import { scaleValue, waitForSubgraphToBeSynced } from 'venus-subgraph-utils'; +import { waitForSubgraphToBeSynced } from 'venus-subgraph-utils'; import subgraphClient from '../../subgraph-client'; +import { checkAccountVToken, checkMarket } from './checkEntities'; const { parseUnits } = ethers.utils; const { MaxUint256 } = ethers.constants; @@ -12,12 +13,12 @@ const { MaxUint256 } = ethers.constants; describe('VToken events', function () { const syncDelay = 2000; let root: SignerWithAddress; - let liquidator: SignerWithAddress; - let liquidator2: SignerWithAddress; let supplier1: SignerWithAddress; let supplier2: SignerWithAddress; - let borrower: SignerWithAddress; + let borrower1: SignerWithAddress; let borrower2: SignerWithAddress; + let liquidator1: SignerWithAddress; + let liquidator2: SignerWithAddress; let comptroller: Contract; let bnxToken: Contract; let vBnxToken: Contract; @@ -31,18 +32,20 @@ describe('VToken events', function () { before(async function () { const signers = await ethers.getSigners(); - [root, supplier1, supplier2, borrower, borrower2, liquidator, liquidator2] = signers; + [root, supplier1, supplier2, borrower1, borrower2, liquidator1, liquidator2] = signers; const fundAccounts = async (token: Contract, amount: string) => { const underlying = await token.underlying(); const underlyingContract = await ethers.getContractAt('BEP20Harness', underlying); await Promise.all( - [supplier1, supplier2, borrower, borrower2, liquidator, liquidator2].map(async account => { - await underlyingContract.connect(account).faucet(amount); - await underlyingContract.connect(account).approve(token.address, MaxUint256); - await underlyingContract.connect(root).faucet(amount); - await underlyingContract.connect(root).approve(token.address, MaxUint256); - }), + [supplier1, supplier2, borrower1, borrower2, liquidator1, liquidator2].map( + async account => { + await underlyingContract.connect(account).faucet(amount); + await underlyingContract.connect(account).approve(token.address, MaxUint256); + await underlyingContract.connect(root).faucet(amount); + await underlyingContract.connect(root).approve(token.address, MaxUint256); + }, + ), ); }; @@ -94,263 +97,365 @@ describe('VToken events', function () { await waitForSubgraphToBeSynced(syncDelay); }); - it('updates the supplierCount for the market', async function () { - const { data: initialData } = await subgraphClient.getMarketById(vBtcbAddress.toLowerCase()); - const { market: initialMarketQuery } = initialData!; + it('should update correctly when minting', async function () { + const btcb1000Usd = await oracle.getAssetTokenAmount( + vBtcbToken.address, + parseUnits('1000', 36), + ); + + // adding two new suppliers + const tx1 = await vBtcbToken.connect(supplier1).mint(btcb1000Usd.toString()); + await tx1.wait(1); + + const tx2 = await vBtcbToken.connect(supplier2).mint(btcb1000Usd.toString()); + await tx2.wait(1); + + await waitForSubgraphToBeSynced(syncDelay); + + checkAccountVToken(supplier1.address, vBtcbToken.address, tx1); + + checkAccountVToken(supplier2.address, vBtcbToken.address, tx2); + const vBtcbMarket = await checkMarket(vBtcbToken.address); + // Deployer is initial supplier + expect(vBtcbMarket?.supplierCount).to.equal('3'); + }); + it('should not increment supplier count and update correctly when mint again', async function () { const btcb5000Usd = await oracle.getAssetTokenAmount( vBtcbToken.address, parseUnits('5000', 36), ); - // 1 current supply - expect(initialMarketQuery?.supplierCount).to.equal('1'); + const bnx5000Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('5000', 36)); // adding two new suppliers - let tx = await vBtcbToken.connect(supplier1).mint(btcb5000Usd.toString()); - await tx.wait(1); + const tx1 = await vBtcbToken.connect(supplier1).mint(btcb5000Usd.toString()); + await tx1.wait(1); + + const tx2 = await vBtcbToken.connect(supplier2).mint(btcb5000Usd.toString()); + await tx2.wait(1); - tx = await vBtcbToken.connect(supplier2).mint(btcb5000Usd.toString()); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - // Check querying pools by account - const { data: positionData } = await subgraphClient.getAccountPositions( - supplier1.address.toLowerCase(), - ); - const { account } = positionData!; - expect(account.pools.length).to.equal(1); - // @todo rename account.pools[0].supply - expect(account.pools[0].collateral.length).to.equal(1); + checkAccountVToken(supplier1.address, vBtcbToken.address, tx1); - const { data: dataWithNewSupplier } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), - ); - const { market: marketsQueryAfterNewSupplier } = dataWithNewSupplier!; - expect(marketsQueryAfterNewSupplier?.supplierCount).to.equal('3'); + checkAccountVToken(supplier2.address, vBtcbToken.address, tx2); + + const vBtcbMarket = await checkMarket(vBtcbToken.address); + // Deployer is initial supplier + expect(vBtcbMarket?.supplierCount).to.equal('3'); + + await vBnxToken.connect(root).mintBehalf(supplier1.address, bnx5000Usd.toString()); + await vBnxToken.connect(root).mintBehalf(supplier2.address, bnx5000Usd.toString()); - // removing supplier - tx = await vBtcbToken.connect(supplier1).redeemUnderlying(btcb5000Usd.toString()); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data: dataWithoutNewSupplier } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), + checkAccountVToken(supplier1.address, vBnxToken.address, tx1); + + checkAccountVToken(supplier2.address, vBnxToken.address, tx2); + + const vBnxMarket = await checkMarket(vBnxToken.address); + expect(vBnxMarket?.supplierCount).to.equal('3'); + }); + + it('should not update the supplier count on the market when partially redeeming', async function () { + const btcb1000Usd = await oracle.getAssetTokenAmount( + vBtcbToken.address, + parseUnits('1000', 36), ); - const { market: marketQueryAfterRemovingSupplier } = dataWithoutNewSupplier!; + const tx1 = await vBtcbToken.connect(supplier1).redeemUnderlying(btcb1000Usd.toString()); + await tx1.wait(1); + const tx2 = await vBtcbToken.connect(supplier2).redeemUnderlying(btcb1000Usd.toString()); + await tx2.wait(1); - expect(marketQueryAfterRemovingSupplier?.supplierCount).to.equal('2'); + await waitForSubgraphToBeSynced(syncDelay); + + checkAccountVToken(supplier1.address, vBtcbToken.address, tx1); + checkAccountVToken(supplier1.address, vBtcbToken.address, tx2); + + const vBtcbMarket = await checkMarket(vBtcbToken.address); + + expect(vBtcbMarket?.supplierCount).to.equal('3'); + }); + + it('should update the supplier count on the market when fully redeeming', async function () { + const tx1 = await vBtcbToken + .connect(supplier1) + .redeem((await vBtcbToken.balanceOf(supplier1.address)).toString()); + await tx1.wait(1); + const tx2 = await vBtcbToken + .connect(supplier2) + .redeem((await vBtcbToken.balanceOf(supplier2.address)).toString()); + await tx2.wait(1); - // partially redeeming should not decrease count - const btcb10Usd = await oracle.getAssetTokenAmount(vBtcbToken.address, parseUnits('10', 36)); - tx = await vBtcbToken.connect(supplier2).redeemUnderlying(btcb10Usd.toString()); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data: dataAfterHalfRedeem } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), - ); - const { market: marketAfterHalfRedeem } = dataAfterHalfRedeem!; + checkAccountVToken(supplier1.address, vBtcbToken.address, tx1); + checkAccountVToken(supplier1.address, vBtcbToken.address, tx2); - expect(marketAfterHalfRedeem?.supplierCount).to.equal('2'); + const vBtcbMarket = await checkMarket(vBtcbToken.address); + + expect(vBtcbMarket?.supplierCount).to.equal('1'); }); - it('updates the borrowerCount for the market', async function () { - const { data: initialData } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); - const { market: marketBeforeData } = initialData!; - expect(marketBeforeData?.borrowerCount).to.equal('0'); + it('should handle enter market', async function () { + await comptroller.connect(borrower1).enterMarkets([vBnxToken.address, vBtcbToken.address]); + await comptroller.connect(borrower2).enterMarkets([vBnxToken.address, vBtcbToken.address]); - const btcb10000Usd = await oracle.getAssetTokenAmount( + await waitForSubgraphToBeSynced(syncDelay); + + for (const vTokenAddress of [vBnxToken.address, vBtcbToken.address]) { + const { accountVToken } = await subgraphClient.getAccountVTokenByAccountAndMarket({ + marketId: vTokenAddress.toLowerCase(), + accountId: borrower1.address, + }); + expect(accountVToken?.enteredMarket).to.equal(true); + } + + for (const vTokenAddress of [vBnxToken.address, vBtcbToken.address]) { + const { accountVToken } = await subgraphClient.getAccountVTokenByAccountAndMarket({ + marketId: vTokenAddress.toLowerCase(), + accountId: borrower2.address, + }); + expect(accountVToken?.enteredMarket).to.equal(true); + } + }); + + it('should handle exit market', async function () { + await comptroller.connect(borrower1).exitMarket(vBtcbToken.address); + await comptroller.connect(borrower2).exitMarket(vBnxToken.address); + + await waitForSubgraphToBeSynced(syncDelay); + + const { accountVToken: accountVTokenVUsdt } = + await subgraphClient.getAccountVTokenByAccountAndMarket({ + marketId: vBtcbToken.address.toLowerCase(), + accountId: borrower1.address, + }); + expect(accountVTokenVUsdt?.enteredMarket).to.equal(false); + + const { accountVToken: accountVTokenVDoge } = + await subgraphClient.getAccountVTokenByAccountAndMarket({ + marketId: vBnxToken.address.toLowerCase(), + accountId: borrower2.address, + }); + expect(accountVTokenVDoge?.enteredMarket).to.equal(false); + }); + + it('should update the borrower count on the market for new borrows', async function () { + const bnx1000Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('1000', 36)); + const btcb1000Usd = await oracle.getAssetTokenAmount( vBtcbToken.address, - parseUnits('1000000', 36), + parseUnits('1000', 36), ); - - const bnx20000Usd = await oracle.getAssetTokenAmount( - vBnxToken.address, - parseUnits('500000', 36), + await vBnxToken.connect(borrower1).mint(bnx1000Usd); + await vBtcbToken.connect(borrower2).mint(btcb1000Usd); + const { market: marketBeforeData } = await subgraphClient.getMarketById( + vBnxAddress.toLowerCase(), ); + expect(marketBeforeData?.borrowerCount).to.equal('0'); - const bnx1000Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('10000', 36)); + const bnx500Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('500', 36)); + const btcb500Usd = await oracle.getAssetTokenAmount(vBtcbToken.address, parseUnits('500', 36)); - // Root supplies BNX - await vBnxToken.connect(root).mint(bnx20000Usd.toString()); - // // Borrower supplies BTCB and borrows BNX - await vBtcbToken.connect(borrower).mint(btcb10000Usd.toString()); - await vBtcbToken.connect(borrower2).mint(btcb10000Usd.toString()); - // @todo check entering market - await comptroller.connect(borrower).enterMarkets([vBtcbToken.address]); - let tx = await comptroller.connect(borrower2).enterMarkets([vBtcbToken.address]); - await tx.wait(1); + const tx1 = await vBtcbToken.connect(borrower1).borrow(btcb500Usd); + const tx2 = await vBnxToken.connect(borrower2).borrow(bnx500Usd); - // borrowing adds to count - await vBnxToken.connect(borrower).borrow(bnx1000Usd.toString()); - tx = await vBnxToken.connect(borrower2).borrow(bnx1000Usd.toString()); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data: dataAfterBorrow } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); - const { market: marketAfterBorrow } = dataAfterBorrow!; + checkAccountVToken(borrower1.address, vBtcbToken.address, tx1); + checkAccountVToken(borrower2.address, vBnxToken.address, tx2); - expect(marketAfterBorrow?.borrowerCount).to.equal('2'); + const vBtcbMarket = await checkMarket(vBtcbToken.address); + expect(vBtcbMarket?.borrowerCount).to.equal('1'); + + const vBnxMarket = await checkMarket(vBnxToken.address); + expect(vBnxMarket?.borrowerCount).to.equal('1'); + }); + + it('should not update the borrower count on the market for repeated borrows', async function () { + const btcb50Usd = await oracle.getAssetTokenAmount(vBtcbToken.address, parseUnits('50', 36)); + + const bnx50Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('50', 36)); + + const tx1 = await vBtcbToken.connect(borrower1).borrow(btcb50Usd.toString()); + const tx2 = await vBnxToken.connect(borrower2).borrow(bnx50Usd.toString()); - tx = await vBnxToken.connect(borrower2).borrow(bnx1000Usd.toString()); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data: dataAfterBorrow2 } = await subgraphClient.getMarketById( - vBnxAddress.toLowerCase(), - ); - const { market: marketAfterBorrow2 } = dataAfterBorrow2!; + checkAccountVToken(borrower1.address, vBtcbToken.address, tx1); + checkAccountVToken(borrower2.address, vBnxToken.address, tx2); - expect(marketAfterBorrow2?.borrowerCount).to.equal('2'); + const vBtcbMarket = await checkMarket(vBtcbToken.address); + expect(vBtcbMarket?.borrowerCount).to.equal('1'); - const { data: positionData } = await subgraphClient.getAccountPositions( - borrower2.address.toLowerCase(), - ); - const { account } = positionData!; + const vBnxMarket = await checkMarket(vBnxToken.address); + expect(vBnxMarket?.borrowerCount).to.equal('1'); + }); - expect(account.pools.length).to.equal(1); - expect(account.pools[0].borrows.length).to.equal(1); - expect(account.pools[0].collateral.length).to.equal(1); + it('should not update the borrower count on the market for partial repayment of borrow', async function () { + const bnx10Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('10', 36)); + + const tx1 = await vBnxToken.connect(borrower2).repayBorrow(bnx10Usd); - // completely repaying the borrow should decrease the count - tx = await vBnxToken - .connect(borrower) - .repayBorrow((await vBnxToken.callStatic.borrowBalanceCurrent(borrower.address)) + 10000n); - await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); - const { market } = data!; + checkAccountVToken(borrower1.address, vBtcbToken.address, tx1); - expect(market?.borrowerCount).to.equal('1'); + const vBnxMarket = await checkMarket(vBnxToken.address); + expect(vBnxMarket?.borrowerCount).to.equal('1'); + }); - const { data: positionDataAfter } = await subgraphClient.getAccountPositions( - borrower2.address.toLowerCase(), - ); - const { account: accountAfter } = positionDataAfter!; - expect(accountAfter.pools.length).to.equal(1); - expect(accountAfter.pools[0].borrows.length).to.equal(1); + it('should handle accrue interest event', async function () { + for (const vToken of [vBtcbToken, vBnxToken]) { + await vToken.accrueInterest(); + + await waitForSubgraphToBeSynced(syncDelay); + await checkMarket(vToken.address); + } + }); + + it('should handle accrue interest event with added reserves', async function () { + const btcb50Usd = await oracle.getAssetTokenAmount(vBtcbToken.address, parseUnits('50', 36)); + const bnx50Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('50', 36)); + for (const [vToken, amount] of [ + [vBtcbToken, btcb50Usd], + [vBnxToken, bnx50Usd], + ]) { + await vToken.addReserves(amount.toString()); + + await waitForSubgraphToBeSynced(syncDelay); + + await checkMarket(vToken.address); + } }); it('should handle liquidateBorrow event', async function () { - await oracle.setPrice(vBtcbToken.address, parseUnits('2500', 18).toString()); - await oracle.setPrice(vBnxToken.address, parseUnits('1500', 18).toString()); + await oracle.setPrice(vBtcbToken.address, parseUnits('30000', 18).toString()); + await oracle.setPrice(vBnxToken.address, parseUnits('.5', 18).toString()); const liquidateAmount = await oracle.getAssetTokenAmount( vBtcbToken.address, - parseUnits('200', 36), + parseUnits('10', 36), ); - await vBnxToken - .connect(liquidator) - .liquidateBorrow(borrower2.address, liquidateAmount.toString(), vBtcbToken.address); + const tx = await vBtcbToken + .connect(liquidator1) + .liquidateBorrow(borrower1.address, liquidateAmount.toString(), vBnxToken.address); await waitForSubgraphToBeSynced(syncDelay); - const { data: updatedAccountVTokenData } = - await subgraphClient.getAccountVTokenByAccountAndMarket( - borrower2.address.toLowerCase(), - vBnxToken.address.toLowerCase(), - ); - const { accountVTokens } = updatedAccountVTokenData!; + checkAccountVToken(borrower1.address, vBnxToken.address, tx); - expect(accountVTokens[0]?.accountBorrowBalanceMantissa).to.be.approximately( - await vBnxToken.callStatic.borrowBalanceCurrent(borrower2.address), - 1e11, - ); + await checkMarket(vBnxToken.address); const { data: { account: accountBorrower }, - } = await subgraphClient.getAccountById(borrower2.address.toLowerCase()); + } = await subgraphClient.getAccountById(borrower1.address.toLowerCase()); expect(accountBorrower.countLiquidated).to.equal(1); const { data: { account: accountLiquidator }, - } = await subgraphClient.getAccountById(liquidator.address.toLowerCase()); + } = await subgraphClient.getAccountById(liquidator1.address.toLowerCase()); expect(accountLiquidator.countLiquidator).to.equal(1); - const { data: dataWithAddedLiquidatorSupplier } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), - ); - const { market: marketWithAddedLiquidatorSupplier } = dataWithAddedLiquidatorSupplier!; - - // Two borrowers and liquidator added as suppliers - expect(marketWithAddedLiquidatorSupplier?.supplierCount).to.equal('5'); + const vBnxMarket = await checkMarket(vBnxToken.address); + // root, one borrower, 2suppliers, and liquidator added as suppliers + expect(vBnxMarket?.supplierCount).to.equal('5'); - const { data: liquidatorAccountVTokenData } = - await subgraphClient.getAccountVTokenByAccountAndMarket( - liquidator.address.toLowerCase(), - vBtcbToken.address.toLowerCase(), - ); - const { accountVTokens: liquidatorAccountVTokens } = liquidatorAccountVTokenData!; - - expect(liquidatorAccountVTokens[0]?.accountVTokenSupplyBalanceMantissa).to.be.approximately( - ethers.BigNumber.from(await vBtcbToken.balanceOf(liquidator.address)), - 1e11, - ); - // @todo Fix collateral error causing this part of the test to fail + checkAccountVToken(liquidator1.address, vBnxToken.address, tx); + // @todo check why repaying exact amount causes an overflow error // let borrowBalanceCurrent = await vBnxToken.borrowBalanceStored(borrower2.address); - // await vBnxToken.connect(borrower2).repayBorrow(borrowBalanceCurrent.sub(1000000)); + // await vBtcbToken.connect(borrower1).repayBorrow(borrowBalanceCurrent.sub(750000000000000)); - // await oracle.setPrice(vBtcbToken.address, parseUnits('1', 18).toString()); - // await oracle.setPrice(vBnxToken.address, parseUnits('1000000', 18).toString()); + // await oracle.setPrice(vBtcbToken.address, parseUnits('100000', 18).toString()); + // await oracle.setPrice(vBnxToken.address, parseUnits('.2', 18).toString()); - // borrowBalanceCurrent = await vBnxToken.callStatic.borrowBalanceCurrent(borrower2.address); + // borrowBalanceCurrent = await vBtcbToken.callStatic.borrowBalanceCurrent(borrower1.address); // // liquidate rest of borrow - // await comptroller.connect(liquidator).liquidateAccount(borrower2.address, [ + // await comptroller.connect(liquidator1).liquidateAccount(borrower1.address, [ // { - // vTokenCollateral: vBtcbToken.address, - // vTokenBorrowed: vBnxToken.address, - // repayAmount: borrowBalanceCurrent.add(18098), + // vTokenCollateral: vBnxToken.address, + // vTokenBorrowed: vBtcbToken.address, + // repayAmount: borrowBalanceCurrent.add(601), // }, // ]); // await waitForSubgraphToBeSynced(syncDelay); - // const { data: bnxMarketData } = await subgraphClient.getMarketById( - // vBnxToken.address.toLowerCase(), + // const { market: vBtcbMarket } = await subgraphClient.getMarketById( + // vBtcbToken.address.toLowerCase(), // ); - // const { market: bnxMarket } = bnxMarketData!; - // expect(bnxMarket.borrowerCount).to.equal('0'); + // expect(vBtcbMarket!.borrowerCount).to.equal('0'); // Reset prices await oracle.setPrice(vBnxToken.address, parseUnits('2', 18).toString()); await oracle.setPrice(vBtcbToken.address, parseUnits('50000', 18).toString()); }); + it('should update the borrower count on the market for full repayment of borrow', async function () { + const tx = await vBnxToken + .connect(borrower2) + .repayBorrow((await vBnxToken.callStatic.borrowBalanceCurrent(borrower2.address)) + 20000n); + + await waitForSubgraphToBeSynced(syncDelay); + + checkAccountVToken(borrower2.address, vBnxToken.address, tx); + + const vBnxMarket = await checkMarket(vBnxToken.address); + expect(vBnxMarket?.borrowerCount).to.equal('0'); + }); + + it('should handle transfer event', async function () { + for (const [supplier, vToken] of [ + [supplier1, vBtcbToken], + [supplier2, vBnxToken], + ] as [SignerWithAddress, Contract][]) { + const supplierBalance = (await vToken.balanceOf(supplier.address)).div(2); + + const tx = await vToken + .connect(supplier) + .transfer(liquidator1.address, supplierBalance.toString()); + + await waitForSubgraphToBeSynced(syncDelay); + + checkAccountVToken(supplier.address, vToken.address, tx); + checkAccountVToken(liquidator1.address, vToken.address, tx); + } + }); + it('handles BadDebtIncreased event', async function () { - // Borrower supplies BNX and borrows BTCB const btcb1000Usd = await oracle.getAssetTokenAmount( vBtcbToken.address, parseUnits('10000', 36), ); - await vBtcbToken.connect(borrower).mint(btcb1000Usd.toString()); - await vBnxToken.connect(borrower).borrow(scaleValue(0.0004446, 18).toString()); + const bnx800Usd = await oracle.getAssetTokenAmount(vBnxToken.address, parseUnits('800', 36)); + // Borrower supplies BNX and borrows BTCB + await vBtcbToken.connect(borrower2).mint(btcb1000Usd.toString()); + await vBnxToken.connect(borrower2).borrow(bnx800Usd.toString()); // set lower price for collateral asset - await oracle.setPrice(vBtcbToken.address, scaleValue(0.00005, 10).toString()); - await oracle.setPrice(vBnxToken.address, scaleValue(160, 18).toString()); + await oracle.setPrice(vBtcbToken.address, parseUnits('50', 10).toString()); + await oracle.setPrice(vBnxToken.address, parseUnits('160', 18).toString()); - const { data: dataBeforeEvent } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); - const { market: marketBeforeUpdate } = dataBeforeEvent!; + const { market: marketBeforeUpdate } = await subgraphClient.getMarketById( + vBnxAddress.toLowerCase(), + ); expect(marketBeforeUpdate?.badDebtMantissa).to.equal('0'); - const tx = await comptroller.connect(liquidator).healAccount(borrower.address); + const tx = await comptroller.connect(liquidator1).healAccount(borrower2.address); await tx.wait(1); await waitForSubgraphToBeSynced(4000); - const { data } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); - const { market } = data!; + const { market } = await subgraphClient.getMarketById(vBnxAddress.toLowerCase()); expect(market?.badDebtMantissa).to.equal((await vBnxToken.badDebt()).toString()); - const { data: accountVTokensData } = await subgraphClient.getAccountVTokens(); - const { accountVTokens } = accountVTokensData!; + const { accountVTokens } = await subgraphClient.getAccountVTokens(); const vBnxAccountTokens = accountVTokens.find( avt => - avt.id.includes(borrower.address.slice(2, 42).toLowerCase()) && + avt.id.includes(borrower2.address.slice(2, 42).toLowerCase()) && avt.market.id.toLowerCase() == vBnxToken.address.toLowerCase(), ); expect(vBnxAccountTokens?.badDebt.length).to.be.equal(1); @@ -360,44 +465,39 @@ describe('VToken events', function () { }); it('handles ReservesAdded event', async function () { - const { data: dataBeforeEvent } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), - ); - const { market: marketBeforeEvent } = dataBeforeEvent!; - expect(marketBeforeEvent?.reservesMantissa).to.be.equals('0'); + const vBtcbMarket = await checkMarket(vBtcbToken.address); const vTokenContract = await ethers.getContractAt('VToken', vBtcbAddress); const tx = await vTokenContract .connect(liquidator2) - .addReserves(scaleValue(0.5, 18).toString()); + .addReserves(parseUnits('0.5', 18).toString()); await tx.wait(1); await waitForSubgraphToBeSynced(syncDelay); - const { data } = await subgraphClient.getMarketById(vBtcbAddress.toLowerCase()); - const { market } = data!; - - expect(market?.reservesMantissa).to.be.equal('500000000000000000'); + const market = await checkMarket(vBtcbToken.address); + // Interest is also accrued + expect(market?.reservesMantissa).to.be.approximately( + BigInt(vBtcbMarket?.reservesMantissa) + BigInt(parseUnits('0.5', 18).toString()), + 1e6, + ); }); it('handles SpreadReservesReduced event', async function () { - const { data: dataBeforeEvent } = await subgraphClient.getMarketById( - vBtcbAddress.toLowerCase(), - ); - const { market: marketBeforeEvent } = dataBeforeEvent!; - - expect(marketBeforeEvent?.reservesMantissa).to.be.equals('500000000000000000'); + const vBtcbMarket = await checkMarket(vBtcbToken.address); const vTokenContract = await ethers.getContractAt('VToken', vBtcbAddress); const tx = await vTokenContract .connect(liquidator2) - .reduceReserves(scaleValue(0.5, 18).toString()); + .reduceReserves(parseUnits('0.5', 18).toString()); tx.wait(1); await waitForSubgraphToBeSynced(4000); - const { data } = await subgraphClient.getMarketById(vBtcbAddress.toLowerCase()); - const { market } = data!; + const market = await checkMarket(vBtcbToken.address); - expect(market?.reservesMantissa).to.be.equal('0'); + expect(market?.reservesMantissa).to.be.approximately( + BigInt(vBtcbMarket?.reservesMantissa) - BigInt(parseUnits('0.5', 18).toString()), + 1e6, + ); }); }); From a714aa89b6dded33fa00c94b3616029b7635e83f Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Mon, 14 Oct 2024 14:16:47 -0300 Subject: [PATCH 8/8] chore: bump version --- subgraphs/isolated-pools/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraphs/isolated-pools/package.json b/subgraphs/isolated-pools/package.json index 4d416094..1662f037 100644 --- a/subgraphs/isolated-pools/package.json +++ b/subgraphs/isolated-pools/package.json @@ -1,6 +1,6 @@ { "name": "isolated-pools-subgraph", - "version": "0.2.0", + "version": "0.3.0", "license": "MIT", "repository": { "url": "https://github.com/VenusProtocol/subgraphs",