Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: issue #513 in eth-steth: Using blockNumber - 1 instead of block.… #519

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions ethereum-steth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@
"stake": "forta-agent stake",
"test": "jest",
"generate-types": "typechain --target=ethers-v5 --out-dir=./src/generated ./src/abi/*",
"eslint:lint": "eslint ./src ./tests",
"eslint:format": "eslint ./src ./tests --fix",
"prettier:check": "prettier --check ./src ./tests",
"prettier:format": "prettier --write ./src ./tests README.md",
"eslint:lint": "eslint ./src",
"eslint:format": "eslint ./src --fix",
"prettier:check": "prettier --check ./src",
"prettier:format": "prettier --write ./src README.md",
"lint": "yarn run prettier:check && yarn run eslint:lint",
"format": "yarn run eslint:format && yarn run prettier:format",
"postinstall": "yarn generate-types"
Expand Down
15 changes: 11 additions & 4 deletions ethereum-steth/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TransactionEvent } from 'forta-agent/dist/sdk/transaction.event'
import { Metadata } from './entity/metadata'
import Version from './utils/version'
import { ETH_DECIMALS } from './utils/constants'
import { BlockDto } from './entity/events'

export function initialize(): Initialize {
const metadata: Metadata = {
Expand Down Expand Up @@ -138,11 +139,17 @@ export const handleBlock = (): HandleBlock => {
out.push(...findingsAsync)
}

const blockDto: BlockDto = {
number: blockEvent.block.number,
timestamp: blockEvent.block.timestamp,
parentHash: blockEvent.block.parentHash,
}

const [bufferedEthFindings, withdrawalsFindings, gateSealFindings, vaultFindings] = await Promise.all([
app.StethOperationSrv.handleBlock(blockEvent),
app.WithdrawalsSrv.handleBlock(blockEvent),
app.GateSealSrv.handleBlock(blockEvent),
app.VaultSrv.handleBlock(blockEvent),
app.StethOperationSrv.handleBlock(blockDto),
app.WithdrawalsSrv.handleBlock(blockDto),
app.GateSealSrv.handleBlock(blockDto),
app.VaultSrv.handleBlock(blockDto),
])

out.push(...bufferedEthFindings, ...withdrawalsFindings, ...gateSealFindings, ...vaultFindings)
Expand Down
15 changes: 9 additions & 6 deletions ethereum-steth/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,19 @@ export class App {
return knex(config)
}

public static async getInstance(): Promise<Container> {
public static async getInstance(rpcUrl?: string): Promise<Container> {
if (!App.instance) {
const db = App.getConnection()

const drpcProvider = `https://eth.drpc.org`
const mainnet = 1
const drcpClient = new ethers.providers.JsonRpcProvider(drpcProvider, mainnet)

const etherscanKey = Buffer.from('SVZCSjZUSVBXWUpZSllXSVM0SVJBSlcyNjRITkFUUjZHVQ==', 'base64').toString('utf-8')
const ethersProvider = getEthersProvider()
let ethersProvider = getEthersProvider()
if (rpcUrl !== undefined) {
ethersProvider = drcpClient
}
ethersProvider.formatter = new FormatterWithEIP1898()

const etherscanProvider = new ethers.providers.EtherscanProvider(ethersProvider.network, etherscanKey)
Expand All @@ -96,10 +103,6 @@ export class App {

const lidoContact = Lido__factory.connect(address.LIDO_STETH_ADDRESS, ethersProvider)

const drpcProvider = `https://eth.drpc.org`

const mainnet = 1
const drcpClient = new ethers.providers.JsonRpcProvider(drpcProvider, mainnet)
const wdQueueContact = WithdrawalQueueERC721__factory.connect(address.WITHDRAWALS_QUEUE_ADDRESS, drcpClient)

const gateSealContact = GateSeal__factory.connect(address.GATE_SEAL_DEFAULT_ADDRESS, ethersProvider)
Expand Down
30 changes: 27 additions & 3 deletions ethereum-steth/src/clients/eth_provider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { App } from '../app'
import * as E from 'fp-ts/Either'
import { Address } from '../utils/constants'
import { Address, ETH_DECIMALS } from '../utils/constants'
import { GateSeal } from '../entity/gate_seal'
import { JsonRpcProvider } from '@ethersproject/providers'
import { ethers } from 'forta-agent'

describe('eth provider tests', () => {
let ethProvider: JsonRpcProvider
const mainnet = 1
const drpcProvider = 'https://eth.drpc.org/'

beforeAll(async () => {
ethProvider = new ethers.providers.JsonRpcProvider(drpcProvider, mainnet)
})

test('getWithdrawalStatuses should return 1750 withdrawal statuses', async () => {
const app = await App.getInstance()
const app = await App.getInstance(drpcProvider)

const blockNumber = 19112800
const requestsRange: number[] = []
Expand All @@ -22,7 +32,7 @@ describe('eth provider tests', () => {
}, 120_000)

test('checkGateSeal should be success', async () => {
const app = await App.getInstance()
const app = await App.getInstance(drpcProvider)

const blockNumber = 19140476

Expand All @@ -40,4 +50,18 @@ describe('eth provider tests', () => {

expect(resp.right).toEqual(expected)
}, 120_000)

test('getBalanceByBlockHash is ok', async () => {
const app = await App.getInstance(drpcProvider)

const blockNumber = 19_140_476
const block = await ethProvider.getBlock(blockNumber)

const resp = await app.ethClient.getBalanceByBlockHash(Address.WITHDRAWALS_QUEUE_ADDRESS, block.parentHash)
if (E.isLeft(resp)) {
throw resp.left.message
}

expect(resp.right.dividedBy(ETH_DECIMALS).toNumber()).toEqual(16_619.29059680177)
}, 120_000)
})
4 changes: 1 addition & 3 deletions ethereum-steth/src/clients/eth_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,7 @@ export class ETHProvider implements IGateSealClient, IStethClient, IVaultClient,
try {
const out = await retryAsync<EtherBigNumber>(
async (): Promise<EtherBigNumber> => {
return await this.jsonRpcProvider.getBalance(address, {
blockHash: blockHash,
} as never)
return await this.jsonRpcProvider.getBalance(address, blockHash)
},
{ delay: DELAY_IN_500MS, maxTry: ATTEMPTS_5 },
)
Expand Down
6 changes: 6 additions & 0 deletions ethereum-steth/src/entity/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ export type EventOfNotice = {
severity: FindingSeverity
type: FindingType
}

export type BlockDto = {
number: number
timestamp: number
parentHash: string
}
1 change: 1 addition & 0 deletions ethereum-steth/src/generated/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
21 changes: 11 additions & 10 deletions ethereum-steth/src/services/gate-seal/GateSeal.srv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { etherscanAddress } from '../../utils/string'
import { Logger } from 'winston'
import { networkAlert } from '../../utils/errors'
import { IGateSealClient } from './contract'
import { BlockEvent, filterLog, Finding, FindingSeverity, FindingType } from 'forta-agent'
import { filterLog, Finding, FindingSeverity, FindingType } from 'forta-agent'
import { BlockDto } from '../../entity/events'

const ONE_HOUR = 60 * 60
const ONE_DAY = 24 * ONE_HOUR
Expand Down Expand Up @@ -102,13 +103,13 @@ export class GateSealSrv {
return this.name
}

public async handleBlock(blockEvent: BlockEvent): Promise<Finding[]> {
public async handleBlock(blockDto: BlockDto): Promise<Finding[]> {
const start = new Date().getTime()
const findings: Finding[] = []

const [pauseRoleFindings, expiryGateSealFindings] = await Promise.all([
this.handlePauseRole(blockEvent),
this.handleExpiryGateSeal(blockEvent),
this.handlePauseRole(blockDto),
this.handleExpiryGateSeal(blockDto),
])

findings.push(...pauseRoleFindings, ...expiryGateSealFindings)
Expand All @@ -117,14 +118,14 @@ export class GateSealSrv {
return findings
}

public async handlePauseRole(blockEvent: BlockEvent): Promise<Finding[]> {
public async handlePauseRole(blockDto: BlockDto): Promise<Finding[]> {
const out: Finding[] = []
if (this.gateSealAddress === undefined) {
return []
}

const currentBlockTimestamp = blockEvent.block.timestamp
const status = await this.ethProvider.checkGateSeal(blockEvent.block.number, this.gateSealAddress)
const currentBlockTimestamp = blockDto.timestamp
const status = await this.ethProvider.checkGateSeal(blockDto.number, this.gateSealAddress)
if (E.isLeft(status)) {
if (status.left === GateSealExpiredErr) {
const f = Finding.fromObject({
Expand Down Expand Up @@ -182,13 +183,13 @@ export class GateSealSrv {
return out
}

public async handleExpiryGateSeal(blockEvent: BlockEvent): Promise<Finding[]> {
public async handleExpiryGateSeal(blockDto: BlockDto): Promise<Finding[]> {
if (this.gateSealAddress === undefined) {
return []
}

const currentBlockTimestamp = blockEvent.block.timestamp
const expiryTimestamp = await this.ethProvider.getExpiryTimestamp(blockEvent.block.number)
const currentBlockTimestamp = blockDto.timestamp
const expiryTimestamp = await this.ethProvider.getExpiryTimestamp(blockDto.number)

if (E.isLeft(expiryTimestamp)) {
return [
Expand Down
20 changes: 14 additions & 6 deletions ethereum-steth/src/services/gate-seal/gate-seal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { Finding, FindingSeverity, FindingType, getEthersProvider } from 'forta-agent'
import { etherBlockToFortaBlockEvent } from '../../../tests/e2e/utils'
import { App } from '../../app'
import { Address } from '../../utils/constants'
import * as E from 'fp-ts/Either'
import { GateSeal } from '../../entity/gate_seal'
import { expect } from '@jest/globals'
import { BlockDto } from '../../entity/events'

describe('GateSeal srv e2e tests', () => {
describe('GateSeal srv functional tests', () => {
const ethProvider = getEthersProvider()

test('handle pause role true', async () => {
const app = await App.getInstance()

const blockNumber = 19113580
const block = await ethProvider.getBlock(blockNumber)
const blockDto: BlockDto = {
number: block.number,
timestamp: block.timestamp,
parentHash: block.parentHash,
}

const initErr = await app.GateSealSrv.initialize(blockNumber)
if (initErr instanceof Error) {
Expand All @@ -33,8 +38,7 @@ describe('GateSeal srv e2e tests', () => {
}
expect(status.right).toEqual(expected)

const blockEvent = etherBlockToFortaBlockEvent(block)
const result = await app.GateSealSrv.handlePauseRole(blockEvent)
const result = await app.GateSealSrv.handlePauseRole(blockDto)

expect(result.length).toEqual(0)
}, 120_000)
Expand All @@ -51,8 +55,12 @@ describe('GateSeal srv e2e tests', () => {

const neededBlock = 19_172_615
const block = await ethProvider.getBlock(neededBlock)
const blockEvent = etherBlockToFortaBlockEvent(block)
const result = await app.GateSealSrv.handleExpiryGateSeal(blockEvent)
const blockDto: BlockDto = {
number: block.number,
timestamp: block.timestamp,
parentHash: block.parentHash,
}
const result = await app.GateSealSrv.handleExpiryGateSeal(blockDto)

const expected = Finding.fromObject({
alertId: 'GATE-SEAL-IS-ABOUT-TO-BE-EXPIRED',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import { ethers, Finding, FindingSeverity, FindingType, getEthersProvider, Network, Transaction } from 'forta-agent'
import { App } from '../../src/app'
import { App } from '../../app'
import { JsonRpcProvider } from '@ethersproject/providers'
import { createTransactionEvent, etherBlockToFortaBlockEvent } from './utils'
import { createTransactionEvent } from '../../utils/forta'
import BigNumber from 'bignumber.js'
import { BlockDto } from '../../entity/events'

const TEST_TIMEOUT = 60_000 // ms

describe('agent-steth-ops e2e tests', () => {
describe('Steth.srv functional tests', () => {
let ethProvider: JsonRpcProvider

beforeAll(async () => {
ethProvider = getEthersProvider()
})

test(
'should process block with low staking limit (10%)',
'LOW-STAKING-LIMIT',
async () => {
const app = await App.getInstance()
const blockNumber = 16704075
const blockNumber = 16_704_075
const block = await ethProvider.getBlock(blockNumber)

const blockEvent = etherBlockToFortaBlockEvent(block)
const blockDto: BlockDto = {
number: block.number,
timestamp: block.timestamp,
parentHash: block.parentHash,
}

const result = await app.StethOperationSrv.handleBlock(blockEvent)
const result = await app.StethOperationSrv.handleBlock(blockDto)

const expected = Finding.fromObject({
alertId: 'LOW-STAKING-LIMIT',
Expand All @@ -43,15 +48,19 @@ describe('agent-steth-ops e2e tests', () => {
)

test(
'should process block with huge buffered ETH amount and low deposit executor balance',
'LOW-DEPOSIT-EXECUTOR-BALANCE',
async () => {
const app = await App.getInstance()
const blockNumber = 17241600
const block = await ethProvider.getBlock(blockNumber)

const blockEvent = etherBlockToFortaBlockEvent(block)
const blockDto: BlockDto = {
number: block.number,
timestamp: block.timestamp,
parentHash: block.parentHash,
}

const result = await app.StethOperationSrv.handleDepositExecutorBalance(blockEvent.block.number, block.timestamp)
const result = await app.StethOperationSrv.handleDepositExecutorBalance(blockDto.number, blockDto.timestamp)

const expected = Finding.fromObject({
alertId: 'LOW-DEPOSIT-EXECUTOR-BALANCE',
Expand Down Expand Up @@ -127,7 +136,7 @@ describe('agent-steth-ops e2e tests', () => {
)

test(
'should process tx with transferred ownership of Insurance fund',
'Insurance fund',
async () => {
const app = await App.getInstance()
const txHash = '0x91c7c2f33faf3b5fb097138c1d49c1d4e83f99e1c3b346b3cad35a5928c03b3a'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { StethOperationCache } from './StethOperation.cache'
import { ETH_DECIMALS } from '../../utils/constants'
import * as E from 'fp-ts/Either'
import { BlockEvent, Finding, FindingSeverity, FindingType } from 'forta-agent'
import { Finding, FindingSeverity, FindingType } from 'forta-agent'
import { EventOfNotice } from '../../entity/events'
import { elapsedTime } from '../../utils/time'
import { IStethClient, TransactionEventContract } from './contracts'
import { Logger } from 'winston'
import { alertId_token_rebased } from '../../utils/events/lido_events'
import { networkAlert } from '../../utils/errors'
import { BlockDto } from '../../entity/events'

// Formula: (60 * 60 * 72) / 13 = 19_938
const HISTORY_BLOCK_OFFSET: number = Math.floor((60 * 60 * 72) / 13)
Expand Down Expand Up @@ -101,15 +102,15 @@ export class StethOperationSrv {
return this.name
}

public async handleBlock(blockEvent: BlockEvent) {
public async handleBlock(blockDto: BlockDto) {
const start = new Date().getTime()
const findings: Finding[] = []

const [bufferedEthFindings, depositorBalanceFindings, stakingLimitFindings] = await Promise.all([
this.handleBufferedEth(blockEvent.block.number, blockEvent.block.timestamp),
this.handleDepositExecutorBalance(blockEvent.block.number, blockEvent.block.timestamp),
this.handleStakingLimit(blockEvent.block.number, blockEvent.block.timestamp),
this.handleShareRateChange(blockEvent.block.number),
this.handleBufferedEth(blockDto.number, blockDto.timestamp),
this.handleDepositExecutorBalance(blockDto.number, blockDto.timestamp),
this.handleStakingLimit(blockDto.number, blockDto.timestamp),
this.handleShareRateChange(blockDto.number),
])

findings.push(...bufferedEthFindings, ...depositorBalanceFindings, ...stakingLimitFindings)
Expand Down
Loading
Loading