Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Update governance action simulation hardhat tasks and documentation #179

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
808bbec
add hardhat tasks for mainnet fork to validate governance actions
Nov 17, 2022
f304e3a
update docs and hardhat tasks for governance action on mainnet fork
Nov 23, 2022
56c9dab
remove unused files
Nov 23, 2022
e95be39
cleanup gov hardhat task file
Nov 23, 2022
2080fb7
update governance action validation hardhat task
Nov 24, 2022
09446a0
use token symbol in gov task
Nov 24, 2022
07ec857
process addresses in batches
Nov 24, 2022
02b5a12
remove unused json file
Nov 24, 2022
6bb3f18
update log formatting
Nov 24, 2022
73a6441
remove unussed files
Nov 24, 2022
d5d84f1
add spy urlin output
Nov 24, 2022
7c0b858
add wBTC address to mainnet token setup for token lookup
Nov 24, 2022
f54f0bf
remove unused files
Nov 24, 2022
782ba05
update docs for governance action validation
Nov 25, 2022
23d287f
log number of account remaining to parse
Nov 25, 2022
c090052
remove unused variable
Nov 25, 2022
70e07cf
resolve pr comments
Nov 25, 2022
1fa7a69
remove unused files
Nov 25, 2022
23484a4
update docs for governance action validation
Nov 25, 2022
014edf8
update docs for governance action validation
Nov 25, 2022
b4d2ad9
update mainnet token setup with uni and link addresses
Dec 14, 2022
abf94fe
fix node provider bug in events parsing for governance action simulation
Dec 14, 2022
00311dd
update docs
Dec 14, 2022
bb0a402
merge with master and resolve conflicts
Dec 14, 2022
7e2e9e3
update hardhat task for gov action simulation
Dec 14, 2022
d87e071
fix bugs in governance action simulation tasks and update docs
Dec 14, 2022
1c909ce
update governance task
Dec 14, 2022
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
4 changes: 3 additions & 1 deletion docs/governance-action-validaton.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ Run the following command in a new tab with the latest block number:
For all the addresses that have entered a market based on logs from the `EnterMarket` event in `BaseLogic.sol`, we want to extract the address, the health score of the address which will be used to determine whether or not the address is in violation or at risk of liquidation.

Run the following command:
`npx hardhat --network localhost gov:forkAccountsAndHealthScores <fileName>`
`npx hardhat --network localhost gov:forkAccountsAndHealthScores <blockNumber forked above> <fileName>`

Note: the `fileName` parameter is needed to store the extracted data in a `.json` file in the project root folder for a later action, i.e., doing a difference check of the health scores before and after the governance action.
This file can be deleted later on in step 6 if not required.

Also, if there are any errors where an account cannot be parsed, the error reason will be logged in a `.json` file with the name prefixed with `error_` followed by the filename specified above.

### 4. Perform a governance action on the mainnet fork

The available actions can be found in the file `tasks/gov.js` and require the `--isFork` option to be `true`.
Expand Down
80 changes: 58 additions & 22 deletions tasks/gov.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,39 @@ task("gov:setChainlinkPriceFeed")


task("gov:forkAccountsAndHealthScores", "Get all unique accounts that have entered an Euler market and their health scores")
.addPositionalParam("blockNumber")
.addPositionalParam("filename", "file name without .json suffix")
.setAction(async ({ filename }) => {
.setAction(async ({ blockNumber, filename }) => {
const fs = require("fs");

const et = require("../test/lib/eTestLib");
const { ctx, } = await setupGovernanceFork();

const transactions = await ctx.contracts.euler.queryFilter(
"EnterMarket",
"earliest",
"latest",
);
const eulerDeploymentBlock = 13687582;
const latestBlock = blockNumber;

let batchSize = 2000;
let transactions = [];
let tempStart = eulerDeploymentBlock;
let endBlock = 0;

while (endBlock < latestBlock) {
let start = tempStart;
let end = Math.min(tempStart + batchSize, latestBlock);
const tempTxs = await ctx.contracts.euler.queryFilter(
"EnterMarket",
(ethers.BigNumber.from(start)).toHexString(), // can also be "earliest",
(ethers.BigNumber.from(end)).toHexString(), // and "latest",
// but RPC URL/node providers i.e., alchemy and rivet will throw an error
// if we process more than 2k events at once
// so its done in batches of 2k
);
if (tempTxs.length > 0) {
transactions.push(...tempTxs);
}
tempStart = end + 1;
endBlock = end;
}

let result = [];
for (let i = 0; i < transactions.length; i++) {
Expand All @@ -146,30 +167,45 @@ task("gov:forkAccountsAndHealthScores", "Get all unique accounts that have enter

// compute health scores
let health_scores = {};

let errors = {};

console.log(`Number of unique addresses to parse in batches: ${uniqueAddresses.length}`);

while (uniqueAddresses.length > 0) {
const chunkSize = 100;
const chunkSize = 50;
const batch = uniqueAddresses.splice(0, chunkSize);

console.log(`Accounts remaining to parse: ${uniqueAddresses.length}\n`);

await Promise.all(batch.map(async account => {
let status = await ctx.contracts.exec.liquidity(account);
let collateralValue = status.collateralValue;
let liabilityValue = status.liabilityValue;
let healthScore = liabilityValue == 0 ? ethers.constants.MaxUint256 : (collateralValue * et.c1e18) / liabilityValue;

health_scores[account] = {
health: healthScore / et.c1e18,
collateralValue,
liabilityValue
};
try {
let status = await ctx.contracts.exec.liquidity(account);
let collateralValue = status.collateralValue;
let liabilityValue = status.liabilityValue;
let healthScore = liabilityValue == 0 ? ethers.constants.MaxUint256 : (collateralValue * et.c1e18) / liabilityValue;

health_scores[account] = {
health: healthScore / et.c1e18,
collateralValue,
liabilityValue
};
} catch (e) {
let spyModeURL = `https://app.euler.finance/account/0?spy=${account}`;
let errorLog = {
account,
error: `Please inspect account. Failed to get liquidity for ${account} with error: ${e.message}`,
spyModeURL
};
errors[account] = errorLog;
}
}));
}

let outputJson = JSON.stringify(health_scores);
let outputJson = JSON.stringify(health_scores, null, 2);
fs.writeFileSync(`${filename}.json`, outputJson + "\n");

outputJson = JSON.stringify(errors, null, 2);
fs.writeFileSync(`errors_${filename}.json`, outputJson + "\n");
});


Expand Down Expand Up @@ -197,7 +233,7 @@ task("gov:forkHealthScoreDiff", "Compare the health scores of accounts from a pa
let collateralValueAfter = ethers.utils.formatEther(post_gov_scores[account].collateralValue.hex);
let liabilityValueAfter = ethers.utils.formatEther(post_gov_scores[account].liabilityValue.hex);
let spyModeURL = `https://app.euler.finance/account/0?spy=${account}`;

let result = {
account,
spyModeURL,
Expand All @@ -210,13 +246,13 @@ task("gov:forkHealthScoreDiff", "Compare the health scores of accounts from a pa
}
if (
pre_gov_scores[account].health > 1.15 &&
post_gov_scores[account].health >= 1 &&
post_gov_scores[account].health >= 0.99 &&
post_gov_scores[account].health <= 1.15
) {
accountsAtRisk.push(result);
} else if (
pre_gov_scores[account].health > 1 &&
post_gov_scores[account].health < 1
post_gov_scores[account].health < 0.99
) {
accountsInViolation.push(result);
}
Expand Down
6 changes: 6 additions & 0 deletions test/lib/token-setups/mainnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,11 @@ module.exports = {
WBTC: {
address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
},
UNI: {
address: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
},
LINK: {
address: "0x514910771AF9Ca656af840dff83E8264EcF986CA"
},
},
};