diff --git a/.env.example b/.env.example index 4d242b2..e9ba4d8 100644 --- a/.env.example +++ b/.env.example @@ -2,11 +2,15 @@ ETH_NETWORK=1 EL_RPC_URLS=https://mainnet.infura.io/v3/... CL_API_URLS=https://quiknode.pro/... -LIDO_STAKING_MODULE_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6320 +CSM_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6320 +VERIFIER_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6321 +TX_SIGNER_PRIVATE_KEY=0x... # Daemon working mode ETH_NETWORK=1 EL_RPC_URLS=https://mainnet.infura.io/v3/... CL_API_URLS=https://quiknode.pro/... KEYSAPI_API_URLS=https://keys-api.lido.fi/ -LIDO_STAKING_MODULE_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6320 +CSM_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6320 +VERIFIER_ADDRESS=0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6321 +TX_SIGNER_PRIVATE_KEY=0x... diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 3652316..26344e0 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -32,5 +32,8 @@ jobs: - name: Install Node dependencies run: yarn install --frozen-lockfile --non-interactive + - name: Generate types + run: yarn typechain + - name: Linters check run: yarn lint diff --git a/.gitignore b/.gitignore index 7834f27..693c23e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ /dist /node_modules +# generated files +/src/common/contracts/types + # ENV /.env diff --git a/README.md b/README.md index c5e05d7..ae5dad2 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ If any of these time thresholds are breached, we can't be sure that if there was ```bash $ yarn install +$ yarn run typechain ``` ## Running the app diff --git a/package.json b/package.json index 4bf859f..12fa7c6 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "private": true, "license": "GPL-3.0", "scripts": { + "typechain": "typechain --target=ethers-v5 --out-dir src/common/contracts/types src/common/contracts/abi/*.json", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", @@ -23,6 +24,8 @@ }, "dependencies": { "@huanshiwushuang/lowdb": "^6.0.2", + "@lido-nestjs/constants": "^5.2.1", + "@lido-nestjs/execution": "^1.12.0", "@lido-nestjs/logger": "^1.3.2", "@lodestar/params": "^1.16.0", "@lodestar/types": "^1.15.0", @@ -30,16 +33,19 @@ "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", + "@typechain/ethers-v5": "^11.1.2", "@types/cli-progress": "^3.11.5", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "cli-progress": "^3.12.0", + "ethers": "^5.7.2", "nest-commander": "^3.12.5", "nest-winston": "^1.9.4", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", "stream-chain": "^2.2.5", "stream-json": "^1.8.0", + "typechain": "^8.3.2", "undici": "^6.4.0", "winston": "^3.11.0" }, diff --git a/src/common/config/env.validation.ts b/src/common/config/env.validation.ts index 4d242ae..d1e6705 100644 --- a/src/common/config/env.validation.ts +++ b/src/common/config/env.validation.ts @@ -11,6 +11,7 @@ import { IsString, Max, Min, + ValidateIf, validateSync, } from 'class-validator'; @@ -43,7 +44,42 @@ export class EnvironmentVariables { @IsNotEmpty() @IsString() - public LIDO_STAKING_MODULE_ADDRESS: string; + public CSM_ADDRESS: string; + + @IsNotEmpty() + @IsString() + public VERIFIER_ADDRESS: string; + + @IsNotEmpty() + @IsString() + @ValidateIf((vars) => !vars.DRY_RUN) + public TX_SIGNER_PRIVATE_KEY: string; + + @IsNumber() + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_MIN_GAS_PRIORITY_FEE = 50_000_000; // 0.05 gwei + + @IsNumber() + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_MAX_GAS_PRIORITY_FEE = 10_000_000_000; // 10 gwei + + @IsNumber() + @Max(100) + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_GAS_PRIORITY_FEE_PERCENTILE = 25; + + @IsNumber() + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_GAS_FEE_HISTORY_DAYS = 1; + + @IsNumber() + @Max(100) + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_GAS_FEE_HISTORY_PERCENTILE = 20; + + @IsNumber() + @Transform(({ value }) => parseInt(value, 10), { toClassOnly: true }) + public TX_GAS_LIMIT = 1_000_000; @IsNumber() @Min(30 * MINUTE) @@ -68,6 +104,7 @@ export class EnvironmentVariables { LOG_FORMAT: LogFormat = LogFormat.Simple; @IsBoolean() + @Transform(({ value }) => toBoolean(value), { toClassOnly: true }) public DRY_RUN = false; @IsNotEmpty() @@ -145,3 +182,31 @@ export function validate(config: Record) { return validatedConfig; } + +const toBoolean = (value: any): boolean => { + if (typeof value === 'boolean') { + return value; + } + + if (typeof value === 'number') { + return !!value; + } + + if (!(typeof value === 'string')) { + return false; + } + + switch (value.toLowerCase().trim()) { + case 'true': + case 'yes': + case '1': + return true; + case 'false': + case 'no': + case '0': + case null: + return false; + default: + return false; + } +}; diff --git a/src/common/contracts/abi/csm.json b/src/common/contracts/abi/csm.json new file mode 100644 index 0000000..39db82c --- /dev/null +++ b/src/common/contracts/abi/csm.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"moduleType","type":"bytes32","internalType":"bytes32"},{"name":"_publicReleaseTimestamp","type":"uint256","internalType":"uint256"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEPOSIT_SIZE","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"EL_REWARDS_STEALING_FINE","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"INITIAL_SLASHING_PENALTY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"KEY_VALIDATOR_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MAX_SIGNING_KEYS_BEFORE_PUBLIC_RELEASE","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_INFINITELY","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PAUSE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"PENALIZE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"REPORT_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RESUME_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_ACCOUNTING_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_EARLY_ADOPTION_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_PUBLIC_RELEASE_TIMESTAMP_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SET_UNVETTING_FEE_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"SLASHING_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"STAKING_ROUTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UNSAFE_UNVET_KEYS_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"WITHDRAWAL_SUBMITTER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"accounting","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSAccounting"}],"stateMutability":"view"},{"type":"function","name":"addNodeOperatorETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"eaProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"addNodeOperatorStETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"eaProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperatorStETHWithPermit","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"eaProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperatorWstETH","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"eaProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperatorWstETHWithPermit","inputs":[{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"eaProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"addValidatorKeysStETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysStETHWithPermit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysWstETH","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addValidatorKeysWstETHWithPermit","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"},{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"},{"name":"permit","type":"tuple","internalType":"struct ICSAccounting.PermitInput","components":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cleanDepositQueue","inputs":[{"name":"maxItems","type":"uint256","internalType":"uint256"},{"name":"pointer","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"nonpayable"},{"type":"function","name":"confirmNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"confirmNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"depositQueue","inputs":[{"name":"maxItems","type":"uint256","internalType":"uint256"},{"name":"pointer","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"items","type":"bytes32[]","internalType":"bytes32[]"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"earlyAdoption","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSEarlyAdoption"}],"stateMutability":"view"},{"type":"function","name":"getActiveNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperator","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct ICSModule.NodeOperatorInfo","components":[{"name":"active","type":"bool","internalType":"bool"},{"name":"managerAddress","type":"address","internalType":"address"},{"name":"rewardAddress","type":"address","internalType":"address"},{"name":"totalVettedValidators","type":"uint256","internalType":"uint256"},{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalWithdrawnValidators","type":"uint256","internalType":"uint256"},{"name":"totalAddedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIds","inputs":[{"name":"offset","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorIsActive","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorSigningKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorSummary","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"isTargetLimitActive","type":"bool","internalType":"bool"},{"name":"targetValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"refundedValidatorsCount","type":"uint256","internalType":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256","internalType":"uint256"},{"name":"totalExitedValidators","type":"uint256","internalType":"uint256"},{"name":"totalDepositedValidators","type":"uint256","internalType":"uint256"},{"name":"depositableValidatorsCount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNodeOperatorsCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getResumeSinceTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getStakingModuleSummary","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getType","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isPaused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isQueueDirty","inputs":[{"name":"maxItems","type":"uint256","internalType":"uint256"},{"name":"pointer","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bool","internalType":"bool"},{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"isValidatorSlashed","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidatorWithdrawn","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"obtainDepositData","inputs":[{"name":"depositsCount","type":"uint256","internalType":"uint256"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"publicKeys","type":"bytes","internalType":"bytes"},{"name":"signatures","type":"bytes","internalType":"bytes"}],"stateMutability":"nonpayable"},{"type":"function","name":"onExitedAndStuckValidatorsCountsUpdated","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onRewardsMinted","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"onWithdrawalCredentialsChanged","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseFor","inputs":[{"name":"duration","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"penalize","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorManagerAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"proposeNodeOperatorRewardAddressChange","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"proposedAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"publicReleaseTimestamp","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"queue","inputs":[],"outputs":[{"name":"front","type":"bytes32","internalType":"bytes32"},{"name":"back","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"removeKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"startIndex","type":"uint256","internalType":"uint256"},{"name":"keysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reportELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"blockNumber","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resetNodeOperatorManagerAddress","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"resume","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setAccounting","inputs":[{"name":"_accounting","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setEarlyAdoption","inputs":[{"name":"_earlyAdoption","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPublicReleaseTimestamp","inputs":[{"name":"timestamp","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setUnvettingFee","inputs":[{"name":"_unvettingFee","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleELRewardsStealingPenalty","inputs":[{"name":"nodeOperatorIds","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitInitialSlashing","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"submitWithdrawal","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unsafeUnvetKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unsafeUpdateValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"exitedValidatorsKeysCount","type":"uint256","internalType":"uint256"},{"name":"stuckValidatorsKeysCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unvetKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unvettingFee","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"updateExitedValidatorsCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"exitedValidatorsCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateRefundedValidatorsCount","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"refundedValidatorsCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateStuckValidatorsCount","inputs":[{"name":"nodeOperatorIds","type":"bytes","internalType":"bytes"},{"name":"stuckValidatorsCounts","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTargetValidatorsLimits","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"isTargetLimitActive","type":"bool","internalType":"bool"},{"name":"targetLimit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"vetKeys","inputs":[{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"vetKeysPointer","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BatchEnqueued","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"startIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"count","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"depositedValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ELRewardsStealingPenaltyReported","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"proposedBlockNumber","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"stolenAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExitedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"exitedValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"InitialSlashingSubmitted","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"from","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"proposedAddress","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorManagerAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":false,"internalType":"address"},{"name":"newAddress","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChangeProposed","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"proposedAddress","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NodeOperatorRewardAddressChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"oldAddress","type":"address","indexed":false,"internalType":"address"},{"name":"newAddress","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"NonceChanged","inputs":[{"name":"nonce","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"duration","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PublicReleaseTimestampSet","inputs":[{"name":"timestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Resumed","inputs":[],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SigningKeyAdded","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"SigningKeyRemoved","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"StakingModuleTypeSet","inputs":[{"name":"moduleType","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"StuckSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"stuckValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TargetValidatorsCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"isTargetLimitActive","type":"bool","indexed":false,"internalType":"bool"},{"name":"targetValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TotalSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"totalValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"UnvettingFeeApplied","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"UnvettingFeeSet","inputs":[{"name":"unvettingFee","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"VettedSigningKeysCountChanged","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"approvedValidatorsCount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawalSubmitted","inputs":[{"name":"nodeOperatorId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"keyIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AlreadyEnqueued","inputs":[]},{"type":"error","name":"AlreadyInitialized","inputs":[]},{"type":"error","name":"AlreadyProposed","inputs":[]},{"type":"error","name":"AlreadySubmitted","inputs":[]},{"type":"error","name":"EmptyKey","inputs":[]},{"type":"error","name":"ExitedKeysDecrease","inputs":[]},{"type":"error","name":"ExitedKeysHigherThanTotalDeposited","inputs":[]},{"type":"error","name":"Expired","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidKeysCount","inputs":[]},{"type":"error","name":"InvalidLength","inputs":[]},{"type":"error","name":"InvalidReportData","inputs":[]},{"type":"error","name":"InvalidVetKeysPointer","inputs":[]},{"type":"error","name":"LimitNotSet","inputs":[]},{"type":"error","name":"MaxSigningKeysCountExceeded","inputs":[]},{"type":"error","name":"NodeOperatorDoesNotExist","inputs":[]},{"type":"error","name":"NotAllowedToJoinYet","inputs":[]},{"type":"error","name":"NotEnoughKeys","inputs":[]},{"type":"error","name":"NullItem","inputs":[]},{"type":"error","name":"PauseUntilMustBeInFuture","inputs":[]},{"type":"error","name":"PausedExpected","inputs":[]},{"type":"error","name":"QueueBatchInvalidCount","inputs":[{"name":"batch","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"QueueBatchInvalidNonce","inputs":[{"name":"batch","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"QueueBatchInvalidStart","inputs":[{"name":"batch","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"QueueEmptyBatch","inputs":[]},{"type":"error","name":"QueueIsEmpty","inputs":[]},{"type":"error","name":"QueueLookupNoLimit","inputs":[]},{"type":"error","name":"ResumedExpected","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SameAddress","inputs":[]},{"type":"error","name":"SenderIsNotManagerAddress","inputs":[]},{"type":"error","name":"SenderIsNotManagerOrKeyValidator","inputs":[]},{"type":"error","name":"SenderIsNotProposedAddress","inputs":[]},{"type":"error","name":"SenderIsNotRewardAddress","inputs":[]},{"type":"error","name":"SigningKeysInvalidOffset","inputs":[]},{"type":"error","name":"StuckKeysHigherThanTotalDeposited","inputs":[]},{"type":"error","name":"StuckKeysPresent","inputs":[]},{"type":"error","name":"TargetLimitExceeded","inputs":[]},{"type":"error","name":"TooManyKeys","inputs":[]},{"type":"error","name":"UnbondedKeysPresent","inputs":[]},{"type":"error","name":"WrongPointer","inputs":[]},{"type":"error","name":"ZeroPauseDuration","inputs":[]}] diff --git a/src/common/contracts/abi/verifier.json b/src/common/contracts/abi/verifier.json new file mode 100644 index 0000000..bbc81c1 --- /dev/null +++ b/src/common/contracts/abi/verifier.json @@ -0,0 +1 @@ +[{"type":"constructor","inputs":[{"name":"slotsPerEpoch","type":"uint64","internalType":"uint64"},{"name":"gIHistoricalSummaries","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstWithdrawal","type":"bytes32","internalType":"GIndex"},{"name":"gIFirstValidator","type":"bytes32","internalType":"GIndex"},{"name":"firstSupportedSlot","type":"uint64","internalType":"Slot"}],"stateMutability":"nonpayable"},{"type":"function","name":"BEACON_ROOTS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"FIRST_SUPPORTED_SLOT","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"Slot"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_VALIDATOR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_FIRST_WITHDRAWAL","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"GI_HISTORICAL_SUMMARIES","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"GIndex"}],"stateMutability":"view"},{"type":"function","name":"SLOTS_PER_EPOCH","inputs":[],"outputs":[{"name":"","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"_locator","type":"address","internalType":"address"},{"name":"_module","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"locator","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILidoLocator"}],"stateMutability":"view"},{"type":"function","name":"module","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ICSModule"}],"stateMutability":"view"},{"type":"function","name":"processHistoricalWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"oldBlock","type":"tuple","internalType":"struct ICSVerifier.HistoricalHeaderWitness","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootGIndex","type":"bytes32","internalType":"GIndex"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processSlashingProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.SlashingWitness","components":[{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"processWithdrawalProof","inputs":[{"name":"beaconBlock","type":"tuple","internalType":"struct ICSVerifier.ProvableBeaconBlockHeader","components":[{"name":"header","type":"tuple","internalType":"struct BeaconBlockHeader","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerIndex","type":"uint64","internalType":"uint64"},{"name":"parentRoot","type":"bytes32","internalType":"bytes32"},{"name":"stateRoot","type":"bytes32","internalType":"bytes32"},{"name":"bodyRoot","type":"bytes32","internalType":"bytes32"}]},{"name":"rootsTimestamp","type":"uint64","internalType":"uint64"}]},{"name":"witness","type":"tuple","internalType":"struct ICSVerifier.WithdrawalWitness","components":[{"name":"withdrawalOffset","type":"uint8","internalType":"uint8"},{"name":"withdrawalIndex","type":"uint64","internalType":"uint64"},{"name":"validatorIndex","type":"uint64","internalType":"uint64"},{"name":"amount","type":"uint64","internalType":"uint64"},{"name":"withdrawalCredentials","type":"bytes32","internalType":"bytes32"},{"name":"effectiveBalance","type":"uint64","internalType":"uint64"},{"name":"slashed","type":"bool","internalType":"bool"},{"name":"activationEligibilityEpoch","type":"uint64","internalType":"uint64"},{"name":"activationEpoch","type":"uint64","internalType":"uint64"},{"name":"exitEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawableEpoch","type":"uint64","internalType":"uint64"},{"name":"withdrawalProof","type":"bytes32[]","internalType":"bytes32[]"},{"name":"validatorProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"nodeOperatorId","type":"uint256","internalType":"uint256"},{"name":"keyIndex","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"error","name":"IndexOutOfRange","inputs":[]},{"type":"error","name":"InvalidBlockHeader","inputs":[]},{"type":"error","name":"InvalidChainConfig","inputs":[]},{"type":"error","name":"InvalidGIndex","inputs":[]},{"type":"error","name":"InvalidWithdrawalAddress","inputs":[]},{"type":"error","name":"PartialWitdrawal","inputs":[]},{"type":"error","name":"RootNotFound","inputs":[]},{"type":"error","name":"UnsupportedSlot","inputs":[{"name":"slot","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ValidatorNotWithdrawn","inputs":[]}] diff --git a/src/common/contracts/contracts.module.ts b/src/common/contracts/contracts.module.ts new file mode 100644 index 0000000..b4fc4b3 --- /dev/null +++ b/src/common/contracts/contracts.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { CsmContract } from './csm-contract.service'; +import { VerifierContract } from './verifier-contract.service'; +import { ProvidersModule } from '../providers/providers.module'; + +@Module({ + imports: [ProvidersModule], + providers: [CsmContract, VerifierContract], + exports: [CsmContract, VerifierContract], +}) +export class ContractsModule {} diff --git a/src/common/contracts/csm-contract.service.ts b/src/common/contracts/csm-contract.service.ts new file mode 100644 index 0000000..d227c73 --- /dev/null +++ b/src/common/contracts/csm-contract.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@nestjs/common'; + +import { Csm, Csm__factory } from './types'; +import { ConfigService } from '../config/config.service'; +import { KeyInfo } from '../prover/types'; +import { Execution } from '../providers/execution/execution'; + +@Injectable() +export class CsmContract { + private impl: Csm; + + constructor( + protected readonly config: ConfigService, + protected readonly execution: Execution, + ) { + this.impl = Csm__factory.connect(this.config.get('CSM_ADDRESS'), this.execution.provider); + } + + public async isSlashingProved(keyInfo: KeyInfo): Promise { + return await this.impl.isValidatorSlashed(keyInfo.operatorId, keyInfo.keyIndex); + } + + public async isWithdrawalProved(keyInfo: KeyInfo): Promise { + return await this.impl.isValidatorWithdrawn(keyInfo.operatorId, keyInfo.keyIndex); + } +} diff --git a/src/common/contracts/verifier-contract.service.ts b/src/common/contracts/verifier-contract.service.ts new file mode 100644 index 0000000..eff2dc6 --- /dev/null +++ b/src/common/contracts/verifier-contract.service.ts @@ -0,0 +1,46 @@ +import { LOGGER_PROVIDER } from '@lido-nestjs/logger'; +import { Inject, Injectable, LoggerService } from '@nestjs/common'; + +import { Verifier, Verifier__factory } from './types'; +import { ConfigService } from '../config/config.service'; +import { HistoricalWithdrawalsProofPayload, SlashingProofPayload, WithdrawalsProofPayload } from '../prover/types'; +import { Execution } from '../providers/execution/execution'; + +@Injectable() +export class VerifierContract { + private impl: Verifier; + + constructor( + @Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService, + protected readonly config: ConfigService, + protected readonly execution: Execution, + ) { + this.impl = Verifier__factory.connect(this.config.get('VERIFIER_ADDRESS'), this.execution.provider); + } + + public async sendSlashingProof(payload: SlashingProofPayload): Promise { + this.logger.debug!(payload); + await this.execution.execute( + this.impl.callStatic.processSlashingProof, + this.impl.populateTransaction.processSlashingProof, + [payload.beaconBlock, payload.witness, payload.nodeOperatorId, payload.keyIndex], + ); + } + + public async sendWithdrawalProof(payload: WithdrawalsProofPayload): Promise { + this.logger.debug!(payload); + await this.execution.execute( + this.impl.callStatic.processWithdrawalProof, + this.impl.populateTransaction.processWithdrawalProof, + [payload.beaconBlock, payload.witness, payload.nodeOperatorId, payload.keyIndex], + ); + } + + public async sendHistoricalWithdrawalProof(payload: HistoricalWithdrawalsProofPayload): Promise { + await this.execution.execute( + this.impl.callStatic.processHistoricalWithdrawalProof, + this.impl.populateTransaction.processHistoricalWithdrawalProof, + [payload.beaconBlock, payload.oldBlock, payload.witness, payload.nodeOperatorId, payload.keyIndex], + ); + } +} diff --git a/src/common/prometheus/prometheus.module.ts b/src/common/prometheus/prometheus.module.ts index 24ca98e..29d2b37 100644 --- a/src/common/prometheus/prometheus.module.ts +++ b/src/common/prometheus/prometheus.module.ts @@ -1,7 +1,8 @@ -import { Module } from '@nestjs/common'; +import { Global, Module } from '@nestjs/common'; import { PrometheusService } from './prometheus.service'; +@Global() @Module({ providers: [PrometheusService], exports: [PrometheusService], diff --git a/src/common/prover/duties/slashings.ts b/src/common/prover/duties/slashings.ts index 96e957a..1ab6d5f 100644 --- a/src/common/prover/duties/slashings.ts +++ b/src/common/prover/duties/slashings.ts @@ -2,10 +2,12 @@ import { ContainerTreeViewType } from '@chainsafe/ssz/lib/view/container'; import { LOGGER_PROVIDER } from '@lido-nestjs/logger'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; +import { CsmContract } from '../../contracts/csm-contract.service'; +import { VerifierContract } from '../../contracts/verifier-contract.service'; import { Consensus } from '../../providers/consensus/consensus'; import { BlockHeaderResponse, BlockInfoResponse } from '../../providers/consensus/response.interface'; import { generateValidatorProof, toHex, verifyProof } from '../helpers/proofs'; -import { KeyInfo, KeyInfoFn, SlashingProvePayload } from '../types'; +import { KeyInfo, KeyInfoFn, SlashingProofPayload } from '../types'; let ssz: typeof import('@lodestar/types').ssz; let anySsz: typeof ssz.phase0 | typeof ssz.altair | typeof ssz.bellatrix | typeof ssz.capella | typeof ssz.deneb; @@ -17,6 +19,8 @@ export class SlashingsService { constructor( @Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService, protected readonly consensus: Consensus, + protected readonly csm: CsmContract, + protected readonly verifier: VerifierContract, ) {} public async getUnprovenSlashings(blockInfo: BlockInfoResponse, keyInfoFn: KeyInfoFn): Promise { @@ -27,9 +31,7 @@ export class SlashingsService { if (!Object.keys(slashings).length) return {}; const unproven: InvolvedKeys = {}; for (const [valIndex, keyInfo] of Object.entries(slashings)) { - // TODO: implement - // const proved = await this.execution.isSlashingProved(slashing); - const proved = false; + const proved = await this.csm.isSlashingProved(keyInfo); if (!proved) unproven[valIndex] = keyInfo; } const unprovenCount = Object.keys(unproven).length; @@ -41,19 +43,17 @@ export class SlashingsService { return unproven; } - public async sendSlashingProves(finalizedHeader: BlockHeaderResponse, slashings: InvolvedKeys): Promise { + public async sendSlashingProof(finalizedHeader: BlockHeaderResponse, slashings: InvolvedKeys): Promise { if (!Object.keys(slashings).length) return; this.logger.log(`Getting state for root [${finalizedHeader.root}]`); const finalizedState = await this.consensus.getState(finalizedHeader.header.message.state_root); const nextHeader = (await this.consensus.getBeaconHeadersByParentRoot(finalizedHeader.root)).data[0]; const nextHeaderTs = this.consensus.slotToTimestamp(Number(nextHeader.header.message.slot)); const stateView = this.consensus.stateToView(finalizedState.bodyBytes, finalizedState.forkName); - const payloads = this.buildSlashingsProvePayloads(finalizedHeader, nextHeaderTs, stateView, slashings); + const payloads = this.buildSlashingsProofPayloads(finalizedHeader, nextHeaderTs, stateView, slashings); for (const payload of payloads) { - this.logger.warn(`📡 Sending slashing prove payload for validator index: ${payload.witness.validatorIndex}`); - // TODO: implement - // TODO: ask before sending if CLI - this.logger.log(payload); + this.logger.warn(`📡 Sending slashing proof payload for validator index: ${payload.witness.validatorIndex}`); + await this.verifier.sendSlashingProof(payload); } } @@ -88,12 +88,12 @@ export class SlashingsService { return slashed; } - private *buildSlashingsProvePayloads( + private *buildSlashingsProofPayloads( currentHeader: BlockHeaderResponse, nextHeaderTimestamp: number, stateView: ContainerTreeViewType, slashings: InvolvedKeys, - ): Generator { + ): Generator { for (const [valIndex, keyInfo] of Object.entries(slashings)) { const validator = stateView.validators.get(Number(valIndex)); const validatorProof = generateValidatorProof(stateView, Number(valIndex)); diff --git a/src/common/prover/duties/withdrawals.ts b/src/common/prover/duties/withdrawals.ts index 2e9d8a5..5c5f014 100644 --- a/src/common/prover/duties/withdrawals.ts +++ b/src/common/prover/duties/withdrawals.ts @@ -3,6 +3,8 @@ import { LOGGER_PROVIDER } from '@lido-nestjs/logger'; import { ForkName } from '@lodestar/params'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; +import { CsmContract } from '../../contracts/csm-contract.service'; +import { VerifierContract } from '../../contracts/verifier-contract.service'; import { Consensus } from '../../providers/consensus/consensus'; import { BlockHeaderResponse, @@ -17,7 +19,7 @@ import { toHex, verifyProof, } from '../helpers/proofs'; -import { KeyInfo, KeyInfoFn, WithdrawalsGeneralProvePayload, WithdrawalsHistoricalProvePayload } from '../types'; +import { HistoricalWithdrawalsProofPayload, KeyInfo, KeyInfoFn, WithdrawalsProofPayload } from '../types'; let ssz: typeof import('@lodestar/types').ssz; let anySsz: typeof ssz.phase0 | typeof ssz.altair | typeof ssz.bellatrix | typeof ssz.capella | typeof ssz.deneb; @@ -33,6 +35,8 @@ export class WithdrawalsService { constructor( @Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService, protected readonly consensus: Consensus, + protected readonly csm: CsmContract, + protected readonly verifier: VerifierContract, ) {} public async getUnprovenWithdrawals( @@ -43,9 +47,7 @@ export class WithdrawalsService { if (!Object.keys(withdrawals).length) return {}; const unproven: InvolvedKeysWithWithdrawal = {}; for (const [valIndex, keyWithWithdrawalInfo] of Object.entries(withdrawals)) { - // TODO: implement - // const proved = await this.execution.isSlashingProved(slashing); - const proved = false; + const proved = await this.csm.isWithdrawalProved(keyWithWithdrawalInfo); if (!proved) unproven[valIndex] = keyWithWithdrawalInfo; } const unprovenCount = Object.keys(unproven).length; @@ -57,7 +59,7 @@ export class WithdrawalsService { return unproven; } - public async sendWithdrawalProves( + public async sendWithdrawalProofs( blockRoot: RootHex, blockInfo: BlockInfoResponse, finalizedHeader: BlockHeaderResponse, @@ -72,13 +74,13 @@ export class WithdrawalsService { // The transaction will be reverted and the application will try to handle that block again if (this.isHistoricalBlock(blockInfo, finalizedHeader)) { this.logger.warn('It is historical withdrawal. Processing will take longer than usual'); - await this.sendHistoricalWithdrawalProves(blockHeader, blockInfo, state, finalizedHeader, withdrawals); + await this.sendHistoricalWithdrawalProofs(blockHeader, blockInfo, state, finalizedHeader, withdrawals); } else { - await this.sendGeneralWithdrawalProves(blockHeader, blockInfo, state, withdrawals); + await this.sendGeneralWithdrawalProofs(blockHeader, blockInfo, state, withdrawals); } } - private async sendGeneralWithdrawalProves( + private async sendGeneralWithdrawalProofs( blockHeader: BlockHeaderResponse, blockInfo: BlockInfoResponse, state: { bodyBytes: Uint8Array; forkName: keyof typeof ForkName }, @@ -87,7 +89,7 @@ export class WithdrawalsService { // create proof against the state with withdrawals const nextBlockHeader = (await this.consensus.getBeaconHeadersByParentRoot(blockHeader.root)).data[0]; const nextBlockTs = this.consensus.slotToTimestamp(Number(nextBlockHeader.header.message.slot)); - const payloads = this.buildWithdrawalsProveGeneralPayloads( + const payloads = this.buildWithdrawalsProofPayloads( blockHeader, nextBlockTs, this.consensus.stateToView(state.bodyBytes, state.forkName), @@ -95,14 +97,12 @@ export class WithdrawalsService { withdrawals, ); for (const payload of payloads) { - this.logger.warn(`📡 Sending withdrawal prove payload for validator index: ${payload.witness.validatorIndex}`); - // TODO: implement - // TODO: ask before sending if CLI - this.logger.log(payload); + this.logger.warn(`📡 Sending withdrawal proof payload for validator index: ${payload.witness.validatorIndex}`); + await this.verifier.sendWithdrawalProof(payload); } } - private async sendHistoricalWithdrawalProves( + private async sendHistoricalWithdrawalProofs( blockHeader: BlockHeaderResponse, blockInfo: BlockInfoResponse, state: { bodyBytes: Uint8Array; forkName: keyof typeof ForkName }, @@ -118,7 +118,7 @@ export class WithdrawalsService { const summarySlot = this.calcSlotOfSummary(summaryIndex); this.logger.log(`Getting state for slot [${summarySlot}]`); const summaryState = await this.consensus.getState(summarySlot); - const payloads = this.buildWithdrawalsProveHistoricalPayloads( + const payloads = this.buildHistoricalWithdrawalsProofPayloads( blockHeader, finalizedHeader, nextBlockTs, @@ -132,11 +132,9 @@ export class WithdrawalsService { ); for (const payload of payloads) { this.logger.warn( - `📡 Sending historical withdrawal prove payload for validator index: ${payload.witness.validatorIndex}`, + `📡 Sending historical withdrawal proof payload for validator index: ${payload.witness.validatorIndex}`, ); - // TODO: implement - // TODO: ask before sending if CLI - this.logger.log(payload); + await this.verifier.sendHistoricalWithdrawalProof(payload); } } @@ -155,13 +153,13 @@ export class WithdrawalsService { return fullWithdrawals; } - private *buildWithdrawalsProveGeneralPayloads( + private *buildWithdrawalsProofPayloads( currentHeader: BlockHeaderResponse, nextHeaderTimestamp: number, stateView: ContainerTreeViewType, currentBlockView: ContainerTreeViewType, withdrawals: InvolvedKeysWithWithdrawal, - ): Generator { + ): Generator { const epoch = this.consensus.slotToEpoch(Number(currentHeader.header.message.slot)); for (const [valIndex, keyWithWithdrawalInfo] of Object.entries(withdrawals)) { const validator = stateView.validators.get(Number(valIndex)); @@ -220,7 +218,7 @@ export class WithdrawalsService { } } - private *buildWithdrawalsProveHistoricalPayloads( + private *buildHistoricalWithdrawalsProofPayloads( headerWithWds: BlockHeaderResponse, finalHeader: BlockHeaderResponse, nextToFinalizedHeaderTimestamp: number, @@ -231,7 +229,7 @@ export class WithdrawalsService { summaryIndex: number, rootIndexInSummary: number, withdrawals: InvolvedKeysWithWithdrawal, - ): Generator { + ): Generator { const epoch = this.consensus.slotToEpoch(Number(headerWithWds.header.message.slot)); for (const [valIndex, keyWithWithdrawalInfo] of Object.entries(withdrawals)) { const validator = stateWithWdsView.validators.get(Number(valIndex)); @@ -299,7 +297,8 @@ export class WithdrawalsService { stateRoot: headerWithWds.header.message.state_root, bodyRoot: headerWithWds.header.message.body_root, }, - rootGIndex: Number(historicalStateProof.gindex), + // NOTE: the last byte can be changed due to `CSVerifier` implementation in the future + rootGIndex: '0x' + (historicalStateProof.gindex.toString(16) + '00').padStart(64, '0'), proof: historicalStateProof.witnesses.map(toHex), }, witness: { diff --git a/src/common/prover/prover.module.ts b/src/common/prover/prover.module.ts index 6f3f711..a98901e 100644 --- a/src/common/prover/prover.module.ts +++ b/src/common/prover/prover.module.ts @@ -3,10 +3,11 @@ import { Module } from '@nestjs/common'; import { SlashingsService } from './duties/slashings'; import { WithdrawalsService } from './duties/withdrawals'; import { ProverService } from './prover.service'; +import { ContractsModule } from '../contracts/contracts.module'; import { ProvidersModule } from '../providers/providers.module'; @Module({ - imports: [ProvidersModule], + imports: [ProvidersModule, ContractsModule], providers: [ProverService, SlashingsService, WithdrawalsService], exports: [ProverService], }) diff --git a/src/common/prover/prover.service.ts b/src/common/prover/prover.service.ts index ffd040e..81d3f53 100644 --- a/src/common/prover/prover.service.ts +++ b/src/common/prover/prover.service.ts @@ -30,8 +30,8 @@ export class ProverService { } const finalizedHeader = await this.consensus.getBeaconHeader(finalizedBlockRoot); // do it consistently because of the high resource usage (both the app and CL node) - await this.slashings.sendSlashingProves(finalizedHeader, slashings); - await this.withdrawals.sendWithdrawalProves(blockRoot, blockInfo, finalizedHeader, withdrawals); - this.logger.log('🏁 Prove(s) sent'); + await this.slashings.sendSlashingProof(finalizedHeader, slashings); + await this.withdrawals.sendWithdrawalProofs(blockRoot, blockInfo, finalizedHeader, withdrawals); + this.logger.log('🏁 Proof(s) sent'); } } diff --git a/src/common/prover/types.ts b/src/common/prover/types.ts index 6e34936..23780f6 100644 --- a/src/common/prover/types.ts +++ b/src/common/prover/types.ts @@ -6,14 +6,14 @@ export interface KeyInfo { export type KeyInfoFn = (valIndex: number) => KeyInfo | undefined; -export type WithdrawalsGeneralProvePayload = { +export type WithdrawalsProofPayload = { beaconBlock: ProvableBeaconBlockHeader; witness: WithdrawalWitness; nodeOperatorId: number; keyIndex: number; }; -export type WithdrawalsHistoricalProvePayload = { +export type HistoricalWithdrawalsProofPayload = { beaconBlock: ProvableBeaconBlockHeader; oldBlock: HistoricalHeaderWitness; witness: WithdrawalWitness; @@ -21,7 +21,7 @@ export type WithdrawalsHistoricalProvePayload = { keyIndex: number; }; -export type SlashingProvePayload = { +export type SlashingProofPayload = { beaconBlock: ProvableBeaconBlockHeader; witness: SlashingWitness; nodeOperatorId: number; @@ -35,7 +35,7 @@ export type ProvableBeaconBlockHeader = { export type HistoricalHeaderWitness = { header: BeaconBlockHeader; - rootGIndex: number; + rootGIndex: string; // bytes32 proof: string[]; // bytes32[] }; diff --git a/src/common/providers/consensus/consensus.ts b/src/common/providers/consensus/consensus.ts index ae09157..b012f6a 100644 --- a/src/common/providers/consensus/consensus.ts +++ b/src/common/providers/consensus/consensus.ts @@ -132,8 +132,8 @@ export class Consensus extends BaseRestProvider implements OnModuleInit { body: BlockInfoResponse, forkName: keyof typeof ForkName, ): ContainerTreeViewType { - return ssz[forkName].BeaconBlock.toView(anySsz.BeaconBlock.fromJson(body.message) as any) as ContainerTreeViewType< - typeof anySsz.BeaconBlock.fields - >; + return ssz[forkName].BeaconBlock.toView( + ssz[forkName].BeaconBlock.fromJson(body.message) as any, + ) as ContainerTreeViewType; } } diff --git a/src/common/providers/execution/execution.ts b/src/common/providers/execution/execution.ts index f9c8f67..a0e0030 100644 --- a/src/common/providers/execution/execution.ts +++ b/src/common/providers/execution/execution.ts @@ -1,4 +1,149 @@ -import { Injectable } from '@nestjs/common'; +import { MAX_BLOCKCOUNT, SimpleFallbackJsonRpcBatchProvider } from '@lido-nestjs/execution'; +import { LOGGER_PROVIDER } from '@lido-nestjs/logger'; +import { Inject, Injectable, LoggerService } from '@nestjs/common'; +import { PopulatedTransaction, Wallet, utils } from 'ethers'; + +import { bigIntMax, bigIntMin, percentile } from './utils/common'; +import { ConfigService } from '../../config/config.service'; @Injectable() -export class Execution {} +export class Execution { + public signer?: Wallet; + + private gasFeeHistoryCache: bigint[] = []; + private lastFeeHistoryBlockNumber = 0; + + constructor( + @Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService, + protected readonly config: ConfigService, + public readonly provider: SimpleFallbackJsonRpcBatchProvider, + ) { + const key = this.config.get('TX_SIGNER_PRIVATE_KEY'); + if (key) this.signer = new Wallet(key, this.provider); + } + + public async execute( + emulateTxCallback: (...payload: any[]) => Promise, + populateTxCallback: (...payload: any[]) => Promise, + payload: any[], + ): Promise { + this.logger.debug!(payload); + const tx = await populateTxCallback(...payload); + await emulateTxCallback(...payload).catch((e) => { + this.logger.error('❌ Emulated call failed'); + throw e; + }); + this.logger.log('✅ Emulated call succeeded'); + if (!this.signer) { + this.logger.warn('✴️ No specified signer. Only emulated calls are available'); + return; + } + const priorityFeeParams = await this.calcPriorityFee(); + const populated = await this.signer.populateTransaction({ + ...tx, + maxFeePerGas: priorityFeeParams.maxFeePerGas, + maxPriorityFeePerGas: priorityFeeParams.maxPriorityFeePerGas, + gasLimit: this.config.get('TX_GAS_LIMIT'), + }); + // TODO: For CLI: + // ask before sending; + // suggest to send tx even if high gas fee; + // suggest to specify custom gas fee (especially if gas history fails) + if (this.config.get('DRY_RUN')) { + this.logger.warn('✴️ Dry run mode is enabled. Transaction is prepared, but not sent:'); + this.logger.warn(populated); + return; + } + const isFeePerGasAcceptable = await this.isFeePerGasAcceptable(); + if (!isFeePerGasAcceptable) { + this.logger.warn('❌ Transaction is not sent due to high gas fee:'); + this.logger.warn(populated); + throw new Error('Transaction is not sent due to high gas fee'); + } + const signed = await this.signer.signTransaction(populated); + try { + const submitted = await this.provider.sendTransaction(signed); + await submitted.wait(); + } catch (e) { + this.logger.error('❌ Transaction failed'); + throw e; + } + this.logger.log('✅ Transaction succeeded'); + } + + // + // Gas calc functions + // + + private async isFeePerGasAcceptable(): Promise { + const { current, recommended } = await this.calcFeePerGas(); + const currentGwei = Number(utils.formatUnits(current, 'gwei')).toFixed(2); + const recommendedGwei = Number(utils.formatUnits(recommended, 'gwei')).toFixed(2); + const info = `Current: ${currentGwei} Gwei | Recommended: ${recommendedGwei} Gwei`; + if (current > recommended) { + this.logger.warn(`📛 Current gas fee is HIGH! ${info}`); + return false; + } + this.logger.log(`✅ Current gas fee is OK! ${info}`); + return true; + } + + private async calcFeePerGas(): Promise<{ recommended: bigint; current: bigint }> { + const { baseFeePerGas: currentFee } = await this.provider.getBlock('pending'); + await this.updateGasFeeHistoryCache(); + const recommended = percentile(this.gasFeeHistoryCache, this.config.get('TX_GAS_FEE_HISTORY_PERCENTILE')); + return { recommended, current: currentFee?.toBigInt() ?? 0n }; + } + + private async calcPriorityFee(): Promise<{ maxFeePerGas: bigint; maxPriorityFeePerGas: bigint }> { + const { baseFeePerGas } = await this.provider.getBlock('pending'); + const { reward } = await this.provider.getFeeHistory(1, 'latest', [ + this.config.get('TX_GAS_PRIORITY_FEE_PERCENTILE'), + ]); + const maxPriorityFeePerGas = bigIntMin( + bigIntMax(reward.pop()?.pop()?.toBigInt() ?? 0n, BigInt(this.config.get('TX_MIN_GAS_PRIORITY_FEE'))), + BigInt(this.config.get('TX_MAX_GAS_PRIORITY_FEE')), + ); + const maxFeePerGas = BigInt(Number(baseFeePerGas)) * 2n + maxPriorityFeePerGas; + this.logger.debug!(`Priority fee: ${maxPriorityFeePerGas} | Max fee: ${maxFeePerGas}`); + return { maxPriorityFeePerGas, maxFeePerGas }; + } + + private async updateGasFeeHistoryCache(): Promise { + const maxBlocksPerHour = (60 * 60) / 12; + const maxBlocksPerDay = 24 * maxBlocksPerHour; + const maxFeeHistoryCacheSize = this.config.get('TX_GAS_FEE_HISTORY_DAYS') * maxBlocksPerDay; + + const { number: latestBlockNumber } = await this.provider.getBlock('latest'); + + const feeHistoryCacheBlocksDelay = latestBlockNumber - this.lastFeeHistoryBlockNumber; + // TODO: what the buffer to update should be? + if (feeHistoryCacheBlocksDelay < maxBlocksPerHour) return; + + this.logger.log('🔄 Updating gas fee history cache'); + + let newGasFees: bigint[] = []; + let blockCountPerRequest = MAX_BLOCKCOUNT; + let latestBlockToRequest = latestBlockNumber; + let totalBlockCountToFetch = Math.min(feeHistoryCacheBlocksDelay, maxFeeHistoryCacheSize); + while (totalBlockCountToFetch > 0) { + if (totalBlockCountToFetch < MAX_BLOCKCOUNT) { + blockCountPerRequest = totalBlockCountToFetch; + } + const stats = await this.provider.getFeeHistory(blockCountPerRequest, latestBlockToRequest, []); + // NOTE: `baseFeePerGas` includes the next block after the newest of the returned range, + // so we need to exclude it + stats.baseFeePerGas.pop(); + newGasFees = [...stats.baseFeePerGas.map((v) => v.toBigInt()), ...newGasFees]; + latestBlockToRequest -= blockCountPerRequest - 1; + totalBlockCountToFetch -= blockCountPerRequest; + } + + // update cache with new values + this.gasFeeHistoryCache = [ + ...(this.gasFeeHistoryCache.length > newGasFees.length ? this.gasFeeHistoryCache.slice(newGasFees.length) : []), + ...newGasFees, + ]; + this.lastFeeHistoryBlockNumber = latestBlockNumber; + } +} diff --git a/src/common/providers/execution/utils/common.ts b/src/common/providers/execution/utils/common.ts new file mode 100644 index 0000000..e9d686c --- /dev/null +++ b/src/common/providers/execution/utils/common.ts @@ -0,0 +1,18 @@ +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json +(BigInt.prototype as any).toJSON = function () { + return this.toString(); +}; + +export const bigIntMax = (...args: bigint[]) => args.reduce((m, e) => (e > m ? e : m)); +export const bigIntMin = (...args: bigint[]) => args.reduce((m, e) => (e < m ? e : m)); +export const percentile = (arr: bigint[], p: number) => { + arr.sort((a, b) => Number(a - b)); + const index = (p / 100) * (arr.length - 1); + if (Number.isInteger(index)) { + return arr[index]; + } else { + const lower = Math.floor(index); + const upper = Math.ceil(index); + return (arr[lower] + arr[upper]) / 2n; + } +}; diff --git a/src/common/providers/providers.module.ts b/src/common/providers/providers.module.ts index 77cdaf4..17e12a4 100644 --- a/src/common/providers/providers.module.ts +++ b/src/common/providers/providers.module.ts @@ -1,19 +1,48 @@ +import { FallbackProviderModule, NonEmptyArray } from '@lido-nestjs/execution'; import { Module } from '@nestjs/common'; import { ConditionalModule } from '@nestjs/config'; import { Consensus } from './consensus/consensus'; import { Execution } from './execution/execution'; import { Keysapi } from './keysapi/keysapi'; +import { ConfigService } from '../config/config.service'; import { WorkingMode } from '../config/env.validation'; -import { PrometheusModule } from '../prometheus/prometheus.module'; +import { PrometheusService } from '../prometheus/prometheus.service'; import { UtilsModule } from '../utils/utils.module'; +const ExecutionDaemon = () => + FallbackProviderModule.forRootAsync({ + async useFactory(configService: ConfigService) { + return { + urls: configService.get('EL_RPC_URLS') as NonEmptyArray, + network: configService.get('ETH_NETWORK'), + // TODO: add prometheus metrics + // fetchMiddlewares: [ ... ], + }; + }, + inject: [ConfigService, PrometheusService], + }); + +const ExecutionCli = () => + FallbackProviderModule.forRootAsync({ + async useFactory(configService: ConfigService) { + return { + urls: configService.get('EL_RPC_URLS') as NonEmptyArray, + network: configService.get('ETH_NETWORK'), + }; + }, + inject: [ConfigService], + }); + @Module({ imports: [ - ConditionalModule.registerWhen(PrometheusModule, (env: NodeJS.ProcessEnv) => { + UtilsModule, + ConditionalModule.registerWhen(ExecutionDaemon(), (env: NodeJS.ProcessEnv) => { return env['WORKING_MODE'] === WorkingMode.Daemon; }), - UtilsModule, + ConditionalModule.registerWhen(ExecutionCli(), (env: NodeJS.ProcessEnv) => { + return env['WORKING_MODE'] === WorkingMode.CLI; + }), ], providers: [Execution, Consensus, Keysapi], exports: [Execution, Consensus, Keysapi], diff --git a/src/daemon/services/keys-indexer.ts b/src/daemon/services/keys-indexer.ts index c45baed..e3a91e7 100644 --- a/src/daemon/services/keys-indexer.ts +++ b/src/daemon/services/keys-indexer.ts @@ -158,7 +158,7 @@ export class KeysIndexer implements OnModuleInit { private async initOrReadServiceData() { const defaultInfo: KeysIndexerServiceInfo = { - moduleAddress: this.config.get('LIDO_STAKING_MODULE_ADDRESS'), + moduleAddress: this.config.get('CSM_ADDRESS'), moduleId: 0, storageStateSlot: 0, lastValidatorsCount: 0, diff --git a/src/daemon/services/roots-processor.ts b/src/daemon/services/roots-processor.ts index 2a9ebc2..2b353c0 100644 --- a/src/daemon/services/roots-processor.ts +++ b/src/daemon/services/roots-processor.ts @@ -24,10 +24,10 @@ export class RootsProcessor { blockRoot: blockRootToProcess, slotNumber: Number(blockInfoToProcess.message.slot), }; - const indexerIsTrusted = this.keysIndexer.isTrustedForEveryDuty(rootSlot.slotNumber); - if (!indexerIsTrusted) await this.rootsStack.push(rootSlot); // only new will be pushed - // prove slashings or withdrawals if needed + await this.rootsStack.push(rootSlot); // in case of revert we should reprocess the root + // TODO: need some protection from run out of account's balance when tx reverting for the same root await this.prover.handleBlock(blockRootToProcess, blockInfoToProcess, finalizedRoot, this.keysIndexer.getKey); + const indexerIsTrusted = this.keysIndexer.isTrustedForEveryDuty(rootSlot.slotNumber); if (indexerIsTrusted) await this.rootsStack.purge(rootSlot); await this.rootsStack.setLastProcessed(rootSlot); } diff --git a/yarn.lock b/yarn.lock index 0333a6c..b8c8848 100644 --- a/yarn.lock +++ b/yarn.lock @@ -439,6 +439,348 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.5.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.5.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.5.2", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.5.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.5.3": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.5.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@fastify/busboy@^2.0.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" @@ -757,7 +1099,27 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@lido-nestjs/logger@^1.3.2": +"@lido-nestjs/constants@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@lido-nestjs/constants/-/constants-5.2.1.tgz#f006972b7b69429f7623b0c5ac8b4bba594f9c01" + integrity sha512-0UvUdQ4KilnH0Nf5JkdKdOrS2HFMjmrS4+2wUXoX08N25MzFryWC0qcdFLp1bvod04Ey/PoUNlj+S2WVKEYgwQ== + +"@lido-nestjs/execution@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@lido-nestjs/execution/-/execution-1.12.0.tgz#3be5954320dbc8c2bba8aae95a95c0fb6892750d" + integrity sha512-1GSxIe70MZ4Ml0pxvaA5ffvXW1jDCiCAv51ZJGjwdg4sQvFinwJo4GOs9vAf3ydykwa0xItsuZjV+WwOwx73rg== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.2" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/providers" "^5.5.3" + "@ethersproject/web" "^5.5.1" + "@lido-nestjs/logger" "1.3.2" + "@lido-nestjs/middleware" "1.2.0" + +"@lido-nestjs/logger@1.3.2", "@lido-nestjs/logger@^1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@lido-nestjs/logger/-/logger-1.3.2.tgz#0d301d7cfc0ea549ad9a658f74d99ded75bbdc80" integrity sha512-Pi00cEruj2jGVuYBK2beKAuvxKvgTvD8zYzswj0GRvCBvxpoMj/MRfsh3fgMCnYq/tYaI0rZQlG6rYyTILLw3Q== @@ -766,6 +1128,11 @@ traverse "^0.6.7" winston "^3.4.0" +"@lido-nestjs/middleware@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@lido-nestjs/middleware/-/middleware-1.2.0.tgz#0e64b69149ef1f7e4594896fd08d6e0bd9ef5382" + integrity sha512-0rkXWKXEKJPRbq1W6cN+yelhc+CruqhUqmdkNKwl4vTk631fpG9yfSfxxQFDAs3LhsTORqqgKUBpdK+epRYjIQ== + "@ljharb/through@^2.3.11": version "2.3.12" resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.12.tgz#c418c43060eee193adce48b15c2206096a28e9ea" @@ -1102,6 +1469,14 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@typechain/ethers-v5@^11.1.2": + version "11.1.2" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-11.1.2.tgz#82510c1744f37a2f906b9e0532ac18c0b74ffe69" + integrity sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -1308,6 +1683,11 @@ dependencies: undici-types "~5.26.4" +"@types/prettier@^2.1.1": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + "@types/qs@*": version "6.9.11" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" @@ -1656,6 +2036,11 @@ acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + ajv-formats@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -1769,6 +2154,16 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" @@ -1949,6 +2344,11 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + bin-check@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" @@ -1988,6 +2388,16 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -2046,6 +2456,11 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + browserslist@^4.21.10, browserslist@^4.22.2: version "4.22.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" @@ -2342,6 +2757,26 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + commander@11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" @@ -2522,6 +2957,11 @@ dedent@^1.0.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2646,6 +3086,19 @@ electron-to-chromium@^1.4.648: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.656.tgz#b374fb7cab9b782a5bc967c0ce0e19826186b9c9" integrity sha512-9AQB5eFTHyR3Gvt2t/NwR0le2jBSUNwCnMbUCejFWHD+so4tH40/dRLgoE+jxlPeWS43XJewyvCv+I8LPMl49Q== +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" @@ -2986,6 +3439,42 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -3223,6 +3712,13 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -3336,6 +3832,15 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-monkey@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" @@ -3459,6 +3964,18 @@ glob@10.3.10: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -3590,6 +4107,14 @@ has-tostringtag@^1.0.0, has-tostringtag@^1.0.1: dependencies: has-symbols "^1.0.3" +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + hasown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" @@ -3602,6 +4127,15 @@ hexoid@^1.0.0: resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -4373,6 +4907,11 @@ jest@^29.5.0: import-local "^3.0.2" jest-cli "^29.7.0" +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4445,6 +4984,13 @@ jsonc-parser@^3.2.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -4513,6 +5059,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -4523,7 +5074,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@4.17.21, lodash@^4.17.21: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4683,6 +5234,16 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + minimatch@9.0.3, minimatch@^9.0.1, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -4726,6 +5287,11 @@ mkdirp@^0.5.4: dependencies: minimist "^1.2.6" +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5163,6 +5729,11 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" +prettier@^2.3.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + prettier@^3.0.0, prettier@^3.1.0: version "3.2.5" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" @@ -5325,6 +5896,11 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + reflect-metadata@^0.1.13: version "0.1.14" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859" @@ -5501,6 +6077,11 @@ schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + semver-regex@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-4.0.5.tgz#fbfa36c7ba70461311f5debcb3928821eb4f9180" @@ -5734,6 +6315,11 @@ streamsearch@^1.1.0: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -5916,6 +6502,16 @@ synckit@^0.8.6: "@pkgr/core" "^0.1.0" tslib "^2.6.2" +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -6035,6 +6631,21 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-command-line-args@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-jest@^29.1.0: version "29.1.2" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" @@ -6142,6 +6753,22 @@ type-is@^1.6.4, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typechain@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.2.tgz#1090dd8d9c57b6ef2aed3640a516bdbf01b00d73" + integrity sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -6191,6 +6818,16 @@ typescript@5.3.3, typescript@^5.3.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + uid@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/uid/-/uid-2.0.2.tgz#4b5782abf0f2feeefc00fa88006b2b3b7af3e3b9" @@ -6220,6 +6857,11 @@ undici@^6.4.0: dependencies: "@fastify/busboy" "^2.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -6421,6 +7063,14 @@ winston@^3.11.0, winston@^3.4.0: triple-beam "^1.3.0" winston-transport "^4.5.0" +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: name wrap-ansi-cjs version "7.0.0" @@ -6462,6 +7112,11 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"