Skip to content

Commit 42e3abd

Browse files
authored
fix: calculateTransactionCollateralOutcome calculation and increased precision (#602)
1 parent 090637b commit 42e3abd

File tree

10 files changed

+81
-42
lines changed

10 files changed

+81
-42
lines changed

core/simulations/configs/specificBlockFork.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { addDaiToBalance, addMkrToBalance } from '../../helpers/hardhat/balance';
12
import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network';
23
import promptToGetBlockNumber from '../helpers/promptToGetBlockNumber';
34
import { Simulation } from '../types';
@@ -12,6 +13,13 @@ const simulation: Simulation = {
1213
await resetNetworkAndSetupWallet(selectedBlockNumber);
1314
},
1415
},
16+
{
17+
title: 'Add DAI and MKR to the wallet',
18+
entry: async () => {
19+
await addDaiToBalance();
20+
await addMkrToBalance();
21+
},
22+
},
1523
{
1624
title: 'Skip time',
1725
entry: async () => {

core/src/bignumber.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import BigNumber from 'bignumber.js';
2-
import { RAY_NUMBER_OF_DIGITS } from './constants/UNITS';
2+
import { RAD_NUMBER_OF_DIGITS } from './constants/UNITS';
33

4-
BigNumber.config({ DECIMAL_PLACES: RAY_NUMBER_OF_DIGITS });
4+
BigNumber.config({ DECIMAL_PLACES: RAD_NUMBER_OF_DIGITS });
55

66
export default BigNumber;

core/src/helpers/parseMetamaskError.ts

+12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,19 @@ const getErrorTitle = function (errorMessage = '') {
2929
return errorMessage.substring(0, jsonStartIndex).trim();
3030
};
3131

32+
const getVMError = function (errorMessage = '') {
33+
const prefix = 'Error: VM Exception while processing transaction:';
34+
if (!errorMessage.startsWith(prefix)) {
35+
return '';
36+
}
37+
return errorMessage.replace(prefix, 'VM').trim();
38+
};
39+
3240
const parseMetamaskError = function (errorMessage = ''): unknown {
41+
const vmError = getVMError(errorMessage);
42+
if (vmError) {
43+
return vmError;
44+
}
3345
const errorTitle = getErrorTitle(errorMessage);
3446
if (!errorTitle) {
3547
return truncateText(errorMessage || UNKNOWN_ERROR_TEXT);

core/src/price.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Auction } from './types';
22
import BigNumber from './bignumber';
33
import { addSeconds } from 'date-fns';
4+
import { RAD_NUMBER_OF_DIGITS } from './constants/UNITS';
45

56
const checkAuctionStartDate = function (startDate: Date, currentDate: Date): void {
67
const auctionStartTimestamp = startDate.getTime();
@@ -65,16 +66,15 @@ export const calculateTransactionCollateralOutcome = function (
6566
const collateralToBuyForTheBid = bidAmountDai.dividedBy(unitPrice);
6667
const potentialOutcomeCollateralAmount = BigNumber.minimum(collateralToBuyForTheBid, auction.collateralAmount); // slice
6768
const potentialOutcomeTotalPrice = potentialOutcomeCollateralAmount.multipliedBy(unitPrice); // owe
68-
const approximateDebt = new BigNumber(auction.debtDAI.toPrecision(16, BigNumber.ROUND_DOWN));
69-
const approximatePotentialOutcomeTotalPrice = new BigNumber(
70-
potentialOutcomeTotalPrice.toPrecision(16, BigNumber.ROUND_DOWN)
69+
const potentialOutcomeTotalPriceRounded = new BigNumber( // rounded up to match debtDAI precision
70+
potentialOutcomeTotalPrice.toPrecision(RAD_NUMBER_OF_DIGITS, BigNumber.ROUND_UP)
7171
);
7272
if (
7373
// if owe > tab
74-
// soft compensation because of precision problems.
75-
approximateDebt.isLessThan(approximatePotentialOutcomeTotalPrice)
74+
potentialOutcomeTotalPriceRounded.isGreaterThan(auction.debtDAI)
7675
) {
77-
return auction.debtDAI.dividedBy(unitPrice); // return tab / price
76+
// return tab / price + 0.1% compensation for the js/sol math differences
77+
return auction.debtDAI.dividedBy(unitPrice).multipliedBy(1.001);
7878
} else if (
7979
// if owe < tab && slice < lot
8080
potentialOutcomeTotalPrice.isLessThan(auction.debtDAI) &&

core/src/tracker.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const trackTransaction = async function (
3535
});
3636
} catch (error: any) {
3737
notifier('error', {
38-
content: `Transaction error: "${parseMetamaskError(error?.message)}"`,
38+
content: `Transaction error: "${parseMetamaskError(error?.data?.message || error?.message)}"`,
3939
key: messageId,
4040
duration: DEFAULT_NOTIFICATION_DURATION,
4141
});
@@ -72,7 +72,9 @@ const trackTransaction = async function (
7272
return confirmedTransactionReceipt.transactionHash;
7373
} catch (error: any) {
7474
notifier('error', {
75-
content: `Transaction was rejected with error: "${parseMetamaskError(error?.message)}"`,
75+
content: `Transaction was rejected with error: "${parseMetamaskError(
76+
error?.data?.message || error?.message
77+
)}"`,
7678
key: messageId,
7779
duration: DEFAULT_NOTIFICATION_DURATION,
7880
});

core/test/surplus-test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ describe('Surplus Auction', () => {
4747
const auctions = await fetchActiveSurplusAuctions(network);
4848
const auction = auctions[0] as SurplusAuctionActive;
4949
const enrichedAucton = await enrichSurplusAuction(network, auction);
50-
expect(enrichedAucton.marketUnitPrice?.toString()).to.equal('0.001395892836151232667549186');
50+
expect(enrichedAucton.marketUnitPrice?.toString()).to.equal('0.001395892836151232667549185678491851066262951');
5151
expect(enrichedAucton.unitPrice?.toString()).to.equal('0.0005430260298973471');
52-
expect(enrichedAucton.marketUnitPriceToUnitPriceRatio?.toString()).to.equal('-0.61098300970253348099040009');
52+
expect(enrichedAucton.marketUnitPriceToUnitPriceRatio?.toString()).to.equal(
53+
'-0.610983009702533480990400000000000000000000026'
54+
);
5355
});
5456
it('enrichesAuctionWithMinimumBids', async () => {
5557
const network = TEST_NETWORK;

core/test/vault-test.ts

+25-25
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,29 @@ const compareVaultTransactionsNotLiquidated = (
3535
expect(expected.network).to.eq(actual.network);
3636
expect(expected.nextPriceChange).to.deep.equalInAnyOrder(actual.nextPriceChange);
3737

38-
expect(expected.liquidationRatio).to.deep.equalInAnyOrder(actual.liquidationRatio);
39-
expect(expected.collateralizationRatio).to.deep.equalInAnyOrder(actual.collateralizationRatio);
40-
expect(expected.proximityToLiquidation).to.deep.equalInAnyOrder(actual.proximityToLiquidation);
38+
expect(expected.liquidationRatio.toFixed()).to.eq(actual.liquidationRatio.toFixed());
39+
expect(expected.collateralizationRatio.toFixed()).to.eq(actual.collateralizationRatio.toFixed());
40+
expect(expected.proximityToLiquidation.toFixed()).to.eq(actual.proximityToLiquidation.toFixed());
4141
expect(expected.id).to.eq(actual.id);
42-
expect(expected.incentiveCombinedDai).to.deep.equalInAnyOrder(actual.incentiveCombinedDai);
43-
expect(expected.incentiveRelativeDai).to.deep.equalInAnyOrder(actual.incentiveRelativeDai);
44-
expect(expected.incentiveConstantDai).to.deep.equalInAnyOrder(actual.incentiveConstantDai);
45-
expect(expected.grossProfitDai).to.deep.equalInAnyOrder(actual.grossProfitDai);
42+
expect(expected.incentiveCombinedDai.toFixed()).to.eq(actual.incentiveCombinedDai.toFixed());
43+
expect(expected.incentiveRelativeDai.toFixed()).to.eq(actual.incentiveRelativeDai.toFixed());
44+
expect(expected.incentiveConstantDai.toFixed()).to.eq(actual.incentiveConstantDai.toFixed());
45+
expect(expected.grossProfitDai.toFixed()).to.eq(actual.grossProfitDai.toFixed());
4646
// TODO: enable the check and fix the bug with inconsistent price received
47-
// expect(expected.netProfitDai).to.deep.equalInAnyOrder(actual.netProfitDai);
48-
expect(expected.stabilityFeeRate).to.deep.equalInAnyOrder(actual.stabilityFeeRate);
49-
expect(expected.minUnitPrice).to.deep.equalInAnyOrder(actual.minUnitPrice);
50-
expect(expected.maximumProtocolDebtDai).to.deep.equalInAnyOrder(actual.maximumProtocolDebtDai);
51-
expect(expected.currentProtocolDebtDai).to.deep.equalInAnyOrder(actual.currentProtocolDebtDai);
52-
expect(expected.currentCollateralDebtDai).to.deep.equalInAnyOrder(actual.currentCollateralDebtDai);
53-
expect(expected.maximumCollateralDebtDai).to.deep.equalInAnyOrder(actual.maximumCollateralDebtDai);
54-
expect(expected.debtDai).to.deep.equalInAnyOrder(actual.debtDai);
55-
expect(expected.collateralAmount).to.deep.equalInAnyOrder(actual.collateralAmount);
56-
expect(expected.currentUnitPrice).to.deep.equalInAnyOrder(actual.currentUnitPrice);
57-
expect(expected.nextUnitPrice).to.deep.equalInAnyOrder(actual.nextUnitPrice);
58-
expect(expected.initialDebtDai).to.deep.equalInAnyOrder(actual.initialDebtDai);
59-
expect(expected.liquidationPenaltyRatio).to.deep.equalInAnyOrder(actual.liquidationPenaltyRatio);
60-
expect(expected.minimalAuctionedDai).to.deep.equalInAnyOrder(actual.minimalAuctionedDai);
47+
// expect(expected.netProfitDai.toFixed()).to.eq(actual.netProfitDai.toFixed());
48+
expect(expected.stabilityFeeRate.toFixed()).to.eq(actual.stabilityFeeRate.toFixed());
49+
expect(expected.minUnitPrice.toFixed()).to.eq(actual.minUnitPrice.toFixed());
50+
expect(expected.maximumProtocolDebtDai.toFixed()).to.eq(actual.maximumProtocolDebtDai.toFixed());
51+
expect(expected.currentProtocolDebtDai.toFixed()).to.eq(actual.currentProtocolDebtDai.toFixed());
52+
expect(expected.currentCollateralDebtDai.toFixed()).to.eq(actual.currentCollateralDebtDai.toFixed());
53+
expect(expected.maximumCollateralDebtDai.toFixed()).to.eq(actual.maximumCollateralDebtDai.toFixed());
54+
expect(expected.debtDai.toFixed()).to.eq(actual.debtDai.toFixed());
55+
expect(expected.collateralAmount.toFixed()).to.eq(actual.collateralAmount.toFixed());
56+
expect(expected.currentUnitPrice.toFixed()).to.eq(actual.currentUnitPrice.toFixed());
57+
expect(expected.nextUnitPrice.toFixed()).to.eq(actual.nextUnitPrice.toFixed());
58+
expect(expected.initialDebtDai.toFixed()).to.eq(actual.initialDebtDai.toFixed());
59+
expect(expected.liquidationPenaltyRatio.toFixed()).to.eq(actual.liquidationPenaltyRatio.toFixed());
60+
expect(expected.minimalAuctionedDai.toFixed()).to.eq(actual.minimalAuctionedDai.toFixed());
6161
};
6262

6363
describe('Vaults', () => {
@@ -82,8 +82,8 @@ describe('Vaults', () => {
8282
nextPriceChange: new Date('2022-09-09T10:00:00.000Z'),
8383

8484
liquidationRatio: new BigNumber('1.45'),
85-
collateralizationRatio: new BigNumber('3.204790430641710905476031356'),
86-
proximityToLiquidation: new BigNumber('0.547552318511616565008415095'),
85+
collateralizationRatio: new BigNumber('3.204790430641710905476031355953603471763531393'),
86+
proximityToLiquidation: new BigNumber('0.547552318511616565008415094516004867207418444'),
8787
liquidationPenaltyRatio: new BigNumber('1.13'),
8888
minimalAuctionedDai: new BigNumber('15000'),
8989
id: 22025,
@@ -141,8 +141,8 @@ describe('Vaults', () => {
141141
nextPriceChange: new Date('2022-06-13T11:00:00.000Z'),
142142

143143
liquidationRatio: new BigNumber(1.7),
144-
collateralizationRatio: new BigNumber('1.698313241866926788910221381'),
145-
proximityToLiquidation: new BigNumber('-0.000993196126304112564617121'),
144+
collateralizationRatio: new BigNumber('1.698313241866926788910221380759664664393806833'),
145+
proximityToLiquidation: new BigNumber('-0.000993196126304112564617120755317536277614422'),
146146
liquidationPenaltyRatio: new BigNumber('1.13'),
147147
minimalAuctionedDai: new BigNumber('5000'),
148148
id: 27435,

frontend/components/common/formatters/AnimatedNumber.vue

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
<template>
2-
<span v-if="isValidNumber"
3-
><span v-if="isValueSmallButNotZero">under </span
4-
><animated-number :value="formattedValue" :format-value="format" :duration="duration"
5-
/></span>
2+
<Popover :content="pureValue" placement="top">
3+
<span v-if="isValidNumber"
4+
><span v-if="isValueSmallButNotZero">under </span
5+
><animated-number :value="formattedValue" :format-value="format" :duration="duration"
6+
/></span>
7+
</Popover>
68
</template>
79

810
<script lang="ts">
911
import Vue from 'vue';
12+
import { Popover } from 'ant-design-vue';
1013
import AnimatedNumber from 'animated-number-vue';
1114
import BigNumber from 'bignumber.js';
1215
import {
@@ -18,6 +21,7 @@ import {
1821
export default Vue.extend({
1922
components: {
2023
AnimatedNumber,
24+
Popover,
2125
},
2226
props: {
2327
value: {
@@ -38,6 +42,15 @@ export default Vue.extend({
3842
},
3943
},
4044
computed: {
45+
pureValue(): string {
46+
if (this.value === undefined) {
47+
return '';
48+
}
49+
if (typeof this.value === 'number') {
50+
return this.value.toString();
51+
}
52+
return this.value.toFixed();
53+
},
4154
formattedValue(): string {
4255
return formatToAutomaticDecimalPoints(this.value, {
4356
decimalPlaces: this.decimalPlaces,

frontend/components/common/other/parseMetamaskError.stories.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)