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

feat: add programs to test execution nodes #6

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
67 changes: 13 additions & 54 deletions configs/deployed-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"nodeOperatorsRegistryBaseDeployTx": "0x32a2b4ec8b59f2cdde007bbdee23ed1b75491f0ca6acc25d45bf7afbf1c8b4dd",
"depositorDeployTx": "0xce40c18b10854166eb69e64171cbd33ec4ba2f369623f2f438bcf684cfed0523",
"executionLayerRewardsVaultDeployTx": "0xd72cf25e4a5fe3677b6f9b2ae13771e02ad66f8d2419f333bb8bde3147bd4294",
"depositContract": {
"address": "0x00000000219ab540356cBB839Cbe05303d7705Fa"
},
"daoInitialSettings": {
"token": {
"name": "Lido DAO Token",
Expand Down Expand Up @@ -163,9 +166,6 @@
},
"lidoApmDeployTx": "0xfa66476569ecef5790f2d0634997b952862bbca56aa088f151b8049421eeb87b",
"lidoApmAddress": "0x0cb113890b04B49455DfE06554e2D784598A29C9",
"depositContract": {
"address": "0x00000000219ab540356cBB839Cbe05303d7705Fa"
},
"createAppReposTx": "0xf48cb21c6be021dd18bd8e02ce89ac7b924245b859f0a8b7c47e88a39016ed41",
"newDaoTx": "0x3feabd79e8549ad68d1827c074fa7123815c80206498946293d5373a160fd866",
"daoAddress": "0xb8FFC3Cd6e7Cf5a098A1c92F48009765B24088Dc",
Expand Down Expand Up @@ -196,9 +196,7 @@
},
"wstethContractAddress": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"wstethContractDeployTx": "0xaf2c1a501d2b290ef1e84ddcfc7beb3406f8ece2c46dee14e212e8233654ff05",
"wstethContractConstructorArgs": [
"0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"
],
"wstethContractConstructorArgs": ["0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"],
"depositorParams": {
"maxDepositsPerBlock": 150,
"minDepositBlockDistance": 25,
Expand Down Expand Up @@ -327,11 +325,7 @@
"contract": "ValidatorsExitBusOracle",
"implementation": "0xA89Ea51FddE660f67d1850e03C9c9862d33Bc42c",
"address": "0x0De4Ea0184c2ad0BacA7183356Aea5B8d5Bf5c6e",
"constructorArgs": [
12,
1606824023,
"0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb"
],
"constructorArgs": [12, 1606824023, "0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb"],
"proxyConstructorArgs": [
"0x6F6541C2203196fEeDd14CD2C09550dA1CbEDa31",
"0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5",
Expand Down Expand Up @@ -372,29 +366,8 @@
"constructorArgs": [
"0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb",
"0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c",
[
20000,
500,
1000,
50,
600,
2,
100,
7680,
750000
],
[
[],
[],
[],
[],
[],
[],
[],
[],
[],
[]
]
[20000, 500, 1000, 50, 600, 2, 100, 7680, 750000],
[[], [], [], [], [], [], [], [], [], []]
]
},
"oracleDaemonConfig": {
Expand All @@ -411,10 +384,7 @@
},
"contract": "OracleDaemonConfig",
"address": "0xbf05A929c3D7885a6aeAd833a992dA6E5ac23b09",
"constructorArgs": [
"0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5",
[]
]
"constructorArgs": ["0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5", []]
},
"withdrawalQueueERC721": {
"parameters": {
Expand All @@ -424,11 +394,7 @@
"contract": "WithdrawalQueueERC721",
"implementation": "0xE42C659Dc09109566720EA8b2De186c2Be7D94D9",
"address": "0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1",
"constructorArgs": [
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"Lido: stETH Withdrawal NFT",
"unstETH"
],
"constructorArgs": ["0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "Lido: stETH Withdrawal NFT", "unstETH"],
"proxyConstructorArgs": [
"0x6F6541C2203196fEeDd14CD2C09550dA1CbEDa31",
"0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5",
Expand All @@ -439,10 +405,7 @@
"address": "0xB9D7934878B5FB9610B3fE8A5e441e8fad7E293f",
"contract": "WithdrawalVault",
"implementation": "0xCC52f17756C04bBa7E377716d7062fC36D7f69Fd",
"constructorArgs": [
"0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84",
"0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c"
]
"constructorArgs": ["0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", "0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c"]
},
"dummyEmptyContract": {
"contract": "DummyEmptyContract",
Expand All @@ -452,17 +415,13 @@
"eip712StETH": {
"contract": "EIP712StETH",
"address": "0x8F73e4C2A6D852bb4ab2A45E6a9CF5715b3228B7",
"constructorArgs": [
"0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"
]
"constructorArgs": ["0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"]
},
"stakingRouter": {
"contract": "StakingRouter",
"implementation": "0xD8784e748f59Ba711fB5643191Ec3fAdD50Fb6df",
"address": "0xFdDf38947aFB03C621C71b06C9C70bce73f12999",
"constructorArgs": [
"0x00000000219ab540356cBB839Cbe05303d7705Fa"
],
"constructorArgs": ["0x00000000219ab540356cBB839Cbe05303d7705Fa"],
"proxyConstructorArgs": [
"0x6F6541C2203196fEeDd14CD2C09550dA1CbEDa31",
"0x8Ea83AD72396f1E0cD2f8E72b1461db8Eb6aF7B5",
Expand Down Expand Up @@ -497,4 +456,4 @@
"0x"
]
}
}
}
29 changes: 29 additions & 0 deletions programs/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { program } from '@command';
import { getLatestBlock } from '@utils';

const accounts = program.command('chain').description('chain utils');

accounts
.command('latest-block')
.description('get latest block')
.action(async () => {
const block = await getLatestBlock();

const formatOptions: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
hour12: false,
};
const intl = new Intl.DateTimeFormat('en-GB', formatOptions);

console.table({
number: block.number,
hash: block.hash,
timestamp: block.timestamp,
datetime: intl.format(block.timestamp * 1000),
});
});
166 changes: 93 additions & 73 deletions programs/common/consensus.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { authorizedCall, getLatestBlock } from '@utils';
import {authorizedCall, getBlock, getLatestBlock, parseBlock } from '@utils';
import { Command } from 'commander';
import { Contract, EventLog, formatEther } from 'ethers';
import { BlockTag, Contract, EventLog, formatEther } from 'ethers';

export const addConsensusCommands = (command: Command, contract: Contract) => {
command
Expand Down Expand Up @@ -133,83 +133,23 @@ export const addConsensusCommands = (command: Command, contract: Contract) => {

command
.command('closest-report')
.description('returns the closest report')
.action(async () => {
const chainConfig = await contract.getChainConfig();
const frameConfig = await contract.getFrameConfig();

const secondsPerSlot = Number(chainConfig.secondsPerSlot);
const genesisTime = Number(chainConfig.genesisTime);
const slotsPerEpoch = Number(chainConfig.slotsPerEpoch);

const initialEpoch = Number(frameConfig.initialEpoch);
const epochsPerFrame = Number(frameConfig.epochsPerFrame);

const computeFrameIndex = (timestamp: number) => {
const epoch = Math.floor((timestamp - genesisTime) / secondsPerSlot / slotsPerEpoch);
return Math.floor((epoch - initialEpoch) / epochsPerFrame);
};

const getFrame = (frameIndex: number) => {
const frameStartEpoch = Math.floor(initialEpoch + frameIndex * epochsPerFrame);
const frameStartSlot = frameStartEpoch * slotsPerEpoch;
const nextFrameStartSlot = frameStartSlot + epochsPerFrame * slotsPerEpoch;

return {
index: frameIndex,
refSlot: frameStartSlot - 1,
reportProcessingDeadlineSlot: nextFrameStartSlot - 1,
};
};

const formatOptions: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
hour12: false,
};
const intl = new Intl.DateTimeFormat('en-GB', formatOptions);

const slotToTime = (slot: number) => {
const time = (genesisTime + slot * secondsPerSlot) * 1000;
return intl.format(time);
};

const nowUnix = Math.floor(Date.now() / 1000);
const currentSlot = Math.floor((nowUnix - genesisTime) / secondsPerSlot);

const currentFrame = getFrame(computeFrameIndex(nowUnix));
const nextFrame = getFrame(currentFrame.index + 1);
.description('returns the closest report for the latest or specific block')
.option('-b, --block <number>', 'block (number or string)', 'latest')
.action(async (options: { block: string }) => {
const blockTag = parseBlock(options.block);
const report = await getClosestReport(contract, blockTag);

const getFrameSlots = (frame: { refSlot: number; reportProcessingDeadlineSlot: number }) => {
const refSlot = frame.refSlot;
const deadlineSlot = frame.reportProcessingDeadlineSlot;

return [
{ value: 'ref slot', slot: refSlot, time: slotToTime(refSlot) },
{ value: 'deadline slot', slot: deadlineSlot, time: slotToTime(deadlineSlot) },
];
};

console.log('current slot');
console.table([
{
value: 'current slot',
slot: currentSlot,
time: slotToTime(currentSlot),
},
]);
console.log(`closest-report for block ${blockTag}`);
console.log('target slot');
console.table(report.targetSlot);

console.log();
console.log('current report frame');
console.table(getFrameSlots(currentFrame));
console.log('target report frame');
console.table(report.targetReportFrame);

console.log();
console.log('next report frame');
console.table(getFrameSlots(nextFrame));
console.table(report.nextReportFrame);
});

command
Expand Down Expand Up @@ -254,3 +194,83 @@ export const addConsensusCommands = (command: Command, contract: Contract) => {
console.table(groupedByRefSlot);
});
};

/**
* Get closest report for specific slot
*/
export const getClosestReport = async (contract: Contract, blockTag: BlockTag) => {
const isNow = blockTag === 'latest';

const latestBlock = await getBlock(blockTag);
const nowUnix = latestBlock.timestamp;
const chainConfig = await contract.getChainConfig({ blockTag });
const frameConfig = await contract.getFrameConfig({ blockTag });

const secondsPerSlot = Number(chainConfig.secondsPerSlot);
const genesisTime = Number(chainConfig.genesisTime);
const slotsPerEpoch = Number(chainConfig.slotsPerEpoch);

const initialEpoch = Number(frameConfig.initialEpoch);
const epochsPerFrame = Number(frameConfig.epochsPerFrame);

const computeFrameIndex = (timestamp: number) => {
const epoch = Math.floor((timestamp - genesisTime) / secondsPerSlot / slotsPerEpoch);
return Math.floor((epoch - initialEpoch) / epochsPerFrame);
};

const getFrame = (frameIndex: number) => {
const frameStartEpoch = Math.floor(initialEpoch + frameIndex * epochsPerFrame);
const frameStartSlot = frameStartEpoch * slotsPerEpoch;
const nextFrameStartSlot = frameStartSlot + epochsPerFrame * slotsPerEpoch;

return {
index: frameIndex,
refSlot: frameStartSlot - 1,
reportProcessingDeadlineSlot: nextFrameStartSlot - 1,
};
};

const formatOptions: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
hour12: false,
};
const intl = new Intl.DateTimeFormat('en-GB', formatOptions);

const slotToTime = (slot: number) => {
const time = (genesisTime + slot * secondsPerSlot) * 1000;
return intl.format(time);
};

const currentSlot = Math.floor((nowUnix - genesisTime) / secondsPerSlot);

const currentFrame = getFrame(computeFrameIndex(nowUnix));
const nextFrame = getFrame(currentFrame.index + 1);

const getFrameSlots = (frame: { refSlot: number; reportProcessingDeadlineSlot: number }) => {
const refSlot = frame.refSlot;
const deadlineSlot = frame.reportProcessingDeadlineSlot;

return [
{ value: 'ref slot', slot: refSlot, time: slotToTime(refSlot) },
{ value: 'deadline slot', slot: deadlineSlot, time: slotToTime(deadlineSlot) },
];
};

const report = {
targetSlot: [{
value: isNow ? 'current slot' : `slot at ${blockTag}`,
slot: currentSlot,
block: latestBlock.number,
time: slotToTime(currentSlot),
}],
targetReportFrame: getFrameSlots(currentFrame),
nextReportFrame: getFrameSlots(nextFrame)
};

return report;
}
24 changes: 22 additions & 2 deletions programs/dsm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { program } from '@command';
import { dsmContract } from '@contracts';
import { authorizedCall } from '@utils';
import { dsmContract, stakingRouterContract } from '@contracts';
import { authorizedCall, getLatestBlock } from '@utils';
import { addLogsCommands, addParsingCommands } from './common';

const dsm = program.command('dsm').description('interact with deposit security module contract');
Expand Down Expand Up @@ -146,3 +146,23 @@ dsm
.action(async (moduleId) => {
await authorizedCall(dsmContract, 'unpauseDeposits', [moduleId]);
});

dsm
.command('can-deposit-block-distance')
.description('check deposits according to block distance condition')
.argument('<moduleId>', 'staking module id')
.action(async (moduleId) => {
const block = await getLatestBlock();
const lastDepositBlock = await stakingRouterContract.getStakingModuleLastDepositBlock(moduleId);
const minDepositBlockDistance = await dsmContract.getMinDepositBlockDistance();

const result = block.number - lastDepositBlock >= minDepositBlockDistance;

console.table({
blockNumber: block.number,
lastDepositBlock: lastDepositBlock,
minDepositBlockDistance: minDepositBlockDistance,
condition: 'blockNumber - lastDepositBlock >= minDepositBlockDistance',
result: result,
});
});
Loading