Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support LSE collateral auctions #622

Merged
merged 28 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f1c5edd
add vscode settings
valiafetisov Sep 30, 2024
e981f41
extend collateral config with contracts object to list relevant chain…
valiafetisov Sep 30, 2024
0501b2a
add LOCKSTAKE collateral config + handle joinless collaterals with error
valiafetisov Sep 30, 2024
3516a7f
working createLockstakeVaultWithCollateral
valiafetisov Sep 30, 2024
07ae133
renaming
valiafetisov Oct 1, 2024
e0d9a68
liquidatable lockstake vault
valiafetisov Oct 1, 2024
aabb872
adjust isCollateralTypeSupported to the new collateral config structure
valiafetisov Oct 1, 2024
cd3f844
add exchange callee config + update collateral config route format
valiafetisov Oct 1, 2024
0d3d9b9
add exchange callee config + update collateral config route format
valiafetisov Oct 1, 2024
247d36b
fix LSE auction start and end dates
valiafetisov Oct 1, 2024
379a030
improve simulation
valiafetisov Oct 2, 2024
afc0adb
working simulation
valiafetisov Oct 2, 2024
1210913
remove overcomplicated getCollateralPriceOracleConfig
valiafetisov Oct 2, 2024
903823c
fix ./core build
valiafetisov Oct 2, 2024
d28ceae
add additional collateral property called tokenName to be able to dis…
valiafetisov Oct 21, 2024
540c2af
fix collaterals modal
valiafetisov Oct 21, 2024
9207970
fix frontend types
valiafetisov Oct 21, 2024
960f8d2
update collateral name for the mainnet
valiafetisov Oct 21, 2024
51d2ac1
use dynamic vaultIndex to open LSE vault
valiafetisov Oct 21, 2024
9326bac
set smaller starting price in the simulation
valiafetisov Oct 21, 2024
7af2e9c
display correct token inside Bid with DAI
valiafetisov Oct 21, 2024
195945e
improve logging
valiafetisov Oct 21, 2024
7f04c83
show full exchange path
valiafetisov Oct 21, 2024
beafc78
use SKY/USDS market for LSE auctions
valiafetisov Oct 21, 2024
0702920
remove unsupported USDC-B collateral to fix tests
valiafetisov Oct 21, 2024
a625ebc
update end-to-end tests to work with LSE collateral
valiafetisov Oct 22, 2024
4427d68
display correct profit token
valiafetisov Oct 22, 2024
6752ddd
fix frontend tests
valiafetisov Oct 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
// Disable the default formatter, use eslint instead
"prettier.enable": false,
"editor.formatOnSave": false,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
// Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [
{
"rule": "style/*",
"severity": "off"
},
{
"rule": "format/*",
"severity": "off"
},
{
"rule": "*-indent",
"severity": "off"
},
{
"rule": "*-spacing",
"severity": "off"
},
{
"rule": "*-spaces",
"severity": "off"
},
{
"rule": "*-order",
"severity": "off"
},
{
"rule": "*-dangle",
"severity": "off"
},
{
"rule": "*-newline",
"severity": "off"
},
{
"rule": "*quotes",
"severity": "off"
},
{
"rule": "*semi",
"severity": "off"
}
],
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"gql",
"graphql"
],
"typescript.tsdk": "node_modules/typescript/lib",
}
4 changes: 2 additions & 2 deletions bot/src/keepers/collateral.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ const checkAndParticipateIfPossible = async function (network: string, auction:
// 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()}`);
console.info(`DAI VAT profit from the transaction: ${postVatBalanceDai.minus(preVatBalanceDai).toFixed()}`);
console.info(`DAI ERC20 profit from the transaction: ${postErcBalanceDai.minus(preErcBalanceDai).toFixed()}`);
};

const participateInAuction = async function (network: string, auction: AuctionInitialInfo) {
Expand Down
19 changes: 6 additions & 13 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,12 @@ The process of adding new collaterals depends on the token type used. This is du
5. Add new exchange file to the [`calleeFunctions` folder](./src/calleeFunctions)
- The file should be named using the name from `1.`
- The file should export `CalleeFunctions`
- The file should be imported in the [`calleeFunctions/index.ts`](./src/calleeFunctions/index.ts)
3. Adding price oracle configurations for the token:
1. Get the source code of the price oracle contract:
- read value `ilks(collateralType)` from [`Spot` contract](https://etherscan.io/address/0x65c79fcb50ca1594b025960e539ed7a9a6d434a3#code) via "Read Contract" tabl - and receive the address of the oracle for the specified collateral. The linked conract is responsible for updating the unit prices for collaterals.
2. Read the contract and determine the slot address of the variable:
- Generally a slot number can be determined by counting definition of variables in the contract source code, but there are exceptions, [please read the docs on the solidity version the contract was compiled with](https://docs.soliditylang.org/en/v0.8.13/internals/layout_in_storage.html)
- Experimenting with blockchain fork (e.g. hardhat) helps: try to fetch the value you're looking for / overwrite it / ... and validate that it's correct via some public method or comparing against your expectation. See section [Overwriting values of price oracles](./README.md#overwriting-values-of-price-oracles)
3. Extend collateral config with the proper slot addresses.
4. If needed, add the oracle type to `types` file if the existing types are not sufficient to cover for the set of values you need.
4. Run `npm run collateral:onboard` to run the script that helps to choose the oracle config.
- when the script outputs the json with the config, add it to the `oracle` key of the collateral configuration in `COLLATERALS.ts`
- if the script terminates with an error, please submit the report to the repository at https://github.com/sidestream-tech/unified-auctions-ui via an issue so that the support could be added.
- Read more about the collateral oracle configurations at `./README.md#collateral-oracle-configs`
6. Import exchange file inside [`calleeFunctions/index.ts`](./src/calleeFunctions/index.ts) and export under `allCalleeFunctions`

3. Adding price oracle configurations for the new collateral type:

1. Get the source code of the price oracle contract. Read value `ilks(collateralType)` from the [`MCD_SPOT` contract](https://etherscan.io/address/0x65c79fcb50ca1594b025960e539ed7a9a6d434a3#code) via "Read Contract" tab and get the address of the oracle for the specified collateral. The linked conract is responsible for updating the unit prices for collaterals
2. If the contract resembles OSM ([Oracle Security Module](https://github.com/makerdao/osm)) `ORACLE_WITH_DELAY` needs to be used, otherwise `ORACLE_WITHOUT_DELAY`

### Onboarding not yet deployed collateral

Expand Down
4 changes: 1 addition & 3 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
"hardhat:silent": "npx hardhat node &> /dev/null",
"hardhat": "npx hardhat node",
"hardhat:simulations": "npx hardhat --network testnetwork --config local.hardhat.config.ts run ./simulations/index.ts",
"simulate": "npm-run-all --parallel hardhat:silent hardhat:simulations",
"collateral:validate": "npx hardhat --network testnetwork --config local.hardhat.config.ts run ./src/getCollateralPriceOracleConfig.ts",
"collateral:onboard": "npm-run-all --parallel hardhat:silent collateral:validate"
"simulate": "npm-run-all --parallel hardhat:silent hardhat:simulations"
},
"engines": {
"node": ">=16.0.0",
Expand Down
4 changes: 2 additions & 2 deletions core/simulations/configs/onboardNewCollateral.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ const simulation: Simulation = {
console.info(`New ${collateralType} oracle price is ${oraclePrice.toFixed()} DAI`);
// create and liquidate vault
const collateralOwned = await calculateMinCollateralAmountToOpenVault(collateralType);
const vaultId = await createVaultWithCollateral(collateralType, collateralOwned);
const { vaultIndex } = await createVaultWithCollateral(collateralType, collateralOwned);
await warpTime(60 * 24 * 30, 60);
await collectStabilityFees(TEST_NETWORK, collateralType);
const vault = await fetchVault(TEST_NETWORK, vaultId);
const vault = await fetchVault(TEST_NETWORK, vaultIndex);
await liquidateVault(TEST_NETWORK, vault.collateralType, vault.address);
},
},
Expand Down
2 changes: 1 addition & 1 deletion core/simulations/configs/specificBlockFork.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addDaiToBalance, addMkrToBalance } from '../../helpers/hardhat/balance';
import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network';
import promptToGetBlockNumber from '../helpers/promptToGetBlockNumber';
import { promptToGetBlockNumber } from '../helpers/promptToGetNumber';
import { Simulation } from '../types';

const simulation: Simulation = {
Expand Down
94 changes: 62 additions & 32 deletions core/simulations/configs/vaultLiquidation.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network';
import { addDaiToBalance, addMkrToBalance } from '../../helpers/hardhat/balance';
import { Simulation } from '../types';
import { collectStabilityFees, fetchVault, liquidateVault } from '../../src/vaults';
import { collectStabilityFees, liquidateVault } from '../../src/vaults';
import { TEST_NETWORK } from '../../helpers/constants';
import createVaultWithCollateral, {
adjustLimitsAndRates,
calculateMinCollateralAmountToOpenVault,
} from '../helpers/createVaultWithCollateral';
import promptToSelectOneOption from '../helpers/promptToSelectOneOption';
import promptToGetBlockNumber from '../helpers/promptToGetBlockNumber';
import { promptToGetNumber, promptToGetBlockNumber } from '../helpers/promptToGetNumber';
import getProvider from '../../src/provider';

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

const TWO_YEARS_IN_MINUTES = 60 * 24 * 30 * 12 * 2;
import { getCurrentOraclePriceByCollateralType } from '../../src/oracles';
import { overwriteCurrentOraclePrice } from '../../helpers/hardhat/overwrites';
import BigNumber from 'bignumber.js';
import { enrichAuction } from '../../src/auctions';
import { overwriteUintValue } from '../../helpers/hardhat/slotOverwrite';
import { RAY } from '../../src/constants/UNITS';

const simulation: Simulation = {
title: 'Create collateral auction',
Expand All @@ -39,35 +42,51 @@ const simulation: Simulation = {
{
title: 'Create underwater vault',
entry: async context => {
// set oracle price
await overwriteCurrentOraclePrice(TEST_NETWORK, context.collateralType, new BigNumber(1000));
const initialOraclePrice = await getCurrentOraclePriceByCollateralType(
TEST_NETWORK,
context.collateralType
);
console.info(`Initial oracle price is ${initialOraclePrice.toFixed()} DAI`);

await adjustLimitsAndRates(context.collateralType);
const collateralOwned = await calculateMinCollateralAmountToOpenVault(context.collateralType);
console.info(`Minimum collateral amount to open vault: ${collateralOwned.toFixed()}`);
await setCollateralDebtCeilingToGlobal(context.collateralType);
const latestVaultId = await createVaultWithCollateral(
const { vaultIndex, vaultAddress } = await createVaultWithCollateral(
context.collateralType,
collateralOwned.multipliedBy(1)
);
console.info(`Created Vault id: ${latestVaultId}`);

console.info(`Skipping ${TWO_YEARS_IN_MINUTES} minutes...`);
await warpTime(TWO_YEARS_IN_MINUTES, 60);
console.info(`Created Vault with id ${vaultIndex} and address ${vaultAddress}`);

console.info(`Collecting stability fees...`);
const vaultBefore = await fetchVault(TEST_NETWORK, latestVaultId);
console.info(`Stability fee before ${vaultBefore.stabilityFeeRate}`);
// drop oracle price
console.info(`Initial oracle price is ${initialOraclePrice.toFixed()} DAI`);
await overwriteCurrentOraclePrice(TEST_NETWORK, context.collateralType, initialOraclePrice.times(0.5));
const newOraclePrice = await getCurrentOraclePriceByCollateralType(
TEST_NETWORK,
context.collateralType
);
console.info(`New oracle price is ${newOraclePrice.toFixed()} DAI`);
await collectStabilityFees(TEST_NETWORK, context.collateralType);
const vaultAfter = await fetchVault(TEST_NETWORK, latestVaultId);
console.info(`Stability fee after ${vaultAfter.stabilityFeeRate}`);

return { ...context, latestVaultId };
return { ...context, vaultIndex, vaultAddress, initialOraclePrice };
},
},
{
title: 'Liquidate the vault',
entry: async context => {
const liquidatedId = context.latestVaultId;
const vault = await fetchVault(TEST_NETWORK, liquidatedId);
await liquidateVault(TEST_NETWORK, vault.collateralType, vault.address);
const collateralConfig = getCollateralConfigByType(context.collateralType);
try {
// overwrite calc.tau (linear auction price reduction duration)
await overwriteUintValue(collateralConfig.contracts.calc, '0x1', new BigNumber(3000));
} catch {}
try {
// overwrite clip.buf (initial auction price multiplier)
await overwriteUintValue(collateralConfig.contracts.clip, '0x5', RAY.dividedBy(50));
} catch {}
// liquidate
await liquidateVault(TEST_NETWORK, context.collateralType, context.vaultAddress);
return context;
},
},
Expand All @@ -78,25 +97,36 @@ const simulation: Simulation = {
TEST_NETWORK,
context.collateralType
);
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);
let proposedSecondsToWarp = Math.floor(auctionLifetime / 12);
const provider = await getProvider(TEST_NETWORK);
const STEP_SECONDS = 30;
while (true) {
proposedSecondsToWarp = await promptToGetNumber({
title: 'Number of seconds to warp',
initial: proposedSecondsToWarp,
max: auctionLifetime,
});
if (proposedSecondsToWarp === 0) {
try {
await provider.send('evm_mine', []);
console.info(`Mined one block without skipping any time`);
} catch (error) {
console.error('evm_mine failed with', error);
}
} else {
await warpTime(proposedSecondsToWarp, 1);
console.info(`Skipped ${proposedSecondsToWarp} seconds`);
}
const initialAuctions = await fetchAuctionsByCollateralType(TEST_NETWORK, context.collateralType);
if (!initialAuctions[0] || !initialAuctions[0].isActive) {
if (!initialAuctions[0]) {
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);
const auction = await enrichAuction(TEST_NETWORK, initialAuctions[0]);
if (!auction?.isActive) {
console.info('No active auctions are found, exiting the "evm_mine" loop');
break;
}
console.info(`One active auction is still present: ${auction.id}`);
}
},
},
Expand Down
Loading
Loading