Skip to content

Commit fee1229

Browse files
authored
feat: Added collateral withdrawal block and logic, fixed collateral profit (#167)
1 parent bc6bf23 commit fee1229

21 files changed

+626
-121
lines changed

core/src/abis/MCD_JOIN.json

+236
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
[
2+
{
3+
"inputs": [
4+
{
5+
"internalType": "address",
6+
"name": "vat_",
7+
"type": "address"
8+
},
9+
{
10+
"internalType": "bytes32",
11+
"name": "ilk_",
12+
"type": "bytes32"
13+
},
14+
{
15+
"internalType": "address",
16+
"name": "gem_",
17+
"type": "address"
18+
}
19+
],
20+
"payable": false,
21+
"stateMutability": "nonpayable",
22+
"type": "constructor"
23+
},
24+
{
25+
"anonymous": true,
26+
"inputs": [
27+
{
28+
"indexed": true,
29+
"internalType": "bytes4",
30+
"name": "sig",
31+
"type": "bytes4"
32+
},
33+
{
34+
"indexed": true,
35+
"internalType": "address",
36+
"name": "usr",
37+
"type": "address"
38+
},
39+
{
40+
"indexed": true,
41+
"internalType": "bytes32",
42+
"name": "arg1",
43+
"type": "bytes32"
44+
},
45+
{
46+
"indexed": true,
47+
"internalType": "bytes32",
48+
"name": "arg2",
49+
"type": "bytes32"
50+
},
51+
{
52+
"indexed": false,
53+
"internalType": "bytes",
54+
"name": "data",
55+
"type": "bytes"
56+
}
57+
],
58+
"name": "LogNote",
59+
"type": "event"
60+
},
61+
{
62+
"constant": false,
63+
"inputs": [],
64+
"name": "cage",
65+
"outputs": [],
66+
"payable": false,
67+
"stateMutability": "nonpayable",
68+
"type": "function"
69+
},
70+
{
71+
"constant": true,
72+
"inputs": [],
73+
"name": "dec",
74+
"outputs": [
75+
{
76+
"internalType": "uint256",
77+
"name": "",
78+
"type": "uint256"
79+
}
80+
],
81+
"payable": false,
82+
"stateMutability": "view",
83+
"type": "function"
84+
},
85+
{
86+
"constant": false,
87+
"inputs": [
88+
{
89+
"internalType": "address",
90+
"name": "usr",
91+
"type": "address"
92+
}
93+
],
94+
"name": "deny",
95+
"outputs": [],
96+
"payable": false,
97+
"stateMutability": "nonpayable",
98+
"type": "function"
99+
},
100+
{
101+
"constant": false,
102+
"inputs": [
103+
{
104+
"internalType": "address",
105+
"name": "usr",
106+
"type": "address"
107+
},
108+
{
109+
"internalType": "uint256",
110+
"name": "wad",
111+
"type": "uint256"
112+
}
113+
],
114+
"name": "exit",
115+
"outputs": [],
116+
"payable": false,
117+
"stateMutability": "nonpayable",
118+
"type": "function"
119+
},
120+
{
121+
"constant": true,
122+
"inputs": [],
123+
"name": "gem",
124+
"outputs": [
125+
{
126+
"internalType": "contract GemLike",
127+
"name": "",
128+
"type": "address"
129+
}
130+
],
131+
"payable": false,
132+
"stateMutability": "view",
133+
"type": "function"
134+
},
135+
{
136+
"constant": true,
137+
"inputs": [],
138+
"name": "ilk",
139+
"outputs": [
140+
{
141+
"internalType": "bytes32",
142+
"name": "",
143+
"type": "bytes32"
144+
}
145+
],
146+
"payable": false,
147+
"stateMutability": "view",
148+
"type": "function"
149+
},
150+
{
151+
"constant": false,
152+
"inputs": [
153+
{
154+
"internalType": "address",
155+
"name": "usr",
156+
"type": "address"
157+
},
158+
{
159+
"internalType": "uint256",
160+
"name": "wad",
161+
"type": "uint256"
162+
}
163+
],
164+
"name": "join",
165+
"outputs": [],
166+
"payable": false,
167+
"stateMutability": "nonpayable",
168+
"type": "function"
169+
},
170+
{
171+
"constant": true,
172+
"inputs": [],
173+
"name": "live",
174+
"outputs": [
175+
{
176+
"internalType": "uint256",
177+
"name": "",
178+
"type": "uint256"
179+
}
180+
],
181+
"payable": false,
182+
"stateMutability": "view",
183+
"type": "function"
184+
},
185+
{
186+
"constant": false,
187+
"inputs": [
188+
{
189+
"internalType": "address",
190+
"name": "usr",
191+
"type": "address"
192+
}
193+
],
194+
"name": "rely",
195+
"outputs": [],
196+
"payable": false,
197+
"stateMutability": "nonpayable",
198+
"type": "function"
199+
},
200+
{
201+
"constant": true,
202+
"inputs": [],
203+
"name": "vat",
204+
"outputs": [
205+
{
206+
"internalType": "contract VatLike",
207+
"name": "",
208+
"type": "address"
209+
}
210+
],
211+
"payable": false,
212+
"stateMutability": "view",
213+
"type": "function"
214+
},
215+
{
216+
"constant": true,
217+
"inputs": [
218+
{
219+
"internalType": "address",
220+
"name": "",
221+
"type": "address"
222+
}
223+
],
224+
"name": "wards",
225+
"outputs": [
226+
{
227+
"internalType": "uint256",
228+
"name": "",
229+
"type": "uint256"
230+
}
231+
],
232+
"payable": false,
233+
"stateMutability": "view",
234+
"type": "function"
235+
}
236+
]

core/src/auctions.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
calculateAuctionPrice,
1212
calculateTransactionGrossProfit,
1313
calculateTransactionGrossProfitDate,
14+
calculateTransactionCollateralOutcome,
1415
} from './price';
1516
import { getSupportedCollateralTypes } from './addresses';
1617
import getContract, { getClipperNameByCollateralType } from './contracts';
@@ -181,14 +182,14 @@ export const restartAuction = async function (
181182

182183
export const bidWithDai = async function (
183184
network: string,
184-
auction: Auction,
185+
auction: AuctionTransaction,
185186
bidAmountDai: BigNumber,
186187
profitAddress: string,
187188
notifier?: Notifier
188189
): Promise<string> {
189190
const contractName = getClipperNameByCollateralType(auction.collateralType);
190191
const updatedAuction = await enrichAuctionWithActualNumbers(network, auction);
191-
const collateralAmount = bidAmountDai.dividedBy(updatedAuction.unitPrice);
192+
const collateralAmount = calculateTransactionCollateralOutcome(bidAmountDai, updatedAuction.unitPrice, auction);
192193
const contractParameters = [
193194
convertNumberTo32Bytes(auction.index),
194195
collateralAmount.shiftedBy(WAD_NUMBER_OF_DIGITS).toFixed(0),

core/src/contracts.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { fetchContractAddressByNetwork } from './addresses';
55
import MCD_DAI from './abis/MCD_DAI.json';
66
import MCD_VAT from './abis/MCD_VAT.json';
77
import MCD_JOIN_DAI from './abis/MCD_JOIN_DAI.json';
8+
import MCD_JOIN from './abis/MCD_JOIN.json';
89
import MCD_CLIP_CALC from './abis/MCD_CLIP_CALC.json';
910
import MCD_CLIP from './abis/MCD_CLIP.json';
1011
import MCD_DOG from './abis/MCD_DOG.json';
@@ -41,6 +42,9 @@ const getContractInterfaceByName = async function (contractName: string): Promis
4142
if (contractName === 'MCD_JOIN_DAI') {
4243
return MCD_JOIN_DAI;
4344
}
45+
if (contractName.startsWith('MCD_JOIN_')) {
46+
return MCD_JOIN;
47+
}
4448
if (contractName.startsWith('MCD_CLIP_CALC_')) {
4549
return MCD_CLIP_CALC;
4650
}

core/src/fetch.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { AuctionInitialInfo, AuctionStatus } from './types';
2-
import { ethers } from 'ethers';
32
import memoizee from 'memoizee';
43
import BigNumber from './bignumber';
54
import getContract, { getClipperNameByCollateralType } from './contracts';
6-
import { RAD, RAY, WAD } from './constants/UNITS';
5+
import { RAD, RAD_NUMBER_OF_DIGITS, RAY, WAD } from './constants/UNITS';
76
import { getCollateralConfigByType } from './constants/COLLATERALS';
87
import convertNumberTo32Bytes from './helpers/convertNumberTo32Bytes';
98

@@ -25,11 +24,10 @@ const fetchMaximumAuctionDurationInSeconds = memoizee(_fetchMaximumAuctionDurati
2524
});
2625

2726
const _fetchMinimumBidDai = async function (network: string, collateralType: string): Promise<BigNumber> {
28-
const dogContract = await getContract(network, 'MCD_DOG');
29-
const encodedCollateralType = ethers.utils.formatBytes32String(collateralType);
30-
const collateralParameters = await dogContract.ilks(encodedCollateralType);
31-
const minimumBidDai = new BigNumber(collateralParameters.dirt._hex).div(RAD);
32-
return minimumBidDai;
27+
const contractName = getClipperNameByCollateralType(collateralType);
28+
const contract = await getContract(network, contractName);
29+
const minimumBidRaw = await contract.chost();
30+
return new BigNumber(minimumBidRaw._hex).shiftedBy(-RAD_NUMBER_OF_DIGITS);
3331
};
3432

3533
export const fetchMinimumBidDai = memoizee(_fetchMinimumBidDai, {

core/src/price.ts

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Auction } from './types';
1+
import type { Auction, AuctionTransaction } from './types';
22
import BigNumber from './bignumber';
33
import { addSeconds } from 'date-fns';
44

@@ -54,6 +54,44 @@ export const calculateTransactionGrossProfit = function (auction: Auction): BigN
5454
return totalMarketPriceLimitedByDebt.minus(auction.debtDAI);
5555
};
5656

57+
export const calculateTransactionCollateralOutcome = function (
58+
bidAmountDai: BigNumber,
59+
unitPrice: BigNumber,
60+
auction: AuctionTransaction
61+
): BigNumber {
62+
// Based on the clipper contract logic
63+
// https://github.com/makerdao/dss/blob/60690042965500992490f695cf259256cc94c140/src/clip.sol#L357-L380
64+
const collateralToBuyForTheBid = bidAmountDai.dividedBy(unitPrice);
65+
const potentialOutcomeCollateralAmount = BigNumber.minimum(collateralToBuyForTheBid, auction.collateralAmount); // slice
66+
const potentialOutcomeTotalPrice = potentialOutcomeCollateralAmount.multipliedBy(unitPrice); // owe
67+
if (
68+
// if owe > tab
69+
potentialOutcomeTotalPrice.isGreaterThan(auction.debtDAI)
70+
) {
71+
return auction.debtDAI.dividedBy(unitPrice); // return tab / price
72+
} else if (
73+
// if owe < tab && slice < lot
74+
potentialOutcomeTotalPrice.isLessThan(auction.debtDAI) &&
75+
potentialOutcomeCollateralAmount.isLessThan(auction.collateralAmount)
76+
) {
77+
if (
78+
// if tab - owe < _chost
79+
auction.debtDAI.minus(potentialOutcomeTotalPrice).isLessThan(auction.minimumBidDai)
80+
) {
81+
if (
82+
// if tab > _chost
83+
auction.debtDAI.isLessThanOrEqualTo(auction.minimumBidDai)
84+
) {
85+
// shouldn't be possible to left less than minimumBidDai
86+
return new BigNumber(NaN);
87+
}
88+
// tab - _chost / price
89+
return auction.debtDAI.minus(auction.minimumBidDai).dividedBy(unitPrice);
90+
}
91+
}
92+
return potentialOutcomeCollateralAmount;
93+
};
94+
5795
export const calculateTransactionGrossProfitDate = function (auction: Auction, currentDate: Date): Date | undefined {
5896
if (
5997
auction.secondsBetweenPriceDrops === undefined ||

0 commit comments

Comments
 (0)