From ccda02ba945fb197b79ba65a0982ae5e33185ef3 Mon Sep 17 00:00:00 2001 From: Corey Rice Date: Wed, 1 Nov 2023 16:18:26 -0300 Subject: [PATCH] feat: support v1 and v2 mint and redeem events --- package.json | 1 - subgraphs/venus/package.json | 4 + subgraphs/venus/schema.graphql | 16 +- subgraphs/venus/src/constants/index.ts | 18 +- subgraphs/venus/src/mappings/vToken.ts | 130 ++-- subgraphs/venus/src/operations/create.ts | 45 +- subgraphs/venus/template.yaml | 40 +- subgraphs/venus/tests/VToken/events.ts | 143 ++++- subgraphs/venus/tests/VToken/index.test.ts | 655 +++++++++++---------- yarn.lock | 30 +- 10 files changed, 693 insertions(+), 389 deletions(-) diff --git a/package.json b/package.json index d569a1b1..41b9dfe2 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "@venusprotocol/governance-contracts": "^1.3.0", "@venusprotocol/isolated-pools": "2.1.0-dev.2", "@venusprotocol/oracle": "^1.7.3-dev.1", - "@venusprotocol/venus-protocol": "3.1.0", "assemblyscript": "0.19.23", "chai": "^4.3.6", "eslint": "^8.25.0", diff --git a/subgraphs/venus/package.json b/subgraphs/venus/package.json index bd5c618b..d393c9dc 100644 --- a/subgraphs/venus/package.json +++ b/subgraphs/venus/package.json @@ -23,5 +23,9 @@ "prepare:bsc": "npx mustache config/bsc.json template.yaml > subgraph.yaml && npx mustache config/bsc.json src/constants/config-template > src/constants/config.ts", "test": "graph test", "test:integration": "true" + }, + "dependencies": { + "@venusprotocol/venus-protocol": "3.1.0", + "@venusprotocol/venus-protocol-orig-events": "npm:@venusprotocol/venus-protocol@2.2.1" } } diff --git a/subgraphs/venus/schema.graphql b/subgraphs/venus/schema.graphql index f3990b9d..30270f79 100644 --- a/subgraphs/venus/schema.graphql +++ b/subgraphs/venus/schema.graphql @@ -198,7 +198,7 @@ type MintEvent implements VTokenTransfer @entity { "Transaction hash concatenated with log index" id: ID! "vTokens transferred" - amount: BigDecimal! + amountMantissa: BigInt! "Account that received tokens (minter)" to: Bytes! "Account that sent tokens (VToken contract)" @@ -207,10 +207,10 @@ type MintEvent implements VTokenTransfer @entity { blockNumber: Int! "Block time" blockTime: Int! - "Symbol of the vToken transferred" - vTokenSymbol: String! + "Address of the vToken transferred" + vTokenAddress: Bytes! "Underlying token amount transferred" - underlyingAmount: BigDecimal + underlyingAmountMantissa: BigInt! } """ @@ -221,7 +221,7 @@ type RedeemEvent implements VTokenTransfer @entity { "Transaction hash concatenated with log index" id: ID! "vTokens transferred" - amount: BigDecimal! + amountMantissa: BigInt! "Account that received tokens (VToken contract)" to: Bytes! "Account that sent tokens (redeemer)" @@ -230,10 +230,10 @@ type RedeemEvent implements VTokenTransfer @entity { blockNumber: Int! "Block time" blockTime: Int! - "Symbol of the vToken transferred" - vTokenSymbol: String! + "Address of the vToken transferred" + vTokenAddress: Bytes! "Underlying token amount transferred" - underlyingAmount: BigDecimal + underlyingAmountMantissa: BigInt! } """ diff --git a/subgraphs/venus/src/constants/index.ts b/subgraphs/venus/src/constants/index.ts index 6de4314d..ce808b92 100644 --- a/subgraphs/venus/src/constants/index.ts +++ b/subgraphs/venus/src/constants/index.ts @@ -20,13 +20,13 @@ export const zeroBigInt32 = BigInt.fromString('0'); export const oneBigInt = BigInt.fromString('1'); export const Actions = [ - MINT, - REDEEM, - BORROW, - REPAY, - SEIZE, - LIQUIDATE, - TRANSFER, - ENTER_MARKET, - EXIT_MARKET, + 'MINT', + 'REDEEM', + 'BORROW', + 'REPAY', + 'SEIZE', + 'LIQUIDATE', + 'TRANSFER', + 'ENTER_MARKET', + 'EXIT_MARKET', ]; diff --git a/subgraphs/venus/src/mappings/vToken.ts b/subgraphs/venus/src/mappings/vToken.ts index d4b7e2ff..3fd34077 100644 --- a/subgraphs/venus/src/mappings/vToken.ts +++ b/subgraphs/venus/src/mappings/vToken.ts @@ -7,8 +7,6 @@ import { BorrowEvent, LiquidationEvent, Market, - MintEvent, - RedeemEvent, RepayEvent, TransferEvent, } from '../../generated/schema'; @@ -16,17 +14,29 @@ import { AccrueInterest, Borrow, LiquidateBorrow, - Mint, + MintBehalf as MintBehalfV1, + Mint as MintV1, NewMarketInterestRateModel, NewReserveFactor, - Redeem, + Redeem as RedeemV1, RepayBorrow, Transfer, } from '../../generated/templates/VToken/VToken'; +import { VToken as VTokenContract } from '../../generated/templates/VToken/VToken'; +import { + Mint, + MintBehalf, + Redeem, +} from '../../generated/templates/VTokenUpdatedEvents/VTokenUpdatedEvents'; import { oneBigInt, zeroBigInt32 } from '../constants'; import { nullAddress } from '../constants/addresses'; -import { createAccount } from '../operations/create'; -import { createMarket } from '../operations/create'; +import { + createAccount, + createMarket, + createMintBehalfEvent, + createMintEvent, + createRedeemEvent, +} from '../operations/create'; import { updateCommonVTokenStats } from '../operations/update'; import { updateMarket } from '../operations/update'; import { exponentToBigDecimal } from '../utilities/exponentToBigDecimal'; @@ -50,31 +60,26 @@ export const handleMint = (event: Mint): void => { if (!market) { market = createMarket(event.address.toHexString()); } - let mintId = getTransactionId(event.transaction.hash, event.transactionLogIndex); - const vTokenDecimals = market.vTokenDecimals; + createMintEvent(event); - let vTokenAmount = event.params.mintTokens - .toBigDecimal() - .div(exponentToBigDecimal(vTokenDecimals)) - .truncate(vTokenDecimals); - let underlyingAmount = event.params.mintAmount - .toBigDecimal() - .div(exponentToBigDecimal(market.underlyingDecimals)) - .truncate(market.underlyingDecimals); + if (event.params.mintTokens.equals(event.params.totalSupply)) { + market.supplierCount = market.supplierCount.plus(oneBigInt); + market.save(); + } +}; - let mint = new MintEvent(mintId); - mint.amount = vTokenAmount; - mint.to = event.params.minter; - mint.from = event.address; - mint.blockNumber = event.block.number.toI32(); - mint.blockTime = event.block.timestamp.toI32(); - mint.vTokenSymbol = market.symbol; - mint.underlyingAmount = underlyingAmount; - mint.save(); +export const handleMintBehalf = (event: MintBehalf): void => { + let market = Market.load(event.address.toHexString()); + if (!market) { + market = createMarket(event.address.toHexString()); + } + + createMintBehalfEvent(event); if (event.params.mintTokens.equals(event.params.totalSupply)) { market.supplierCount = market.supplierCount.plus(oneBigInt); + market.save(); } }; @@ -95,30 +100,8 @@ export const handleRedeem = (event: Redeem): void => { if (!market) { market = createMarket(event.address.toHexString()); } - let vTokenDecimals = market.vTokenDecimals; - let redeemID = event.transaction.hash - .toHexString() - .concat('-') - .concat(event.transactionLogIndex.toString()); - let vTokenAmount = event.params.redeemTokens - .toBigDecimal() - .div(exponentToBigDecimal(vTokenDecimals)) - .truncate(vTokenDecimals); - let underlyingAmount = event.params.redeemAmount - .toBigDecimal() - .div(exponentToBigDecimal(market.underlyingDecimals)) - .truncate(market.underlyingDecimals); - - let redeem = new RedeemEvent(redeemID); - redeem.amount = vTokenAmount; - redeem.to = event.address; - redeem.from = event.params.redeemer; - redeem.blockNumber = event.block.number.toI32(); - redeem.blockTime = event.block.timestamp.toI32(); - redeem.vTokenSymbol = market.symbol; - redeem.underlyingAmount = underlyingAmount; - redeem.save(); + createRedeemEvent(event); if (event.params.totalSupply.equals(zeroBigInt32)) { // if the current balance is 0 then the user has withdrawn all their assets from this market @@ -496,3 +479,54 @@ export function handleNewMarketInterestRateModel(event: NewMarketInterestRateMod market.interestRateModelAddress = event.params.newInterestRateModel; market.save(); } + +export function handleMintV1(event: MintV1): void { + let market = Market.load(event.address.toHexString()); + if (!market) { + market = createMarket(event.address.toHexString()); + } + + createMintEvent(event); + + const vTokenContract = VTokenContract.bind(event.address); + let totalSupply = vTokenContract.balanceOf(event.params.minter); + + if (event.params.mintTokens.equals(totalSupply)) { + market.supplierCount = market.supplierCount.plus(oneBigInt); + market.save(); + } +} + +export function handleMintBehalfV1(event: MintBehalfV1): void { + let market = Market.load(event.address.toHexString()); + if (!market) { + market = createMarket(event.address.toHexString()); + } + + createMintBehalfEvent(event); + + const vTokenContract = VTokenContract.bind(event.address); + let totalSupply = vTokenContract.balanceOf(event.params.receiver); + + if (event.params.mintTokens.equals(totalSupply)) { + market.supplierCount = market.supplierCount.plus(oneBigInt); + market.save(); + } +} + +export function handleRedeemV1(event: RedeemV1): void { + let market = Market.load(event.address.toHexString()); + if (!market) { + market = createMarket(event.address.toHexString()); + } + createRedeemEvent(event); + + const vTokenContract = VTokenContract.bind(event.address); + let totalSupply = vTokenContract.balanceOf(event.params.redeemer); + + if (totalSupply.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(); + } +} diff --git a/subgraphs/venus/src/operations/create.ts b/subgraphs/venus/src/operations/create.ts index 422ff0d1..30a0c6f4 100644 --- a/subgraphs/venus/src/operations/create.ts +++ b/subgraphs/venus/src/operations/create.ts @@ -1,12 +1,13 @@ import { Address, BigDecimal, BigInt, log } from '@graphprotocol/graph-ts'; -import { Account, AccountVToken, Market } from '../../generated/schema'; +import { Account, AccountVToken, Market, MintEvent, RedeemEvent } from '../../generated/schema'; import { BEP20 } from '../../generated/templates/VToken/BEP20'; import { VBep20Storage } from '../../generated/templates/VToken/VBep20Storage'; import { VToken } from '../../generated/templates/VToken/VToken'; import { zeroBigDecimal, zeroBigInt32 } from '../constants'; import { nullAddress, vBnbAddress } from '../constants/addresses'; import { getUnderlyingPrice } from '../utilities/getUnderlyingPrice'; +import { getTransactionId } from '../utilities/ids'; export function createAccountVToken( accountVTokenId: string, @@ -106,3 +107,45 @@ export function createMarket(marketAddress: string): Market { return market; } + +export function createMintEvent(event: E): void { + const mintId = getTransactionId(event.transaction.hash, event.transactionLogIndex); + + const mint = new MintEvent(mintId); + mint.amountMantissa = event.params.mintTokens; + mint.to = event.params.minter; + mint.from = event.address; + mint.blockNumber = event.block.number.toI32(); + mint.blockTime = event.block.timestamp.toI32(); + mint.vTokenAddress = event.address; + mint.underlyingAmountMantissa = event.params.mintAmount; + mint.save(); +} + +export function createMintBehalfEvent(event: E): void { + const mintId = getTransactionId(event.transaction.hash, event.transactionLogIndex); + + const mint = new MintEvent(mintId); + mint.amountMantissa = event.params.mintTokens; + mint.to = event.params.receiver; + mint.from = event.address; + mint.blockNumber = event.block.number.toI32(); + mint.blockTime = event.block.timestamp.toI32(); + mint.vTokenAddress = event.address; + mint.underlyingAmountMantissa = event.params.mintAmount; + mint.save(); +} + +export function createRedeemEvent(event: E): void { + const redeemId = getTransactionId(event.transaction.hash, event.transactionLogIndex); + + const redeem = new RedeemEvent(redeemId); + redeem.amountMantissa = event.params.redeemTokens; + redeem.to = event.address; + redeem.from = event.params.redeemer; + redeem.blockNumber = event.block.number.toI32(); + redeem.blockTime = event.block.timestamp.toI32(); + redeem.vTokenAddress = event.address; + redeem.underlyingAmountMantissa = event.params.redeemAmount; + redeem.save(); +} diff --git a/subgraphs/venus/template.yaml b/subgraphs/venus/template.yaml index 001f0d8c..58c94338 100644 --- a/subgraphs/venus/template.yaml +++ b/subgraphs/venus/template.yaml @@ -64,9 +64,9 @@ templates: - VTokenInfo abis: - name: VToken - file: ../../node_modules/@venusprotocol/venus-protocol/artifacts/contracts/Tokens/VTokens/VBep20.sol/VBep20.json + file: ../../node_modules/@venusprotocol/venus-protocol-orig-events/artifacts/contracts/Tokens/VTokens/VBep20.sol/VBep20.json - name: VBep20Storage - file: ../../node_modules/@venusprotocol/venus-protocol/artifacts/contracts/Tokens/VTokens/VTokenInterfaces.sol/VBep20Storage.json + file: ../../node_modules/@venusprotocol/venus-protocol-orig-events/artifacts/contracts/Tokens/VTokens/VTokenInterfaces.sol/VBep20Storage.json - name: PriceOracle file: ../../node_modules/@venusprotocol/oracle/artifacts/contracts/ResilientOracle.sol/ResilientOracle.json - name: BEP20 @@ -74,10 +74,12 @@ templates: - name: Comptroller file: ../../node_modules/@venusprotocol/venus-protocol/artifacts/contracts/Comptroller/Comptroller.sol/Comptroller.json eventHandlers: - - event: Mint(address,uint256,uint256,uint256) - handler: handleMint - - event: Redeem(address,uint256,uint256,uint256) - handler: handleRedeem + - event: Mint(address,uint256,uint256) + handler: handleMintV1 + - event: MintBehalf(address,address,uint256,uint256) + handler: handleMintV1 + - event: Redeem(address,uint256,uint256) + handler: handleRedeemV1 - event: Borrow(address,uint256,uint256,uint256) handler: handleBorrow - event: RepayBorrow(address,address,uint256,uint256,uint256) @@ -92,3 +94,29 @@ templates: handler: handleTransfer - event: NewMarketInterestRateModel(address,address) handler: handleNewMarketInterestRateModel + - name: VTokenUpdatedEvents + kind: ethereum/contract + network: {{ network }} + source: + abi: VTokenUpdatedEvents + mapping: + kind: ethereum/events + apiVersion: 0.0.5 + language: wasm/assemblyscript + file: ./src/mappings/vToken.ts + entities: + - User + - Market + - VTokenInfo + abis: + - name: VTokenUpdatedEvents + file: ../../node_modules/@venusprotocol/venus-protocol/artifacts/contracts/Tokens/VTokens/VBep20.sol/VBep20.json + - name: VBep20Storage + file: ../../node_modules/@venusprotocol/venus-protocol/artifacts/contracts/Tokens/VTokens/VTokenInterfaces.sol/VBep20Storage.json + eventHandlers: + - event: Mint(address,uint256,uint256,uint256) + handler: handleMint + - event: MintBehalf(address,address,uint256,uint256,uint256) + handler: handleMint + - event: Redeem(address,uint256,uint256,uint256) + handler: handleRedeem \ No newline at end of file diff --git a/subgraphs/venus/tests/VToken/events.ts b/subgraphs/venus/tests/VToken/events.ts index fe09d8af..d02511ae 100644 --- a/subgraphs/venus/tests/VToken/events.ts +++ b/subgraphs/venus/tests/VToken/events.ts @@ -7,14 +7,20 @@ import { Approval as ApprovalEvent, Borrow as BorrowEvent, LiquidateBorrow as LiquidateBorrowEvent, - Mint as MintEvent, + MintBehalf as MintBehalfEventV1, + Mint as MintEventV1, NewComptroller as NewComptrollerEvent, NewMarketInterestRateModel as NewMarketInterestRateModelEvent, NewReserveFactor as NewReserveFactorEvent, - Redeem as RedeemEvent, + Redeem as RedeemEventV1, RepayBorrow as RepayBorrowEvent, Transfer as TransferEvent, } from '../../generated/templates/VToken/VToken'; +import { + MintBehalf as MintBehalfEvent, + Mint as MintEvent, + Redeem as RedeemEvent, +} from '../../generated/templates/VTokenUpdatedEvents/VTokenUpdatedEvents'; export const createMarketListedEvent = (vTokenAddress: Address): MarketListedEvent => { const event = changetype(newMockEvent()); @@ -377,3 +383,136 @@ export const createNewComptrollerEvent = ( return event; }; + +export const createMintEventV1 = ( + vTokenAddress: Address, + minterAddress: Address, + mintAmount: BigInt, + mintTokens: BigInt, +): MintEventV1 => { + const event = changetype(newMockEvent()); + event.address = vTokenAddress; + event.parameters = []; + + const minterParam = new ethereum.EventParam('minter', ethereum.Value.fromAddress(minterAddress)); + event.parameters.push(minterParam); + + const mintAmountParam = new ethereum.EventParam( + 'mintAmount', + ethereum.Value.fromUnsignedBigInt(mintAmount), + ); + event.parameters.push(mintAmountParam); + + const mintTokensParam = new ethereum.EventParam( + 'mintTokens', + ethereum.Value.fromUnsignedBigInt(mintTokens), + ); + event.parameters.push(mintTokensParam); + + return event; +}; +export const createMintBehalfEvent = ( + vTokenAddress: Address, + payerAddress: Address, + receiverAddress: Address, + mintAmount: BigInt, + mintTokens: BigInt, + totalSupply: BigInt, +): MintBehalfEvent => { + const event = changetype(newMockEvent()); + event.address = vTokenAddress; + event.parameters = []; + + const payerParam = new ethereum.EventParam('minter', ethereum.Value.fromAddress(payerAddress)); + event.parameters.push(payerParam); + + const receiverParam = new ethereum.EventParam( + 'minter', + ethereum.Value.fromAddress(receiverAddress), + ); + event.parameters.push(receiverParam); + + const mintAmountParam = new ethereum.EventParam( + 'mintAmount', + ethereum.Value.fromUnsignedBigInt(mintAmount), + ); + event.parameters.push(mintAmountParam); + + const mintTokensParam = new ethereum.EventParam( + 'mintTokens', + ethereum.Value.fromUnsignedBigInt(mintTokens), + ); + event.parameters.push(mintTokensParam); + + const totalSupplyParam = new ethereum.EventParam( + 'totalSupply', + ethereum.Value.fromUnsignedBigInt(totalSupply), + ); + event.parameters.push(totalSupplyParam); + + return event; +}; +export const createMintBehalfEventV1 = ( + vTokenAddress: Address, + payerAddress: Address, + receiverAddress: Address, + mintAmount: BigInt, + mintTokens: BigInt, +): MintBehalfEventV1 => { + const event = changetype(newMockEvent()); + event.address = vTokenAddress; + event.parameters = []; + + const payerParam = new ethereum.EventParam('minter', ethereum.Value.fromAddress(payerAddress)); + event.parameters.push(payerParam); + + const receiverParam = new ethereum.EventParam( + 'minter', + ethereum.Value.fromAddress(receiverAddress), + ); + event.parameters.push(receiverParam); + + const mintAmountParam = new ethereum.EventParam( + 'mintAmount', + ethereum.Value.fromUnsignedBigInt(mintAmount), + ); + event.parameters.push(mintAmountParam); + + const mintTokensParam = new ethereum.EventParam( + 'mintTokens', + ethereum.Value.fromUnsignedBigInt(mintTokens), + ); + event.parameters.push(mintTokensParam); + return event; +}; + +export const createRedeemEventV1 = ( + vTokenAddress: Address, + redeemerAddress: Address, + redeemAmount: BigInt, + redeemTokens: BigInt, +): RedeemEventV1 => { + const event = changetype(newMockEvent()); + event.address = vTokenAddress; + event.parameters = []; + + const redeemerParam = new ethereum.EventParam( + 'redeemer', + ethereum.Value.fromAddress(redeemerAddress), + ); + event.parameters.push(redeemerParam); + + const redeemAmountParam = new ethereum.EventParam( + 'redeemAmount', + ethereum.Value.fromUnsignedBigInt(redeemAmount), + ); + event.parameters.push(redeemAmountParam); + + const redeemTokensParam = new ethereum.EventParam( + 'redeemTokens', + ethereum.Value.fromUnsignedBigInt(redeemTokens), + ); + event.parameters.push(redeemTokensParam); + + return event; +}; diff --git a/subgraphs/venus/tests/VToken/index.test.ts b/subgraphs/venus/tests/VToken/index.test.ts index 3fc099a1..0dc3b0e7 100644 --- a/subgraphs/venus/tests/VToken/index.test.ts +++ b/subgraphs/venus/tests/VToken/index.test.ts @@ -18,9 +18,13 @@ import { handleBorrow, handleLiquidateBorrow, handleMint, + handleMintBehalf, + handleMintBehalfV1, + handleMintV1, handleNewMarketInterestRateModel, handleNewReserveFactor, handleRedeem, + handleRedeemV1, handleRepayBorrow, handleTransfer, } from '../../src/mappings/vToken'; @@ -31,10 +35,14 @@ import { createBorrowEvent, createLiquidateBorrowEvent, createMarketListedEvent, + createMintBehalfEvent, + createMintBehalfEventV1, createMintEvent, + createMintEventV1, createNewMarketInterestRateModelEvent, createNewReserveFactorEvent, createRedeemEvent, + createRedeemEventV1, createRepayBorrowEvent, createTransferEvent, } from './events'; @@ -44,6 +52,8 @@ import { createMarketMock, createPriceOracleMock, createVBep20AndUnderlyingMock const tokenAddress = Address.fromString('0x0000000000000000000000000000000000000b0b'); const user1Address = Address.fromString('0x0000000000000000000000000000000000000101'); const user2Address = Address.fromString('0x0000000000000000000000000000000000000202'); +const user3Address = Address.fromString('0x0000000000000000000000000000000000000303'); +const user4Address = Address.fromString('0x0000000000000000000000000000000000000404'); const aaaTokenAddress = Address.fromString('0x0000000000000000000000000000000000000aaa'); const interestRateModelAddress = Address.fromString('0x594942C0e62eC577889777424CD367545C796A74'); @@ -268,313 +278,344 @@ describe('VToken', () => { if (!market) { return; } + }); + + test('registers accrue interest event', () => { + /** Constants */ + const cashPrior = BigInt.fromString('1246205398726345'); + const interestAccumulated = BigInt.fromI32(26454); + const borrowIndex = BigInt.fromI32(1); + const totalBorrows = BigInt.fromString('62197468301'); + + /** Setup test */ + const accrueInterestEvent = createAccrueInterestEvent( + aaaTokenAddress, + cashPrior, + interestAccumulated, + borrowIndex, + totalBorrows, + ); + + /** Fire Event */ + handleAccrueInterest(accrueInterestEvent); + + const assertMarketDocument = (key: string, value: string): void => { + assert.fieldEquals('Market', aaaTokenAddress.toHexString(), key, value); + }; + + assertMarketDocument('accrualBlockNumber', '999'); + assertMarketDocument('blockTimestamp', accrueInterestEvent.block.timestamp.toString()); + assertMarketDocument('exchangeRateMantissa', '365045823500000000000000'); + assertMarketDocument('borrowIndexMantissa', '300000000000000000000'); + assertMarketDocument('reservesMantissa', '5128924555022289393'); + assertMarketDocument('totalBorrowsMantissa', '2641234234636158123'); + assertMarketDocument('cashMantissa', '1418171344423412457'); + assertMarketDocument('borrowRateMantissa', '12678493'); + assertMarketDocument('supplyRateMantissa', '12678493'); + }); + + test('registers new reserve factor', () => { + const oldReserveFactor = BigInt.fromI64(12462053079875); + const newReserveFactor = BigInt.fromI64(37035970026454); + const reserveFactorEvent = createNewReserveFactorEvent( + aaaTokenAddress, + oldReserveFactor, + newReserveFactor, + ); + + handleNewReserveFactor(reserveFactorEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'id', aaaTokenAddress.toHexString()); + assert.fieldEquals( + 'Market', + aaaTokenAddress.toHex(), + 'reserveFactor', + newReserveFactor.toString(), + ); + }); + + test('registers transfer from event', () => { + /** Constants */ + const from = user1Address; // 101 + const to = aaaTokenAddress; + const amount = BigInt.fromString('146205398726345'); + const balanceOf = BigInt.fromString('262059874253345'); + + /** Setup test */ + const transferEvent = createTransferEvent(aaaTokenAddress, from, to, amount); + createMockedFunction( + aaaTokenAddress, + 'getAccountSnapshot', + 'getAccountSnapshot(address):(uint256,uint256,uint256,uint256)', + ) + .withArgs([ethereum.Value.fromAddress(from)]) + .returns([ + ethereum.Value.fromSignedBigInt(zeroBigInt32), + ethereum.Value.fromSignedBigInt(balanceOf), + ethereum.Value.fromSignedBigInt(zeroBigInt32), + ethereum.Value.fromSignedBigInt(oneBigInt), + ]); + + /** Fire Event */ + handleTransfer(transferEvent); + + const accountVTokenId = getAccountVTokenId(aaaTokenAddress, from); + + /** AccountVToken */ + assert.fieldEquals( + 'AccountVToken', + accountVTokenId, + 'accrualBlockNumber', + transferEvent.block.number.toString(), + ); + + assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); + + assert.fieldEquals( + 'AccountVToken', + accountVTokenId, + 'totalUnderlyingRedeemedMantissa', + '53371670178204461670107500000000000000', + ); + }); + + test('registers transfer to event', () => { + /** Constants */ + const amount = BigInt.fromString('5246205398726345'); + const from = aaaTokenAddress; + const to = user2Address; + const balanceOf = BigInt.fromString('262059874253345'); + + /** Setup test */ + const transferEvent = createTransferEvent(aaaTokenAddress, from, to, amount); + createAccountVTokenBalanceOfMock( + aaaTokenAddress, + aaaTokenAddress, // something is wrong with this test + balanceOf, + ); + createMockedFunction( + aaaTokenAddress, + 'getAccountSnapshot', + 'getAccountSnapshot(address):(uint256,uint256,uint256,uint256)', + ) + .withArgs([ethereum.Value.fromAddress(to)]) + .returns([ + ethereum.Value.fromSignedBigInt(zeroBigInt32), + ethereum.Value.fromSignedBigInt(balanceOf), + ethereum.Value.fromSignedBigInt(zeroBigInt32), + ethereum.Value.fromSignedBigInt(oneBigInt), + ]); + + /** Fire Event */ + handleTransfer(transferEvent); + + const accountVTokenId = getAccountVTokenId(aaaTokenAddress, to); + + /** AccountVToken */ + assert.fieldEquals( + 'AccountVToken', + accountVTokenId, + 'accrualBlockNumber', + transferEvent.block.number.toString(), + ); + + assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); + }); + + test('registers new interest rate model', () => { + const oldInterestRateModel = Address.fromString('0x0000000000000000000000000000000000000e0e'); + const newInterestRateModel = Address.fromString('0x0000000000000000000000000000000000000f0f'); + const newMarketInterestRateModelEvent = createNewMarketInterestRateModelEvent( + aaaTokenAddress, + oldInterestRateModel, + newInterestRateModel, + ); + + handleNewMarketInterestRateModel(newMarketInterestRateModelEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'id', aaaTokenAddress.toHexString()); + assert.fieldEquals( + 'Market', + aaaTokenAddress.toHex(), + 'interestRateModelAddress', + newInterestRateModel.toHexString(), + ); + }); + + test('registers increase and decrease in the market supplier count', () => { + const market = getMarket(aaaTokenAddress); + assert.assertNotNull(market); + if (!market) { + return; + } + assert.fieldEquals('Market', market.id, 'supplierCount', '0'); + + const actualMintAmount = BigInt.fromI64(12); + const halfActualMintAmount = actualMintAmount.div(BigInt.fromI64(2)); + const mintTokens = BigInt.fromI64(10); + const accountBalance = mintTokens; + const halfMintTokens = mintTokens.div(BigInt.fromI64(2)); + + const supplier01 = user1Address; + const mintEvent = createMintEvent( + aaaTokenAddress, + supplier01, + actualMintAmount, + mintTokens, + accountBalance, + ); + + handleMint(mintEvent); + + assert.fieldEquals('Market', market.id, 'supplierCount', '1'); + + const supplier02 = user2Address; + const mintEventV1 = createMintEventV1( + aaaTokenAddress, + supplier02, + actualMintAmount, + mintTokens, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier02, mintTokens); + + handleMintV1(mintEventV1); + assert.fieldEquals('Market', market.id, 'supplierCount', '2'); + + const supplier03 = user3Address; + const mintBehalfEvent = createMintBehalfEvent( + aaaTokenAddress, + supplier01, + supplier03, + actualMintAmount, + mintTokens, + accountBalance, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier03, mintTokens); + + handleMintBehalf(mintBehalfEvent); + assert.fieldEquals('Market', market.id, 'supplierCount', '3'); + + const supplier04 = user4Address; + const mintBehalfEventV1 = createMintBehalfEventV1( + aaaTokenAddress, + supplier01, + supplier04, + actualMintAmount, + mintTokens, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier04, mintTokens); + + handleMintBehalfV1(mintBehalfEventV1); + assert.fieldEquals('Market', market.id, 'supplierCount', '4'); + + let redeemEvent = createRedeemEvent( + aaaTokenAddress, + supplier02, + actualMintAmount, + mintTokens, + zeroBigInt32, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier02, zeroBigInt32); + + handleRedeem(redeemEvent); + assert.fieldEquals('Market', market.id, 'supplierCount', '3'); + + const redeemEventV1 = createRedeemEventV1( + aaaTokenAddress, + supplier01, + halfActualMintAmount, + halfMintTokens, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier01, halfMintTokens); + + handleRedeemV1(redeemEventV1); + assert.fieldEquals('Market', market.id, 'supplierCount', '3'); + + redeemEvent = createRedeemEvent( + aaaTokenAddress, + supplier01, + halfActualMintAmount, + halfMintTokens, + zeroBigInt32, + ); + createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier01, zeroBigInt32); + + handleRedeem(redeemEvent); + assert.fieldEquals('Market', market.id, 'supplierCount', '2'); + }); + + test('registers increase and decrease in the market borrower count', () => { + const market = getMarket(aaaTokenAddress); + assert.assertNotNull(market); + if (!market) { + return; + } + assert.fieldEquals('Market', market.id, 'borrowerCount', '0'); + + const borrowAmount = BigInt.fromI64(10); + const halfBorrowAmountTokens = borrowAmount.div(BigInt.fromI64(2)); + + const borrower01 = user1Address; + let borrowEvent = createBorrowEvent( + aaaTokenAddress, + borrower01, + borrowAmount, + borrowAmount, + borrowAmount, + ); + + handleBorrow(borrowEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); + + const borrower02 = user2Address; + borrowEvent = createBorrowEvent( + aaaTokenAddress, + borrower02, + borrowAmount, + borrowAmount, + borrowAmount, + ); + + handleBorrow(borrowEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '2'); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '2'); + + let repayEvent = createRepayBorrowEvent( + aaaTokenAddress, + borrower02, + borrower02, + borrowAmount, + zeroBigInt32, + zeroBigInt32, + ); + + handleRepayBorrow(repayEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); + + repayEvent = createRepayBorrowEvent( + aaaTokenAddress, + borrower01, + borrower01, + halfBorrowAmountTokens, + halfBorrowAmountTokens, + halfBorrowAmountTokens, + ); + + handleRepayBorrow(repayEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); + + repayEvent = createRepayBorrowEvent( + aaaTokenAddress, + borrower01, + borrower01, + halfBorrowAmountTokens, + oneBigInt, + oneBigInt, + ); - test('registers accrue interest event', () => { - /** Constants */ - const cashPrior = BigInt.fromString('1246205398726345'); - const interestAccumulated = BigInt.fromI32(26454); - const borrowIndex = BigInt.fromI32(1); - const totalBorrows = BigInt.fromString('62197468301'); - - /** Setup test */ - const accrueInterestEvent = createAccrueInterestEvent( - aaaTokenAddress, - cashPrior, - interestAccumulated, - borrowIndex, - totalBorrows, - ); - - /** Fire Event */ - handleAccrueInterest(accrueInterestEvent); - - const assertMarketDocument = (key: string, value: string): void => { - assert.fieldEquals('Market', aaaTokenAddress.toHexString(), key, value); - }; - - assertMarketDocument('accrualBlockNumber', '999'); - assertMarketDocument('blockTimestamp', accrueInterestEvent.block.timestamp.toString()); - assertMarketDocument('exchangeRateMantissa', '365045823500000000000000'); - assertMarketDocument('borrowIndexMantissa', '300000000000000000000'); - assertMarketDocument('reservesMantissa', '5128924555022289393'); - assertMarketDocument('totalBorrowsMantissa', '2641234234636158123'); - assertMarketDocument('cashMantissa', '1418171344423412457'); - assertMarketDocument('borrowRateMantissa', '12678493'); - assertMarketDocument('supplyRateMantissa', '12678493'); - }); - - test('registers new reserve factor', () => { - const oldReserveFactor = BigInt.fromI64(12462053079875); - const newReserveFactor = BigInt.fromI64(37035970026454); - const reserveFactorEvent = createNewReserveFactorEvent( - aaaTokenAddress, - oldReserveFactor, - newReserveFactor, - ); - - handleNewReserveFactor(reserveFactorEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'id', aaaTokenAddress.toHexString()); - assert.fieldEquals( - 'Market', - aaaTokenAddress.toHex(), - 'reserveFactor', - newReserveFactor.toString(), - ); - }); - - test('registers transfer from event', () => { - /** Constants */ - const from = user1Address; // 101 - const to = aaaTokenAddress; - const amount = BigInt.fromString('146205398726345'); - const balanceOf = BigInt.fromString('262059874253345'); - - /** Setup test */ - const transferEvent = createTransferEvent(aaaTokenAddress, from, to, amount); - createMockedFunction( - aaaTokenAddress, - 'getAccountSnapshot', - 'getAccountSnapshot(address):(uint256,uint256,uint256,uint256)', - ) - .withArgs([ethereum.Value.fromAddress(from)]) - .returns([ - ethereum.Value.fromSignedBigInt(zeroBigInt32), - ethereum.Value.fromSignedBigInt(balanceOf), - ethereum.Value.fromSignedBigInt(zeroBigInt32), - ethereum.Value.fromSignedBigInt(oneBigInt), - ]); - - /** Fire Event */ - handleTransfer(transferEvent); - - const accountVTokenId = getAccountVTokenId(aaaTokenAddress, from); - - /** AccountVToken */ - assert.fieldEquals( - 'AccountVToken', - accountVTokenId, - 'accrualBlockNumber', - transferEvent.block.number.toString(), - ); - - assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); - - assert.fieldEquals( - 'AccountVToken', - accountVTokenId, - 'totalUnderlyingRedeemedMantissa', - '53371670178204461670107500000000000000', - ); - }); - - test('registers transfer to event', () => { - /** Constants */ - const amount = BigInt.fromString('5246205398726345'); - const from = aaaTokenAddress; - const to = user2Address; - const balanceOf = BigInt.fromString('262059874253345'); - - /** Setup test */ - const transferEvent = createTransferEvent(aaaTokenAddress, from, to, amount); - createMockedFunction( - aaaTokenAddress, - 'getAccountSnapshot', - 'getAccountSnapshot(address):(uint256,uint256,uint256,uint256)', - ) - .withArgs([ethereum.Value.fromAddress(to)]) - .returns([ - ethereum.Value.fromSignedBigInt(zeroBigInt32), - ethereum.Value.fromSignedBigInt(balanceOf), - ethereum.Value.fromSignedBigInt(zeroBigInt32), - ethereum.Value.fromSignedBigInt(oneBigInt), - ]); - - /** Fire Event */ - handleTransfer(transferEvent); - - const accountVTokenId = getAccountVTokenId(aaaTokenAddress, to); - - /** AccountVToken */ - assert.fieldEquals( - 'AccountVToken', - accountVTokenId, - 'accrualBlockNumber', - transferEvent.block.number.toString(), - ); - - assert.fieldEquals('AccountVToken', accountVTokenId, 'accountBorrowIndexMantissa', '0'); - }); - - test('registers new interest rate model', () => { - const oldInterestRateModel = Address.fromString('0x0000000000000000000000000000000000000e0e'); - const newInterestRateModel = Address.fromString('0x0000000000000000000000000000000000000f0f'); - const newMarketInterestRateModelEvent = createNewMarketInterestRateModelEvent( - aaaTokenAddress, - oldInterestRateModel, - newInterestRateModel, - ); - - handleNewMarketInterestRateModel(newMarketInterestRateModelEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'id', aaaTokenAddress.toHexString()); - assert.fieldEquals( - 'Market', - aaaTokenAddress.toHex(), - 'interestRateModelAddress', - newInterestRateModel.toHexString(), - ); - }); - - test('registers increase and decrease in the market supplier count', () => { - const market = getMarket(aaaTokenAddress); - assert.assertNotNull(market); - if (!market) { - return; - } - - const actualMintAmount = BigInt.fromI64(12); - const halfActualMintAmount = actualMintAmount.div(BigInt.fromI64(2)); - const mintTokens = BigInt.fromI64(10); - const accountBalance = mintTokens; - const halfMintTokens = mintTokens.div(BigInt.fromI64(2)); - - const supplier01 = user1Address; - let mintEvent = createMintEvent( - aaaTokenAddress, - supplier01, - actualMintAmount, - mintTokens, - accountBalance, - ); - createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier01, mintTokens); - - handleMint(mintEvent); - - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'supplierCount', '2'); - - const supplier02 = user2Address; - mintEvent = createMintEvent( - aaaTokenAddress, - supplier02, - actualMintAmount, - mintTokens, - accountBalance, - ); - createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier02, mintTokens); - - handleMint(mintEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'supplierCount', '3'); - - let redeemEvent = createRedeemEvent( - aaaTokenAddress, - supplier02, - actualMintAmount, - mintTokens, - zeroBigInt32, - ); - createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier02, zeroBigInt32); - - handleRedeem(redeemEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'supplierCount', '2'); - - redeemEvent = createRedeemEvent( - aaaTokenAddress, - supplier01, - halfActualMintAmount, - halfMintTokens, - halfMintTokens, - ); - createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier01, halfMintTokens); - - handleRedeem(redeemEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'supplierCount', '1'); - - redeemEvent = createRedeemEvent( - aaaTokenAddress, - supplier01, - halfActualMintAmount, - halfMintTokens, - zeroBigInt32, - ); - createAccountVTokenBalanceOfMock(aaaTokenAddress, supplier01, zeroBigInt32); - - handleRedeem(redeemEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'supplierCount', '0'); - }); - - test('registers increase and decrease in the market borrower count', () => { - const market = getMarket(aaaTokenAddress); - assert.assertNotNull(market); - if (!market) { - return; - } - - const borrowAmount = BigInt.fromI64(10); - const halfBorrowAmountTokens = borrowAmount.div(BigInt.fromI64(2)); - - const borrower01 = user1Address; - let borrowEvent = createBorrowEvent( - aaaTokenAddress, - borrower01, - borrowAmount, - borrowAmount, - borrowAmount, - ); - - handleBorrow(borrowEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '2'); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '2'); - - const borrower02 = user2Address; - borrowEvent = createBorrowEvent( - aaaTokenAddress, - borrower02, - borrowAmount, - borrowAmount, - borrowAmount, - ); - - handleBorrow(borrowEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '3'); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '3'); - - let repayEvent = createRepayBorrowEvent( - aaaTokenAddress, - borrower02, - borrower02, - borrowAmount, - zeroBigInt32, - zeroBigInt32, - ); - - handleRepayBorrow(repayEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '2'); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '2'); - - repayEvent = createRepayBorrowEvent( - aaaTokenAddress, - borrower01, - borrower01, - halfBorrowAmountTokens, - halfBorrowAmountTokens, - halfBorrowAmountTokens, - ); - - handleRepayBorrow(repayEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); - - repayEvent = createRepayBorrowEvent( - aaaTokenAddress, - borrower01, - borrower01, - halfBorrowAmountTokens, - oneBigInt, - oneBigInt, - ); - - handleRepayBorrow(repayEvent); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); - assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); - }); + handleRepayBorrow(repayEvent); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCount', '1'); + assert.fieldEquals('Market', aaaTokenAddress.toHex(), 'borrowerCountAdjusted', '1'); }); }); diff --git a/yarn.lock b/yarn.lock index ddda6f48..9baeb27e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4309,6 +4309,20 @@ __metadata: languageName: node linkType: hard +"@venusprotocol/venus-protocol-orig-events@npm:@venusprotocol/venus-protocol@2.2.1": + version: 2.2.1 + resolution: "@venusprotocol/venus-protocol@npm:2.2.1" + dependencies: + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.0 + dotenv: ^16.0.1 + module-alias: ^2.2.2 + peerDependencies: + hardhat: ^2.10.1 + checksum: 797c6f141af571d6448a70c607dea92b8db24bc5b31c97ae13c67ae411873718b66394b37c3abf86154107a3ff5299e717864f0ea40e4bf5ed9c12ea286b0cea + languageName: node + linkType: hard + "@venusprotocol/venus-protocol@npm:0.7.0": version: 0.7.0 resolution: "@venusprotocol/venus-protocol@npm:0.7.0" @@ -6534,6 +6548,12 @@ __metadata: languageName: node linkType: hard +"core-pool-abis@workspace:packages/core-pool-abis": + version: 0.0.0-use.local + resolution: "core-pool-abis@workspace:packages/core-pool-abis" + languageName: unknown + linkType: soft + "core-util-is@npm:1.0.2": version: 1.0.2 resolution: "core-util-is@npm:1.0.2" @@ -14860,7 +14880,6 @@ __metadata: "@venusprotocol/governance-contracts": ^1.3.0 "@venusprotocol/isolated-pools": 2.1.0-dev.2 "@venusprotocol/oracle": ^1.7.3-dev.1 - "@venusprotocol/venus-protocol": 3.1.0 assemblyscript: 0.19.23 chai: ^4.3.6 eslint: ^8.25.0 @@ -15942,12 +15961,6 @@ __metadata: languageName: node linkType: hard -"venus-cross-chain-governance-subgraph@workspace:subgraphs/cross-chain-governance": - version: 0.0.0-use.local - resolution: "venus-cross-chain-governance-subgraph@workspace:subgraphs/cross-chain-governance" - languageName: unknown - linkType: soft - "venus-governance-abis@workspace:packages/venus-governance-abis": version: 0.0.0-use.local resolution: "venus-governance-abis@workspace:packages/venus-governance-abis" @@ -15975,6 +15988,9 @@ __metadata: "venus-subgraph@workspace:subgraphs/venus": version: 0.0.0-use.local resolution: "venus-subgraph@workspace:subgraphs/venus" + dependencies: + "@venusprotocol/venus-protocol": 3.1.0 + "@venusprotocol/venus-protocol-orig-events": "npm:@venusprotocol/venus-protocol@2.2.1" languageName: unknown linkType: soft