From 647c0cd40ba07c1d758d078ed963739870233e4a Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 7 Dec 2023 17:49:14 -0500 Subject: [PATCH] wip rc9 updates --- .gitignore | 3 ++- copy-abis.sh | 10 ++++++++-- schema.graphql | 3 +++ src/utils/pool/liquidation.ts | 25 ++++++++++++++++++++----- src/utils/pool/loan.ts | 1 + tests/erc-20-pool.test.ts | 27 +++++++++++++++++++++++---- tests/erc-721-pool.test.ts | 16 +++++++++++++--- tests/utils/mock-contract-calls.ts | 22 +++++++++++++--------- 8 files changed, 83 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index e85605d..65d1ea4 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,5 @@ data/ # matchstick test files tests/.bin/ -tests/.latest.json \ No newline at end of file +tests/.latest.json +tests/.docker/ \ No newline at end of file diff --git a/copy-abis.sh b/copy-abis.sh index d0db902..5475459 100755 --- a/copy-abis.sh +++ b/copy-abis.sh @@ -11,9 +11,15 @@ rm abis/* jq '.abi' "${ABI_PATH_CONTRACTS}/ERC20.sol/ERC20.json" > abis/ERC20.json jq '.abi' "${ABI_PATH_CONTRACTS}/ERC20Pool.sol/ERC20Pool.json" > abis/ERC20Pool.json jq '.abi' "${ABI_PATH_CONTRACTS}/ERC20PoolFactory.sol/ERC20PoolFactory.json" > abis/ERC20PoolFactory.json +jq '.abi' "${ABI_PATH_CONTRACTS}/ERC721.sol/ERC721.json" > abis/ERC721.json +jq '.abi' "${ABI_PATH_CONTRACTS}/ERC721Pool.sol/ERC721Pool.json" > abis/ERC721Pool.json jq '.abi' "${ABI_PATH_CONTRACTS}/ERC721PoolFactory.sol/ERC721PoolFactory.json" > abis/ERC721PoolFactory.json jq '.abi' "${ABI_PATH_CONTRACTS}/PoolInfoUtils.sol/PoolInfoUtils.json" > abis/PoolInfoUtils.json +jq '.abi' "${ABI_PATH_CONTRACTS}/PoolInfoUtilsMulticall.sol/PoolInfoUtilsMulticall.json" > abis/PoolInfoUtilsMulticall.json + jq '.abi' "${ABI_PATH_CONTRACTS}/PositionManager.sol/PositionManager.json" > abis/PositionManager.json -jq '.abi' "${ABI_PATH_CONTRACTS}/RewardsManager.sol/RewardsManager.json" > abis/RewardsManager.json -jq '.abi' "${ABI_PATH_GRANTS}/GrantFund.sol/GrantFund.json" > abis/GrantFund.json \ No newline at end of file +jq '.abi' "${ABI_PATH_GRANTS}/GrantFund.sol/GrantFund.json" > abis/GrantFund.json +jq '.abi' "${ABI_PATH_GRANTS}/AjnaToken.sol/AjnaToken.json" > abis/AjnaToken.json + +# Note this removes the needed BurnWrappedAjna ABI diff --git a/schema.graphql b/schema.graphql index d45cec4..f4c432f 100644 --- a/schema.graphql +++ b/schema.graphql @@ -193,6 +193,8 @@ type Loan @entity { liquidationAuction: LiquidationAuction # collateral tokens deposited in a pool by the borrower collateralPledged: BigDecimal! + # borrower's threshold price in t0 terms + thresholdPrice: BigDecimal! # list of tokenIds pledged by the borrower tokenIdsPledged: [BigInt!]! # debt in T0 terms, useful when the caller knows the pending inflator @@ -264,6 +266,7 @@ type LiquidationAuction @entity { bondFactor: BigDecimal! # bond factor determining the reward or penalty for the kicker neutralPrice: BigDecimal! # price at which kicker will have their bond returned without penalty or reward referencePrice: BigDecimal! # max(HTP, NP) used in auction price curve + thresholdPrice: BigDecimal! # borrower's threshold price } # tracks the reserve auction process across multiple takes in a single auction diff --git a/src/utils/pool/liquidation.ts b/src/utils/pool/liquidation.ts index 44c9346..0766e73 100644 --- a/src/utils/pool/liquidation.ts +++ b/src/utils/pool/liquidation.ts @@ -7,6 +7,7 @@ import { PoolInfoUtils } from "../../../generated/templates/ERC20Pool/PoolInfoUt import { wadToDecimal } from "../convert" import { ONE_BI, ZERO_ADDRESS, ZERO_BD, ZERO_BI, poolInfoUtilsAddressTable } from "../constants" +import { thresholdPrice } from './loan'; export function getLiquidationAuctionId(poolId: Bytes, loanId: Bytes, kickBlock: BigInt): Bytes { return poolId.concat(Bytes.fromUTF8('|' + loanId.toString() + '|' + kickBlock.toString())) @@ -82,6 +83,7 @@ export function updateLiquidationAuction( liquidationAuction.kickTime = auctionInfo.kickTime liquidationAuction.neutralPrice = wadToDecimal(auctionInfo.neutralPrice) liquidationAuction.referencePrice = wadToDecimal(auctionInfo.referencePrice) + liquidationAuction.thresholdPrice = wadToDecimal(auctionInfo.thresholdPrice) } // update remaining quantities even if auction was settled and they are 0 @@ -99,16 +101,18 @@ export class AuctionInfo { kickTime: BigInt referencePrice: BigInt neutralPrice: BigInt + thresholdPrice: BigInt head: Address next: Address prev: Address - constructor(kicker: Address, bondFactor: BigInt, bondSize: BigInt, kickTime: BigInt, referencePrice: BigInt, neutralPrice: BigInt, head: Address, next: Address, prev: Address) { + constructor(kicker: Address, bondFactor: BigInt, bondSize: BigInt, kickTime: BigInt, referencePrice: BigInt, neutralPrice: BigInt, thresholdPrice: BigInt, head: Address, next: Address, prev: Address) { this.kicker = kicker this.bondFactor = bondFactor this.bondSize = bondSize this.kickTime = kickTime this.referencePrice = referencePrice this.neutralPrice = neutralPrice + this.thresholdPrice = thresholdPrice this.head = head this.next = next this.prev = prev @@ -126,7 +130,8 @@ export function getAuctionInfoERC20Pool(borrower: Bytes, pool: Pool): AuctionInf auctionInfoResult.value5, auctionInfoResult.value6, auctionInfoResult.value7, - auctionInfoResult.value8 + auctionInfoResult.value8, + auctionInfoResult.value9 ) return auctionInfo } @@ -142,7 +147,8 @@ export function getAuctionInfoERC721Pool(borrower: Bytes, pool: Pool): AuctionIn auctionInfoResult.value5, auctionInfoResult.value6, auctionInfoResult.value7, - auctionInfoResult.value8 + auctionInfoResult.value8, + auctionInfoResult.value9 ) return auctionInfo } @@ -154,13 +160,19 @@ export class AuctionStatus { isCollateralized: bool price: BigInt neutralPrice: BigInt - constructor(kickTime: BigInt, collateral: BigInt, debtToCover: BigInt, isCollateralized: bool, price: BigInt, neutralPrice: BigInt) { + referencePrice: BigInt + thresholdPrice: BigInt + bondFactor: BigInt + constructor(kickTime: BigInt, collateral: BigInt, debtToCover: BigInt, isCollateralized: bool, price: BigInt, neutralPrice: BigInt, referencePrice: BigInt, thresholdPrice: BigInt, bondFactor: BigInt) { this.kickTime = kickTime this.collateral = collateral this.debtToCover = debtToCover this.isCollateralized = isCollateralized this.price = price this.neutralPrice = neutralPrice + this.referencePrice = referencePrice + this.thresholdPrice = thresholdPrice + this.bondFactor = bondFactor } } export function getAuctionStatus(pool: Pool, borrower: Address): AuctionStatus { @@ -173,6 +185,9 @@ export function getAuctionStatus(pool: Pool, borrower: Address): AuctionStatus { result.value2, result.value3, result.value4, - result.value5 + result.value5, + result.value6, + result.value7, + result.value8 ) } diff --git a/src/utils/pool/loan.ts b/src/utils/pool/loan.ts index 4d10e35..ffd98da 100644 --- a/src/utils/pool/loan.ts +++ b/src/utils/pool/loan.ts @@ -21,6 +21,7 @@ export function loadOrCreateLoan(loanId: Bytes, poolId: Bytes, borrower: Bytes): loan.poolAddress = poolId.toHexString() loan.collateralPledged = ZERO_BD loan.t0debt = ZERO_BD + loan.thresholdPrice = ZERO_BD loan.inLiquidation = false loan.liquidationAuction = null loan.tokenIdsPledged = [] diff --git a/tests/erc-20-pool.test.ts b/tests/erc-20-pool.test.ts index 6bd7df7..209d61b 100644 --- a/tests/erc-20-pool.test.ts +++ b/tests/erc-20-pool.test.ts @@ -24,7 +24,7 @@ import { addressToBytes, wadToDecimal } from "../src/utils/convert" import { FIVE_PERCENT_BI, MAX_PRICE, MAX_PRICE_BI, MAX_PRICE_INDEX, ONE_BI, ONE_PERCENT_BI, ONE_WAD_BI, TWO_BI, ZERO_ADDRESS, ZERO_BD, ZERO_BI } from '../src/utils/constants'; import { Account, Lend, Loan, Pool } from "../generated/schema" import { getLendId } from "../src/utils/pool/lend" -import { BorrowerInfo, getLoanId } from "../src/utils/pool/loan" +import { BorrowerInfo, getLoanId, thresholdPrice } from '../src/utils/pool/loan'; import { AuctionInfo, AuctionStatus, getLiquidationAuctionId } from "../src/utils/pool/liquidation" import { BurnInfo, DebtInfo } from "../src/utils/pool/pool" import { getReserveAuctionId } from "../src/utils/pool/reserve-auction" @@ -654,6 +654,7 @@ describe("ERC20Pool assertions", () => { const kickTime = BigInt.fromI32(123) const neutralPrice = BigInt.fromI32(456) const referencePrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(collateral) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -665,6 +666,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -676,7 +678,10 @@ describe("ERC20Pool assertions", () => { debt, false, startPrice, - neutralPrice + neutralPrice, + referencePrice, + thresholdPrice, + bondFactor ) mockGetAuctionStatus(poolAddress, borrower, expectedAuctionStatus) @@ -836,6 +841,7 @@ describe("ERC20Pool assertions", () => { const kickTime = BigInt.fromI32(123) const referencePrice = BigInt.fromI32(456) const neutralPrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(collateral) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -847,6 +853,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -883,6 +890,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -894,7 +902,10 @@ describe("ERC20Pool assertions", () => { debt, false, wmul(neutralPrice, BigInt.fromString("970000000000000000")), // take price = neutral price * 0.97 - neutralPrice + neutralPrice, + referencePrice, + thresholdPrice, + bondFactor ) mockGetAuctionStatus(poolAddress, borrower, expectedAuctionStatus) expectedBorrowerInfo = new BorrowerInfo( @@ -1024,6 +1035,7 @@ describe("ERC20Pool assertions", () => { const kickTime = BigInt.fromI32(123) const referencePrice = BigInt.fromI32(456) const neutralPrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(collateral) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -1034,6 +1046,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -1063,6 +1076,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -1074,7 +1088,10 @@ describe("ERC20Pool assertions", () => { debt, false, wmul(neutralPrice, BigInt.fromString("1020000000000000000")), // take price = neutral price * 1.02 - neutralPrice + neutralPrice, + referencePrice, + thresholdPrice, + bondFactor ) mockGetAuctionStatus(poolAddress, borrower, expectedAuctionStatus) @@ -1216,6 +1233,7 @@ describe("ERC20Pool assertions", () => { const kickTime = BigInt.fromI32(123) const referencePrice = BigInt.fromI32(456) const neutralPrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(collateral) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -1226,6 +1244,7 @@ describe("ERC20Pool assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev diff --git a/tests/erc-721-pool.test.ts b/tests/erc-721-pool.test.ts index 817d70d..e13d1b8 100644 --- a/tests/erc-721-pool.test.ts +++ b/tests/erc-721-pool.test.ts @@ -20,7 +20,7 @@ import { mockGetAuctionInfo, mockGetAuctionStatus, mockGetBorrowerInfo, mockGetB import { BucketInfo, getBucketId } from "../src/utils/pool/bucket" import { addressToBytes, wadToDecimal } from "../src/utils/convert" import { DebtInfo } from "../src/utils/pool/pool" -import { BorrowerInfo, getLoanId } from "../src/utils/pool/loan" +import { BorrowerInfo, getLoanId, thresholdPrice } from '../src/utils/pool/loan'; import { wdiv, wmul } from "../src/utils/math" import { getLendId } from "../src/utils/pool/lend" import { AuctionInfo, AuctionStatus, getLiquidationAuctionId } from "../src/utils/pool/liquidation" @@ -818,6 +818,7 @@ describe("Describe entity assertions", () => { const kickTime = BigInt.fromI32(123) const referencePrice = BigInt.fromI32(456) const neutralPrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(amountPledged) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -830,6 +831,7 @@ describe("Describe entity assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -842,7 +844,10 @@ describe("Describe entity assertions", () => { debt, false, wmul(neutralPrice, BigInt.fromString("1020000000000000000")), // take price = neutral price * 1.02 - neutralPrice + neutralPrice, + referencePrice, + thresholdPrice, + bondFactor ) mockGetAuctionStatus(poolAddress, borrower, expectedAuctionStatus) @@ -1211,6 +1216,7 @@ describe("Describe entity assertions", () => { const kickTime = BigInt.fromI32(123) const referencePrice = BigInt.fromI32(456) const neutralPrice = BigInt.fromI32(456) + const thresholdPrice = debt.div(amountPledged) const head = Address.fromString("0x0000000000000000000000000000000000000000") const next = Address.fromString("0x0000000000000000000000000000000000000000") const prev = Address.fromString("0x0000000000000000000000000000000000000000") @@ -1223,6 +1229,7 @@ describe("Describe entity assertions", () => { kickTime, referencePrice, neutralPrice, + thresholdPrice, head, next, prev @@ -1235,7 +1242,10 @@ describe("Describe entity assertions", () => { debt, false, wmul(neutralPrice, BigInt.fromString("1020000000000000000")), // take price = neutral price * 1.02 - neutralPrice + neutralPrice, + referencePrice, + thresholdPrice, + bondFactor ) mockGetAuctionStatus(poolAddress, borrower, expectedAuctionStatus) diff --git a/tests/utils/mock-contract-calls.ts b/tests/utils/mock-contract-calls.ts index 25375ce..8ba0fd3 100644 --- a/tests/utils/mock-contract-calls.ts +++ b/tests/utils/mock-contract-calls.ts @@ -5,7 +5,7 @@ import { BucketInfo } from "../../src/utils/pool/bucket" import { positionManagerAddressTable, poolInfoUtilsAddressTable, ZERO_BI, ONE_BI, poolInfoUtilsMulticallAddressTable } from '../../src/utils/constants'; import { BurnInfo, DebtInfo, LoansInfo, PoolPricesInfo, PoolUtilizationInfo, ReservesInfo, PoolDetails, RatesAndFees, PoolBalanceDetails, depositUpToIndex } from '../../src/utils/pool/pool'; import { AuctionInfo, AuctionStatus } from "../../src/utils/pool/liquidation" -import { BorrowerInfo } from "../../src/utils/pool/loan" +import { BorrowerInfo, thresholdPrice } from '../../src/utils/pool/loan'; import { wdiv, wmin, wmul } from "../../src/utils/math" import { addressToBytes, decimalToWad } from "../../src/utils/convert" import { Pool } from "../../generated/schema" @@ -326,7 +326,7 @@ export function mockGetPoolBalanceDetails(pool: Address, meaningfulIndex: BigInt // mock auctionInfo contract calls export function mockGetAuctionInfo(borrower: Address, pool: Address, expectedInfo: AuctionInfo): void { - createMockedFunction(pool, 'auctionInfo', 'auctionInfo(address):(address,uint256,uint256,uint256,uint256,uint256,address,address,address)') + createMockedFunction(pool, 'auctionInfo', 'auctionInfo(address):(address,uint256,uint256,uint256,uint256,uint256,uint256,address,address,address)') .withArgs([ethereum.Value.fromAddress(borrower)]) .returns([ ethereum.Value.fromAddress(expectedInfo.kicker), @@ -335,6 +335,7 @@ export function mockGetAuctionInfo(borrower: Address, pool: Address, expectedInf ethereum.Value.fromUnsignedBigInt(expectedInfo.kickTime), ethereum.Value.fromUnsignedBigInt(expectedInfo.referencePrice), ethereum.Value.fromUnsignedBigInt(expectedInfo.neutralPrice), + ethereum.Value.fromUnsignedBigInt(expectedInfo.thresholdPrice), ethereum.Value.fromAddress(expectedInfo.head), ethereum.Value.fromAddress(expectedInfo.next), ethereum.Value.fromAddress(expectedInfo.prev) @@ -344,15 +345,18 @@ export function mockGetAuctionInfo(borrower: Address, pool: Address, expectedInf // mock auctionStatus poolInfoUtils calls export function mockGetAuctionStatus(pool: Address, borrower: Address, expectedInfo: AuctionStatus): void { createMockedFunction(poolInfoUtilsAddressTable.get(dataSource.network())!, - 'auctionStatus', 'auctionStatus(address,address):(uint256,uint256,uint256,bool,uint256,uint256)') + 'auctionStatus', 'auctionStatus(address,address):(uint256,uint256,uint256,bool,uint256,uint256,uint256,uint256,uint256)') .withArgs([ethereum.Value.fromAddress(pool), ethereum.Value.fromAddress(borrower)]) .returns([ - ethereum.Value.fromUnsignedBigInt(expectedInfo.kickTime), - ethereum.Value.fromUnsignedBigInt(expectedInfo.collateral), - ethereum.Value.fromUnsignedBigInt(expectedInfo.debtToCover), - ethereum.Value.fromBoolean(expectedInfo.isCollateralized), - ethereum.Value.fromUnsignedBigInt(expectedInfo.price), - ethereum.Value.fromUnsignedBigInt(expectedInfo.neutralPrice) + ethereum.Value.fromUnsignedBigInt(expectedInfo.kickTime), + ethereum.Value.fromUnsignedBigInt(expectedInfo.collateral), + ethereum.Value.fromUnsignedBigInt(expectedInfo.debtToCover), + ethereum.Value.fromBoolean(expectedInfo.isCollateralized), + ethereum.Value.fromUnsignedBigInt(expectedInfo.price), + ethereum.Value.fromUnsignedBigInt(expectedInfo.neutralPrice), + ethereum.Value.fromUnsignedBigInt(expectedInfo.referencePrice), + ethereum.Value.fromUnsignedBigInt(expectedInfo.thresholdPrice), + ethereum.Value.fromUnsignedBigInt(expectedInfo.bondFactor) ]) }