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

rETH onboarding #506

Merged
merged 21 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
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
3 changes: 3 additions & 0 deletions core/bytecode/compiledSpells.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion core/helpers/hardhat/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { overwriteUintMappingInAddress, runBalanceSlotDiscoveryLoopForERC20Token
export const determineBalanceSlot = async (
collateralType: CollateralType
): Promise<[string, 'vyper' | 'solidity'] | [null, null]> => {
console.info('Determining balance slot...');
const collateralConfig = getCollateralConfigByType(collateralType);
const tokenContractAddress = await getContractAddressByName(TEST_NETWORK, collateralConfig.symbol);
try {
Expand Down
21 changes: 21 additions & 0 deletions core/helpers/hardhat/overwrites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import BigNumber from '../../src/bignumber';
import { ethers } from 'ethers';
import { getCollateralConfigByType } from '../../src/constants/COLLATERALS';
import { DAI_NUMBER_OF_DIGITS } from '../../src/constants/UNITS';
import executeTransaction from '../../src/execute';
import createStructCoder from '../../src/helpers/createStructCoder';
import { getOracleAddressByCollateralType } from '../../src/oracles';
import { overwriteUintValueInAddress } from './slotOverwrite';

export const overwriteCurrentOraclePrice = async (network: string, collateralType: string, amount: BigNumber) => {
const collateralConfig = getCollateralConfigByType(collateralType);
const oracleAddress = await getOracleAddressByCollateralType(network, collateralType);
const amoutInteger = amount.shiftedBy(DAI_NUMBER_OF_DIGITS).toFixed();
const valueWithValidity = createStructCoder().encode(['uint128', 'uint128'], ['1', amoutInteger]);
await overwriteUintValueInAddress(
oracleAddress,
collateralConfig.oracle.currentPriceSlotAddress,
valueWithValidity
);
await executeTransaction(network, 'MCD_SPOT', 'poke', [ethers.utils.formatBytes32String(collateralType)]);
};
4 changes: 2 additions & 2 deletions core/helpers/hardhat/slotOverwrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ export const generateMappingSlotAddress = (
export const overwriteUintValueInAddress = async (
address: string,
slotAddress: string,
newValue: BigNumber,
newValue: BigNumber | string,
provider: EthereumProvider = hre.network.provider
) => {
const hexValue = formatToHex(newValue, 32);
const hexValue = typeof newValue === 'string' ? newValue : formatToHex(newValue, 32);
const storageToWrite = [address, slotAddress, hexValue];
await provider.send('hardhat_setStorageAt', storageToWrite);
};
Expand Down
4 changes: 3 additions & 1 deletion core/simulations/config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Simulation } from './types';
import debtAuctionSimulation from './configs/createDebtAuctionSimulation';
import surplusAuctionBlockchain from './configs/surplusAuctionSimulation';
import wstethAuctionSimulation from './configs/wstethAuctionSimulation';
import surplusAuctionSimulation from './configs/createSurplusAcutionSimulation';
import blockWithVaultsInAllStates from './configs/blocksWithVaultsInAllStates';
import vaultLiquidation from './configs/vaultLiquidation';
import { Simulation } from './types';
import onboardNewCollateral from './configs/onboardNewCollateral';

export const SIMULATIONS: Simulation[] = [
debtAuctionSimulation,
Expand All @@ -13,4 +14,5 @@ export const SIMULATIONS: Simulation[] = [
wstethAuctionSimulation,
blockWithVaultsInAllStates,
vaultLiquidation,
onboardNewCollateral,
];
76 changes: 76 additions & 0 deletions core/simulations/configs/onboardNewCollateral.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import BigNumber from '../../src/bignumber';
import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network';
import { addDaiToBalance } from '../../helpers/hardhat/balance';
import { Simulation } from '../types';
import { getAllCollateralTypes } from '../../src/constants/COLLATERALS';
import { collectStabilityFees, fetchVault, liquidateVault } from '../../src/vaults';
import { TEST_NETWORK } from '../../helpers/constants';
import createVaultWithCollateral, {
calculateMinCollateralAmountToOpenVault,
} from '../helpers/createVaultWithCollateral';
import deploySpell, { getAllSpellNames } from '../helpers/deploySpell';
import executeSpell from '../helpers/executeSpell';
import { getCurrentOraclePriceByCollateralType } from '../../src/oracles';
import { overwriteCurrentOraclePrice } from '../../helpers/hardhat/overwrites';
import promptToSelectOneOption from '../helpers/promptToSelectOneOption';

const simulation: Simulation = {
title: 'Onboard new collateral',
steps: [
{
title: 'Reset blockchain fork and add balances',
entry: async () => {
await resetNetworkAndSetupWallet(15791971);
await addDaiToBalance();
},
},
{
title: 'Deploy the spell',
entry: async () => {
const spellName = await promptToSelectOneOption(
'Select the spell you want to deploy',
getAllSpellNames()
);
const spellAddress = await deploySpell(TEST_NETWORK, spellName);
return {
spellAddress,
};
},
},
{
title: 'Execute the spell',
entry: async context => {
await executeSpell(context.spellAddress);
},
},
{
title: 'Create new auction',
entry: async () => {
const collateralType = await promptToSelectOneOption(
'Select the collateral symbol to add to the VAT',
getAllCollateralTypes()
);
// overwrite oracle price
await overwriteCurrentOraclePrice(TEST_NETWORK, collateralType, new BigNumber(1000));
const oraclePrice = await getCurrentOraclePriceByCollateralType(TEST_NETWORK, collateralType);
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);
await warpTime(60 * 24 * 30, 60);
await collectStabilityFees(TEST_NETWORK, collateralType);
const vault = await fetchVault(TEST_NETWORK, vaultId);
await liquidateVault(TEST_NETWORK, vault.collateralType, vault.address);
},
},
{
title: 'Skip time',
entry: async context => {
await warpTime(60, 60);
return context;
},
},
],
};

export default simulation;
56 changes: 12 additions & 44 deletions core/simulations/configs/vaultLiquidation.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,13 @@
import { warpTime, resetNetworkAndSetupWallet } from '../../helpers/hardhat/network';
import { addDaiToBalance, addMkrToBalance } from '../../helpers/hardhat/balance';
import { Simulation } from '../types';
import prompts from 'prompts';
import COLLATERALS from '../../src/constants/COLLATERALS';
import { collectStabilityFees, fetchVault, liquidateVault } from '../../src/vaults';
import { TEST_NETWORK } from '../../helpers/constants';
import createVaultWithCollateral, {
calculateMinCollateralAmountToOpenVault,
getLiquidatableCollateralTypes,
} from '../helpers/createVaultWithCollateral';

const UNSUPPORTED_COLLATERAL_TYPES = [
'CRVV1ETHSTETH-A', // collateral handled differently
'UNIV2DAIUSDC-A', // Liquidation limit too high (fails with "Dog/liquidation-limit-hit")
'WSTETH-B', // does not accumulate stability fee rate at all.
];

export const getLiquidatableCollateralTypes = () => {
return Object.keys(COLLATERALS).filter(collateralType => !UNSUPPORTED_COLLATERAL_TYPES.includes(collateralType));
};

const getCollateralType = async () => {
const { collateralType } = await prompts([
{
type: 'select',
name: 'collateralType',
message: 'Select the collateral symbol to add to the VAT.',
choices: getLiquidatableCollateralTypes()
.sort()
.map(collateral => ({
title: collateral,
value: collateral,
})),
},
]);
return collateralType;
};

const getBaseContext = async () => {
const collateralType = await getCollateralType();
const decimals = COLLATERALS[collateralType].decimals;
const collateralOwned = await calculateMinCollateralAmountToOpenVault(collateralType);

console.info(`Collateral in the VAT initially: ${collateralOwned.toFixed()}`);
return {
collateralType,
decimals,
collateralOwned,
};
};
import promptToSelectOneOption from '../helpers/promptToSelectOneOption';

const simulation: Simulation = {
title: 'Simulate liquidation Auctions',
Expand All @@ -56,13 +16,21 @@ const simulation: Simulation = {
title: 'Reset blockchain fork',
entry: async () => {
await resetNetworkAndSetupWallet();
return getBaseContext();
const collateralType = await promptToSelectOneOption(
'Select the collateral symbol to add to the VAT.',
getLiquidatableCollateralTypes()
);
return {
collateralType,
};
},
},
{
title: 'Create the vault',
entry: async context => {
const latestVaultId = await createVaultWithCollateral(context.collateralType, context.collateralOwned);
const collateralOwned = await calculateMinCollateralAmountToOpenVault(context.collateralType);
console.info(`Minimum collateral amount to open vault: ${collateralOwned.toFixed()}`);
const latestVaultId = await createVaultWithCollateral(context.collateralType, collateralOwned);
return { ...context, latestVaultId };
},
},
Expand Down
85 changes: 85 additions & 0 deletions core/simulations/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
FROM vulcanize/dapptools:v0.30.0-v1.10.16-statediff-3.0.2a

ENTRYPOINT ["tail", "-f", "/dev/null"]

# # RUN nix-shell --pure -p cacert cachix curl git jq nix gnumake nano --run "bash docker/install.sh"
# RUN nix-shell -p cacert cachix curl git jq nix gnumake nano
# RUN dapp --version
# RUN seth --version

# # edit nix.conf to add filter-syscalls = false
# RUN echo 'filter-syscalls = false' >> /etc/nix/nix.conf

# RUN git clone https://github.com/makerdao/spells-mainnet spells
# WORKDIR /root/spells
# RUN git checkout CES-795
# RUN dapp update

# # prepare keys
# RUN echo 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' > ../private-key
# RUN echo '' > ../key-password
# # RUN (printf "\n\n" && cat) | geth account import --datadir /root ../private-key
# ENV ETH_FROM="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
# ENV ETH_KEYSTORE="/root/keystore"
# ENV ETH_PASSWORD="/root/key-password"
# ENV ETH_RPC_URL=http://core:8545
# ENV ETH_GAS=30000000
# ENV ETH_GAS_PRICE=1000000000000
# RUN make
# RUN dapp create DssSpell

# ENTRYPOINT [ "sh" ]

# FROM ubuntu:20.04 as base-installs

# RUN apt-get update && apt-get -y install curl xz-utils git make

# FROM base-installs as tool-installs

# RUN useradd -s /bin/bash -d /home/blockchain/ -m -G sudo blockchain
# RUN mkdir -m 0755 /nix && chown blockchain /nix
# RUN sysctl kernel.unprivileged_userns_clone=1
# USER blockchain
# ENV USER="blockchain"
# ENV HOME="/home/${USER}"
# ENV PATH="${HOME}/.nix-profile/bin:${PATH}"
# ENV NIX_PATH="${HOME}/.nix-defexpr/channels"
# RUN curl -L https://nixos.org/nix/install | sh -s -- --no-daemon
# RUN nix --version
# RUN mkdir /nix/store
# RUN curl -L https://dapp.tools/install | sh
# CMD ["/bin/bash"]

# # RUN seth --version

# # FROM tool-installs as base-clones

# # USER blockchain
# # RUN mkdir /home/blockchain/spells
# # WORKDIR /home/blockchain/spells
# # COPY ./onboard.sh .
# # RUN git clone https://github.com/makerdao/spells-mainnet.git
# # RUN git clone https://github.com/makerdao/exchange-callees.git

# # FROM base-clones as cast-spell-base

# # ARG ETH_RPC_URL
# # ENV ETH_RPC_URL=${ETH_RPC_URL}
# # ARG ETH_GAS
# # ENV ETH_GAS=${ETH_GAS}
# # ARG ETH_FROM
# # ENV ETH_FROM=${ETH_FROM}


# # ENV USER="blockchain"
# # ENV HOME="/home/${USER}"
# # ENV PATH="${HOME}/.nix-profile/bin:${PATH}"

# # USER blockchain
# # RUN export ETH_GAS_PRICE=$(seth --to-wei 100 "gwei")
# # WORKDIR /home/blockchain/spells/spells-mainnet
# # RUN echo "export ETH_RPC_ACCOUNTS=yes" >> /home/blockchain/.sethrc

# # FROM cast-spell-base as cast-spell-execute

# # CMD ["../onboard.sh"]
21 changes: 21 additions & 0 deletions core/simulations/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: '3'

services:

spells:
restart: "no"
build:
context: .

core:
restart: "no"
ports:
- '8545:8545'
expose:
- 8545
env_file:
- '../../.env'
build:
context: ../../../
dockerfile: ./core/Dockerfile
target: hardhat
16 changes: 14 additions & 2 deletions core/simulations/helpers/createVaultWithCollateral.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ethers } from 'ethers';
import BigNumber from '../../src/bignumber';
import { setCollateralInVat } from '../../helpers/hardhat/balance';
import { getCollateralConfigByType } from '../../src/constants/COLLATERALS';
import BigNumber from '../../src/bignumber';
import { changeVaultContents, fetchVault, openVault, fetchVaultCollateralParameters } from '../../src/vaults';
import { HARDHAT_PUBLIC_KEY, TEST_NETWORK } from '../../helpers/constants';
import {
Expand All @@ -17,9 +18,20 @@ import {
} from '../../src/wallet';
import { MAX } from '../../src/constants/UNITS';
import { CollateralConfig, CollateralType } from '../../src/types';
import { ethers } from 'ethers';
import { roundDownToFirstSignificantDecimal, roundUpToFirstSignificantDecimal } from '../../helpers/hex';
import { determineBalanceSlot, setCollateralInWallet } from '../../helpers/hardhat/erc20';
import { getAllCollateralTypes } from '../../src/constants/COLLATERALS';

const UNSUPPORTED_COLLATERAL_TYPES = [
'CRVV1ETHSTETH-A', // Collateral handled differently
'UNIV2DAIUSDC-A', // Liquidation limit too high (fails with "Dog/liquidation-limit-hit")
'WSTETH-B', // Does not accumulate stability fee rate at all
'RETH-A', // [temporary] this collateral is not yet deployed, tested via different flow
];

export const getLiquidatableCollateralTypes = () => {
return getAllCollateralTypes().filter(collateralType => !UNSUPPORTED_COLLATERAL_TYPES.includes(collateralType));
};

const setAndCheckCollateralInVat = async (collateralType: CollateralType, collateralOwned: BigNumber) => {
console.info(`Setting ${collateralType} balance in VAT...`);
Expand Down
25 changes: 25 additions & 0 deletions core/simulations/helpers/deploySpell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ethers } from 'ethers';
import getSigner from '../../src/signer';
import compiledSpells from '../../bytecode/compiledSpells.json';

export const getAllSpellNames = function (): string[] {
return Object.keys(compiledSpells).sort();
};

const deploySpell = async function (network: string, name: string): Promise<string> {
console.info(`Deploying spell "${name}"`);

if (!(name in compiledSpells)) {
throw new Error(`spel "${name}" not found in compiled spells`);
}
const bytecode: string = (compiledSpells as Record<string, string>)[name];

const signer = await getSigner(network);
const factory = new ethers.ContractFactory([], bytecode, signer);
const contract = await factory.deploy();
await contract.deployTransaction.wait();
console.info(`Spell has been deployed at ${contract.address}`);
return contract.address;
};

export default deploySpell;
Loading