Skip to content

Commit

Permalink
chore: Improve simulations (#616)
Browse files Browse the repository at this point in the history
  • Loading branch information
valiafetisov authored Apr 4, 2024
1 parent 037502d commit 6aa8178
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 42 deletions.
23 changes: 19 additions & 4 deletions bot/src/keepers/collateral.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AuctionInitialInfo } from 'auctions-core/src/types';
import { bidWithCallee, enrichAuction } from 'auctions-core/src/auctions';
import getSigner from 'auctions-core/src/signer';
import { fetchVATbalanceDAI, fetchBalanceDAI } from 'auctions-core/src/wallet';
import { KEEPER_COLLATERAL_MINIMUM_NET_PROFIT_DAI } from '../variables';
import { checkAndAuthorizeCollateral, checkAndAuthorizeWallet } from '../authorisation';
import { setupWallet } from '../signer';
Expand Down Expand Up @@ -49,18 +50,22 @@ const checkAndParticipateIfPossible = async function (network: string, auction:
return;
}

// check auction's profit
// check auction's gross profit
if (!auctionTransaction.transactionGrossProfit || auctionTransaction.transactionGrossProfit.isLessThan(0)) {
if (auctionTransaction.transactionGrossProfit) {
const profit = `${auctionTransaction.transactionGrossProfit.toFixed(0)} DAI`;
const grossProfit = `${auctionTransaction.transactionGrossProfit.toFixed(0)} DAI`;
console.info(
`collateral keeper: auction "${auction.id}" is not yet profitable (current profit: ${profit})`
`collateral keeper: auction "${auction.id}" is not yet executable (current gross profit: ${grossProfit})`
);
} else {
console.info(`collateral keeper: auction "${auction.id}" is not tradable`);
}
return;
}
const grossProfit = `${auctionTransaction.transactionGrossProfit.toFixed(0)} DAI`;
console.info(
`collateral keeper: auction "${auction.id}" gross profit is ${grossProfit}, moving on to check net profit`
);

// check auction's net profit – profit without transaction fees
if (
Expand All @@ -70,7 +75,7 @@ const checkAndParticipateIfPossible = async function (network: string, auction:
console.info(
`collateral keeper: auction "${
auction.id
}" net profit is smaller than min profit (${auctionTransaction.transactionNetProfit.toFixed(
}" net profit is smaller than min net profit (${auctionTransaction.transactionNetProfit.toFixed(
0
)} < ${KEEPER_COLLATERAL_MINIMUM_NET_PROFIT_DAI})`
);
Expand Down Expand Up @@ -107,6 +112,10 @@ const checkAndParticipateIfPossible = async function (network: string, auction:
return;
}

// save previous balances
const preVatBalanceDai = await fetchVATbalanceDAI(network, walletAddress);
const preErcBalanceDai = await fetchBalanceDAI(network, walletAddress);

// bid on the Auction
console.info(`collateral keeper: auction "${auctionTransaction.id}": attempting swap execution`);
const bidHash = await bidWithCallee(
Expand All @@ -118,6 +127,12 @@ const checkAndParticipateIfPossible = async function (network: string, auction:
console.info(
`collateral keeper: auction "${auctionTransaction.id}" was succesfully executed via "${bidHash}" transaction`
);

// display profit
const postVatBalanceDai = await fetchVATbalanceDAI(network, walletAddress);
const postErcBalanceDai = await fetchBalanceDAI(network, walletAddress);
console.info(`DAI VAT profit from the transaction: ${postVatBalanceDai.minus(preVatBalanceDai).toFixed()}`);
console.info(`DAI ERC profit from the transaction: ${postErcBalanceDai.minus(preErcBalanceDai).toFixed()}`);
};

const participateInAuction = async function (network: string, auction: AuctionInitialInfo) {
Expand Down
75 changes: 40 additions & 35 deletions core/simulations/configs/vaultLiquidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import createVaultWithCollateral, {
} from '../helpers/createVaultWithCollateral';
import promptToSelectOneOption from '../helpers/promptToSelectOneOption';
import promptToGetBlockNumber from '../helpers/promptToGetBlockNumber';
import getProvider from '../../src/provider';

import { fetchMaximumAuctionDurationInSeconds } from '../../src/fetch';
import fetchAuctionsByCollateralType, { fetchMaximumAuctionDurationInSeconds } from '../../src/fetch';
import { getAllCollateralTypes } from '../../src/constants/COLLATERALS';
import { setCollateralDebtCeilingToGlobal } from '../../helpers/hardhat/contractParametrization';

const TWO_YEARS_IN_MINUTES = 60 * 24 * 30 * 12 * 2;

Expand All @@ -23,8 +25,10 @@ const simulation: Simulation = {
entry: async () => {
const number = await promptToGetBlockNumber();
await resetNetworkAndSetupWallet(number);
await addDaiToBalance();
await addMkrToBalance();
const collateralType = await promptToSelectOneOption(
'Select the collateral symbol to add to the VAT.',
'Select the collateral type',
getAllCollateralTypes()
);
return {
Expand All @@ -33,34 +37,29 @@ const simulation: Simulation = {
},
},
{
title: 'Create the vault',
title: 'Create underwater vault',
entry: async context => {
await adjustLimitsAndRates(context.collateralType);
const collateralOwned = await calculateMinCollateralAmountToOpenVault(context.collateralType);
console.info(`Minimum collateral amount to open vault: ${collateralOwned.toFixed()}`);
const latestVaultId = await createVaultWithCollateral(context.collateralType, collateralOwned);
await setCollateralDebtCeilingToGlobal(context.collateralType);
const latestVaultId = await createVaultWithCollateral(
context.collateralType,
collateralOwned.multipliedBy(1)
);
console.info(`Created Vault id: ${latestVaultId}`);
return { ...context, latestVaultId };
},
},
{
title: 'Skip time',
entry: async context => {

console.info(`Skipping ${TWO_YEARS_IN_MINUTES} minutes...`);
await warpTime(TWO_YEARS_IN_MINUTES, 60);
return context;
},
},
{
title: 'Collect stability fees',
entry: async context => {
const collateralType = context.collateralType;
const latestVaultId = context.latestVaultId;

console.info(`Collecting stability fees...`);
const vaultBefore = await fetchVault(TEST_NETWORK, latestVaultId);
console.info(`stability fees before ${vaultBefore.stabilityFeeRate}`);
await collectStabilityFees(TEST_NETWORK, collateralType);
console.info(`Stability fee before ${vaultBefore.stabilityFeeRate}`);
await collectStabilityFees(TEST_NETWORK, context.collateralType);
const vaultAfter = await fetchVault(TEST_NETWORK, latestVaultId);
console.info(`stability fees after ${vaultAfter.stabilityFeeRate}`);
return context;
console.info(`Stability fee after ${vaultAfter.stabilityFeeRate}`);

return { ...context, latestVaultId };
},
},
{
Expand All @@ -79,20 +78,26 @@ const simulation: Simulation = {
TEST_NETWORK,
context.collateralType
);
const warpSeconds = Math.floor(auctionLifetime / 2);
if (!warpSeconds) {
throw new Error('Auction lifetime is too short to warp time.');
}
console.info(`Skipping time: ${warpSeconds} seconds`);
const INITIAL_WARP_PARTS = 1 / 13;
const warpSeconds = Math.floor(auctionLifetime * INITIAL_WARP_PARTS);
console.info(`Initial warp of ${INITIAL_WARP_PARTS} of an auction time: ${warpSeconds} seconds`);
await warpTime(warpSeconds, 1);
return context;
},
},
{
title: 'Add DAI and MKR to the wallet',
entry: async () => {
await addDaiToBalance();
await addMkrToBalance();
const provider = await getProvider(TEST_NETWORK);
const STEP_SECONDS = 30;
while (true) {
const initialAuctions = await fetchAuctionsByCollateralType(TEST_NETWORK, context.collateralType);
if (!initialAuctions[0] || !initialAuctions[0].isActive) {
console.info('No active auctions are found, exiting the "evm_mine" loop');
break;
}
console.info(`Gradually skipping time, one block every ${STEP_SECONDS} seconds`);
try {
await provider.send('evm_mine', []);
await new Promise(resolve => setTimeout(resolve, STEP_SECONDS * 1000));
} catch (error) {
console.error('evm_mine failed with', error);
}
}
},
},
],
Expand Down
4 changes: 1 addition & 3 deletions core/src/auctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,18 @@ export const enrichMarketDataRecordsWithValues = async function (
exchangeFees: ExchangeFees,
amount: BigNumber = new BigNumber(1)
): Promise<Record<string, MarketData>> {
const exchangeFeePerUnitDAI = exchangeFees.exchangeFeeDAI.dividedBy(amount);
let enrichedMarketDataRecords = {};
for (const marketId in marketDataRecords) {
let marketData = marketDataRecords[marketId];
// enrich with values dependent on marketUnitPrice
let marketUnitPrice = marketData.marketUnitPrice;
const marketUnitPrice = marketData.marketUnitPrice;
if (marketUnitPrice.isNaN()) {
enrichedMarketDataRecords = {
...enrichedMarketDataRecords,
[marketId]: { ...marketData },
};
continue;
}
marketUnitPrice = marketUnitPrice.plus(exchangeFeePerUnitDAI);
marketData = {
...marketData,
marketUnitPrice,
Expand Down

0 comments on commit 6aa8178

Please sign in to comment.