Skip to content

Commit

Permalink
test: update integration test codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
tamtamchik committed Jul 11, 2024
1 parent 3733732 commit 57a965a
Show file tree
Hide file tree
Showing 26 changed files with 1,334 additions and 1,264 deletions.
6 changes: 3 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4

[*.{js,yml,json,cjs,ts}]
indent_size = 2

[*.sol]
indent_size = 4
28 changes: 15 additions & 13 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
{
"parser": "@typescript-eslint/parser",
"extends": ["plugin:@typescript-eslint/recommended", "prettier"],
"parserOptions": { "ecmaVersion": 2022, "sourceType": "module", "project": ["./tsconfig.json"] },
"parserOptions": {
"ecmaVersion": 2022, "sourceType": "module", "project": ["./tsconfig.json"]
},
"plugins": ["no-only-tests", "simple-import-sort"],
"rules": {
"@typescript-eslint/no-explicit-any": ["warn"],
"@typescript-eslint/no-unused-vars": ["warn"],
"@typescript-eslint/no-floating-promises": ["warn"],
"@typescript-eslint/consistent-type-imports": ["error"],
"@typescript-eslint/consistent-type-exports": ["error"],
"@typescript-eslint/no-shadow": ["error"],
// prevents committing `describe.only` and `it.only` tests
"no-only-tests/no-only-tests": "warn",
"no-shadow": "off",
"simple-import-sort/imports": [
"error",
{
"error", {
"groups": [
["^node:"],
["^\\u0000"],
Expand All @@ -22,17 +27,14 @@
["^test"],
["^../"],
["^./"],
["^"],
],
},
],
["^"]
]
}
]
},
"overrides": [
{
"files": ["./scripts/{**/,}*.js", "./test/{**/,}*.js"],
"env": {
"mocha": true,
},
},
],
"files": ["./scripts/{**/,}*.js", "./test/{**/,}*.js"], "env": {"mocha": true}
}
]
}
9 changes: 6 additions & 3 deletions lib/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,12 @@ log.trace = (
) => {
const color = tx.status ? gr : rd;

log(`Transaction sent`, yl(tx.hash));
log(` Gas price: ${yl(tx.gasPrice)} gwei Gas limit: ${yl(tx.gasLimit)} Nonce: ${yl(tx.nonce)}`);
log(` Block: ${yl(tx.blockNumber)} Gas used: ${yl(tx.gasUsed)} (${yl(tx.gasUsedPercent)}%)`);
const value = tx.value === "0.0" ? "" : `Value: ${yl(tx.value)} ETH`;

log(`Transaction sent:`, yl(tx.hash));
log(` From: ${yl(tx.from)} To: ${yl(tx.to)} ${value}`);
log(` Gas price: ${yl(tx.gasPrice)} gwei Gas limit: ${yl(tx.gasLimit)} Gas used: ${yl(tx.gasUsed)} (${yl(tx.gasUsedPercent)})`);
log(` Block: ${yl(tx.blockNumber)} Nonce: ${yl(tx.nonce)}`);
log(` ${color(name)} ${color(tx.status ? "confirmed" : "failed")}`);
log.emptyLine();
};
22 changes: 22 additions & 0 deletions lib/protocol/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ether, impersonate } from "lib";

import { discover } from "./discovery";
import { ProtocolContext, ProtocolSigners } from "./types";

type Signer = string | keyof ProtocolSigners;

const getSigner = async (signer: Signer, balance = ether("100"), signers: ProtocolSigners) => {
// @ts-expect-error TS7053
const signerAddress = signers[signer] ?? signer;
return impersonate(signerAddress, balance);
};

export const getProtocolContext = async (): Promise<ProtocolContext> => {
const { contracts, signers } = await discover();

return {
contracts,
signers,
getSigner: async (signer: Signer, balance?: bigint) => getSigner(signer, balance, signers)
};
};
143 changes: 143 additions & 0 deletions lib/protocol/discovery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import hre from "hardhat";

import { AccountingOracle, Lido, LidoLocator, StakingRouter } from "typechain-types";

import { batch, log } from "lib";

import { networks } from "./networks";
import {
AragonContracts,
ContractName,
ContractType,
FoundationContracts,
HashConsensusContracts,
LoadedContract,
ProtocolContracts,
ProtocolSigners,
StackingModulesContracts
} from "./types";

// TODO: inflate config from whatever source is available (yaml, json, etc)

const guard = (address: string, env: string) => {
if (!address) throw new Error(`${address} address is not set, please set it in the environment variables: ${env}`);
};

const getDiscoveryConfig = () => {
const config = networks.get(hre.network.name);

if (!config) {
throw new Error(`Network ${hre.network.name} is not supported`);
}

const locatorAddress = process.env[config.env.locator] ?? config.defaults.locator ?? "";
const agentAddress = process.env[config.env.agent] ?? config.defaults.agent ?? "";
const votingAddress = process.env[config.env.voting] ?? config.defaults.voting ?? "";
const easyTrackExecutorAddress = process.env[config.env.easyTrack] ?? config.defaults.easyTrack ?? "";

guard(locatorAddress, config.env.locator);
guard(agentAddress, config.env.agent);
guard(votingAddress, config.env.voting);

log.debug("Discovery config", {
"Network": hre.network.name,
"Locator address": locatorAddress,
"Agent address": agentAddress,
"Voting address": votingAddress,
"Easy track executor address": easyTrackExecutorAddress
});

return {
locatorAddress,
agentAddress,
votingAddress,
easyTrackExecutorAddress
};
};

/**
* Load contract by name and address.
*/
const loadContract = async <Name extends ContractName>(name: Name, address: string) => {
const contract = await hre.ethers
.getContractAt(name, address) as unknown as LoadedContract<ContractType<Name>>;
contract.address = address;
return contract;
};

/**
* Load all Lido protocol foundation contracts.
*/
const getFoundationContracts = async (locator: LoadedContract<LidoLocator>) => (await batch({
accountingOracle: loadContract("AccountingOracle", await locator.accountingOracle()),
depositSecurityModule: loadContract("DepositSecurityModule", await locator.depositSecurityModule()),
elRewardsVault: loadContract("LidoExecutionLayerRewardsVault", await locator.elRewardsVault()),
legacyOracle: loadContract("LegacyOracle", await locator.legacyOracle()),
lido: loadContract("Lido", await locator.lido()),
oracleReportSanityChecker: loadContract("OracleReportSanityChecker", await locator.oracleReportSanityChecker()),
burner: loadContract("Burner", await locator.burner()),
stakingRouter: loadContract("StakingRouter", await locator.stakingRouter()),
validatorsExitBusOracle: loadContract("ValidatorsExitBusOracle", await locator.validatorsExitBusOracle()),
withdrawalQueue: loadContract("WithdrawalQueueERC721", await locator.withdrawalQueue()),
withdrawalVault: loadContract("WithdrawalVault", await locator.withdrawalVault()),
oracleDaemonConfig: loadContract("OracleDaemonConfig", await locator.oracleDaemonConfig())
}) as FoundationContracts);

/**
* Load Aragon contracts required for protocol.
*/
const getAragonContracts = async (lido: LoadedContract<Lido>) => {
const kernelAddress = await lido.kernel();
const kernel = await loadContract("Kernel", kernelAddress);
return await batch({
kernel: new Promise(resolve => resolve(kernel)), // Avoiding double loading
acl: loadContract("ACL", await kernel.acl())
}) as AragonContracts;
};

/**
* Load staking modules contracts registered in the staking router.
*/
const getStakingModules = async (stakingRouter: LoadedContract<StakingRouter>) => {
const [nor, sdvt] = await stakingRouter.getStakingModules();
return await batch({
nor: loadContract("NodeOperatorsRegistry", nor.stakingModuleAddress),
sdvt: loadContract("NodeOperatorsRegistry", sdvt.stakingModuleAddress)
}) as StackingModulesContracts;
};

/**
* Load HashConsensus contract for accounting oracle.
*/
const getHashConsensus = async (accountingOracle: LoadedContract<AccountingOracle>) => {
const hashConsensusAddress = await accountingOracle.getConsensusContract();
return await batch({
hashConsensus: loadContract("HashConsensus", hashConsensusAddress)
}) as HashConsensusContracts;
};

export async function discover() {
const networkConfig = getDiscoveryConfig();
const locator = await loadContract("LidoLocator", networkConfig.locatorAddress);
const foundationContracts = await getFoundationContracts(locator);

const contracts = {
locator,
...foundationContracts,
...await getAragonContracts(foundationContracts.lido),
...await getStakingModules(foundationContracts.stakingRouter),
...await getHashConsensus(foundationContracts.accountingOracle)
} as ProtocolContracts;

log.debug("Contracts discovered", contracts);

const signers = {
agent: networkConfig.agentAddress,
voting: networkConfig.votingAddress,
easyTrack: networkConfig.easyTrackExecutorAddress
} as ProtocolSigners;

log.debug("Signers discovered", signers);

return { contracts, signers };
}
Loading

0 comments on commit 57a965a

Please sign in to comment.