Skip to content

Commit

Permalink
fix: l2-bridge-base moved 🚨🚨🚨 Base bridge balance mismatch 🚨🚨🚨from l2…
Browse files Browse the repository at this point in the history
…-bridge-balance
  • Loading branch information
sergeyWh1te committed Apr 11, 2024
1 parent 999a602 commit 37a7e4a
Show file tree
Hide file tree
Showing 27 changed files with 674 additions and 410 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/test-l2-bridge-base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: Tests @ l2-bridge-base

on:
workflow_dispatch:
pull_request:
paths:
- "l2-bridge-base/**"

jobs:
tests:
uses: ./.github/workflows/_tests.yml
with:
path: ./l2-bridge-base
secrets: inherit
1 change: 0 additions & 1 deletion l2-bridge-balance/src/agent-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export async function handleBlock(blockEvent: BlockEvent) {
findings,
BRIDGE_PARAMS_WSTETH.Optimism,
),
handleBridgeBalanceWstETH(blockEvent, findings, BRIDGE_PARAMS_WSTETH.Base),
handleBridgeBalanceWstETH(
blockEvent,
findings,
Expand Down
7 changes: 0 additions & 7 deletions l2-bridge-balance/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export interface BridgeParamWstETH {
export interface BridgeParamsWstETH {
Arbitrum: BridgeParamWstETH;
Optimism: BridgeParamWstETH;
Base: BridgeParamWstETH;
ZkSync: BridgeParamWstETH;
Mantle: BridgeParamWstETH;
}
Expand All @@ -38,12 +37,6 @@ export const BRIDGE_PARAMS_WSTETH: BridgeParamsWstETH = {
wstEthBridged: "0x1f32b1c2345538c0c6f582fcb022739c4a194ebb",
rpcUrl: config.Optimism.RpcUrl,
},
Base: {
name: "Base",
l1Gateway: "0x9de443AdC5A411E83F1878Ef24C3F52C61571e72",
wstEthBridged: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
rpcUrl: config.Base.RpcUrl,
},
ZkSync: {
name: "ZkSync",
l1Gateway: "0x41527B2d03844dB6b0945f25702cB958b6d55989",
Expand Down
11 changes: 6 additions & 5 deletions l2-bridge-base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
## Alerts

1. Bridge events
1. 🚨 Base L2 Bridge: Role Admin changed
1. 🚨🚨🚨 Base bridge balance mismatch 🚨🚨🚨
2. 🚨 Base L2 Bridge: Withdrawals Disabled
3. 🚨 Base L2 Bridge: Implementation initialized
4. 🚨 Base L2 Bridge: Deposits Disabled
5. ⚠️ Base L2 Bridge: Role granted
6. ⚠️ Base L2 Bridge: Role revoked
7. ℹ️ Base L2 Bridge: Deposits Enabled
8. ℹ️ Base L2 Bridge: Withdrawals Enabled
5. 🚨 Base L2 Bridge: Role Admin changed
6. ⚠️ Base L2 Bridge: Role granted
7. ⚠️ Base L2 Bridge: Role revoked
8. ℹ️ Base L2 Bridge: Deposits Enabled
9. ℹ️ Base L2 Bridge: Withdrawals Enabled
2. Gov Events
1. 🚨 Base Gov Bridge: Ethereum Governance Executor Updated
2. 🚨 Base Gov Bridge: Guardian Updated
Expand Down
15 changes: 9 additions & 6 deletions l2-bridge-base/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "lido-l2-bridge-base-bot",
"name": "lido-l2-bridge-base",
"version": "0.0.1",
"description": "Lido Detection Bot for base part of L2 bridge",
"license": "MIT",
Expand All @@ -12,6 +12,9 @@
"target": 5
}
},
"engines": {
"node": ">=20.0"
},
"scripts": {
"update-version": "node ../utils/write-version.js",
"build": "tsc && yarn run copy-version",
Expand All @@ -35,10 +38,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 Expand Up @@ -76,7 +79,7 @@
"ts-generator": "^0.1.1",
"ts-jest": "^29.1.1",
"typechain": "^8.3.2",
"typescript": "^5.3.2"
"typescript": "^5.3.3"
},
"packageManager": "[email protected]"
}
64 changes: 64 additions & 0 deletions l2-bridge-base/src/agent.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { App } from './app'
import * as E from 'fp-ts/Either'
import { Finding } from 'forta-agent'
import BigNumber from 'bignumber.js'

describe('agent-base functional test', () => {
test('should process app on 13_022_644 and 13_022_744 (100 l2 blocks)', async () => {
const app = await App.getInstance()

const l1Block = 19_632_237
const l2StartBlock = 13_022_644
const l2EndBlock = 13_022_744
const l2BlocksDto = await app.baseClient.fetchL2Blocks(l2StartBlock, l2EndBlock)

for (const proxyWatcher of app.proxyWatchers) {
const err = await proxyWatcher.initialize(l2StartBlock)
if (err !== null) {
throw null
}
}

const monitorWithdrawalsInitResp = await app.monitorWithdrawals.initialize(l2StartBlock)
if (E.isLeft(monitorWithdrawalsInitResp)) {
throw monitorWithdrawalsInitResp.left
}

const l2logs = await app.blockSrv.getL2Logs(l2BlocksDto)
if (E.isLeft(l2logs)) {
throw l2logs.left
}

const l2BlockNumberSet: Set<number> = new Set<number>()
for (const l2log of l2logs.right) {
l2BlockNumberSet.add(new BigNumber(l2log.blockNumber, 10).toNumber())
}

const bridgeEventFindings = app.bridgeWatcher.handleL2Logs(l2logs.right)
const govEventFindings = app.govWatcher.handleL2Logs(l2logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleL2Logs(l2logs.right)
const monitorWithdrawalsFindings = app.monitorWithdrawals.handleL2Blocks(l2logs.right, l2BlocksDto)
const proxyWatcherFindings: Finding[] = []

const l2BlockNumbers = Array.from(l2BlockNumberSet).toSorted((a, b) => a - b)

for (const proxyWatcher of app.proxyWatchers) {
const fnds = await proxyWatcher.handleL2Blocks(l2BlockNumbers)
proxyWatcherFindings.push(...fnds)
}

const bridgeBalanceFindings = await app.bridgeBalanceSrc.handleBlock(l1Block, l2BlockNumbers)

const findings: Finding[] = []
findings.push(
...bridgeEventFindings,
...govEventFindings,
...proxyAdminEventFindings,
...monitorWithdrawalsFindings,
...proxyWatcherFindings,
...bridgeBalanceFindings,
)

expect(findings.length).toEqual(0)
}, 360_000)
})
23 changes: 13 additions & 10 deletions l2-bridge-base/src/agent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BlockEvent, decodeJwt, Finding, FindingSeverity, FindingType, HandleBlock, HealthCheck } from 'forta-agent'
import { BlockEvent, Finding, FindingSeverity, FindingType, HandleBlock, HealthCheck } from 'forta-agent'
import * as process from 'process'
import { InitializeResponse } from 'forta-agent/dist/sdk/initialize.response'
import { Initialize } from 'forta-agent/dist/sdk/handlers'
Expand Down Expand Up @@ -59,11 +59,10 @@ export function initialize(): Initialize {
agents.push(app.monitorWithdrawals.getName())

metadata.agents = '[' + agents.toString() + ']'
const decodedJwt = decodeJwt(token.right)

await app.findingsRW.write([
Finding.fromObject({
name: `Agent launched, ScannerId: ${decodedJwt.payload.sub}`,
name: `Agent launched`,
description: `Version: ${VERSION.desc}`,
alertId: 'LIDO-AGENT-LAUNCHED',
severity: FindingSeverity.Info,
Expand Down Expand Up @@ -110,29 +109,33 @@ export const handleBlock = (): HandleBlock => {
return [l2logs.left]
}

const bridgeEventFindings = app.bridgeWatcher.handleLogs(l2logs.right)
const govEventFindings = app.govWatcher.handleLogs(l2logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleLogs(l2logs.right)
const monitorWithdrawalsFindings = app.monitorWithdrawals.handleBlocks(l2logs.right, l2blocksDto.right)
const bridgeEventFindings = app.bridgeWatcher.handleL2Logs(l2logs.right)
const govEventFindings = app.govWatcher.handleL2Logs(l2logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleL2Logs(l2logs.right)
const monitorWithdrawalsFindings = app.monitorWithdrawals.handleL2Blocks(l2logs.right, l2blocksDto.right)

const l2BlockNumbers: Set<number> = new Set<number>()
const l2BlockNumberSet: Set<number> = new Set<number>()
for (const l2log of l2logs.right) {
l2BlockNumbers.add(new BigNumber(l2log.blockNumber, 10).toNumber())
l2BlockNumberSet.add(new BigNumber(l2log.blockNumber, 10).toNumber())
}

const l2BlockNumbers = Array.from(l2BlockNumberSet).toSorted((a, b) => a - b)
const proxyWatcherFindings: Finding[] = []

for (const proxyWatcher of app.proxyWatchers) {
const fnds = await proxyWatcher.handleBlocks(Array.from(l2BlockNumbers))
const fnds = await proxyWatcher.handleL2Blocks(l2BlockNumbers)
proxyWatcherFindings.push(...fnds)
}

const bridgeBalanceFindings = await app.bridgeBalanceSrc.handleBlock(blockEvent.block.number, l2BlockNumbers)

findings.push(
...bridgeEventFindings,
...govEventFindings,
...proxyAdminEventFindings,
...monitorWithdrawalsFindings,
...proxyWatcherFindings,
...bridgeBalanceFindings,
)

app.healthChecker.check(findings)
Expand Down
39 changes: 27 additions & 12 deletions l2-bridge-base/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { FortaGuardClient } from './clients/forta_guard_client'
import { ethers, fetchJwt } from 'forta-agent'
import { IProvider, BaseProvider } from './clients/base_provider'
import { ethers, fetchJwt, getJsonRpcUrl } from 'forta-agent'
import { BaseClient } from './clients/base_client'
import { EventWatcher } from './services/event_watcher'
import { getL2BridgeEvents } from './utils/events/bridge_events'
import { getGovEvents } from './utils/events/gov_events'
import { getProxyAdminEvents } from './utils/events/proxy_admin_events'
import { ProxyContractClient } from './clients/proxy_contract_client'
import { Address } from './utils/constants'
import { L2Bridge__factory, ProxyShortABI__factory } from './generated'
import { ERC20Short__factory, L2Bridge__factory, ProxyShortABI__factory } from './generated'
import { BlockClient } from './clients/base_block_client'
import { ProxyWatcher } from './services/proxy_watcher'
import { MonitorWithdrawals } from './services/monitor_withdrawals'
Expand All @@ -17,13 +16,17 @@ import { Logger } from 'winston'
import { BorderTime, HealthChecker, MaxNumberErrorsPerBorderTime } from './services/health-checker/health-checker.srv'
import { verifyJwt } from 'forta-agent/dist/sdk/jwt'
import * as E from 'fp-ts/Either'
import { BridgeBalanceSrv } from './services/bridge_balance'
import { ETHProvider } from './clients/eth_provider_client'

export type Container = {
baseClient: IProvider
ethClient: ETHProvider
baseClient: BaseClient
proxyWatchers: ProxyWatcher[]
monitorWithdrawals: MonitorWithdrawals
blockSrv: BlockClient
bridgeWatcher: EventWatcher
bridgeBalanceSrc: BridgeBalanceSrv
govWatcher: EventWatcher
proxyEventWatcher: EventWatcher
findingsRW: FindingsRW
Expand Down Expand Up @@ -65,14 +68,13 @@ export class App {
transports: [new Winston.transports.Console()],
})

const baseRpcURL = FortaGuardClient.getSecret()

const baseNetworkID = 8453
const nodeClient = new ethers.providers.JsonRpcProvider(baseRpcURL, baseNetworkID)
const baseProvider = new ethers.providers.JsonRpcProvider('https://base.llamarpc.com', baseNetworkID)
const adr: Address = Address

const l2Bridge = L2Bridge__factory.connect(adr.L2_ERC20_TOKEN_GATEWAY_ADDRESS, nodeClient)
const baseClient = new BaseProvider(nodeClient, l2Bridge, logger)
const l2Bridge = L2Bridge__factory.connect(adr.L2_ERC20_TOKEN_GATEWAY_ADDRESS, baseProvider)
const bridgedWSthEthRunner = ERC20Short__factory.connect(adr.BASE_WST_ETH_BRIDGED_ADDRESS, baseProvider)
const baseClient = new BaseClient(baseProvider, l2Bridge, logger, bridgedWSthEthRunner)

const bridgeEventWatcher = new EventWatcher(
'BridgeEventWatcher',
Expand All @@ -90,14 +92,14 @@ export class App {
new ProxyWatcher(
new ProxyContractClient(
adr.L2_ERC20_TOKEN_GATEWAY,
ProxyShortABI__factory.connect(adr.L2_ERC20_TOKEN_GATEWAY.address, nodeClient),
ProxyShortABI__factory.connect(adr.L2_ERC20_TOKEN_GATEWAY.address, baseProvider),
),
logger,
),
new ProxyWatcher(
new ProxyContractClient(
adr.BASE_WST_ETH_BRIDGED,
ProxyShortABI__factory.connect(adr.BASE_WST_ETH_BRIDGED.address, nodeClient),
ProxyShortABI__factory.connect(adr.BASE_WST_ETH_BRIDGED.address, baseProvider),
),
logger,
),
Expand All @@ -107,12 +109,25 @@ export class App {

const monitorWithdrawals = new MonitorWithdrawals(baseClient, adr.L2_ERC20_TOKEN_GATEWAY_ADDRESS, logger)

const mainnet = 1
const drpcUrl = 'https://eth.drpc.org/'
const ethProvider = new ethers.providers.FallbackProvider([
new ethers.providers.JsonRpcProvider(getJsonRpcUrl(), mainnet),
new ethers.providers.JsonRpcProvider(drpcUrl, mainnet),
])

const wSthEthRunner = ERC20Short__factory.connect(adr.WSTETH_ADDRESS, ethProvider)
const ethClient = new ETHProvider(logger, wSthEthRunner)
const bridgeBalanceSrv = new BridgeBalanceSrv(logger, ethClient, adr.BASE_L1ERC20_TOKEN_BRIDGE, baseClient)

App.instance = {
ethClient: ethClient,
baseClient: baseClient,
proxyWatchers: proxyWatchers,
monitorWithdrawals: monitorWithdrawals,
blockSrv: blockSrv,
bridgeWatcher: bridgeEventWatcher,
bridgeBalanceSrc: bridgeBalanceSrv,
govWatcher: govEventWatcher,
proxyEventWatcher: proxyEventWatcher,
findingsRW: new FindingsRW([]),
Expand Down
8 changes: 4 additions & 4 deletions l2-bridge-base/src/clients/base_block_client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BlockDto } from 'src/entity/blockDto'
import { IProvider } from './base_provider'
import { BlockDto } from '../entity/blockDto'
import { IBaseClient } from './base_client'
import { Log } from '@ethersproject/abstract-provider'
import { Finding } from 'forta-agent'
import * as E from 'fp-ts/Either'
Expand All @@ -8,11 +8,11 @@ import { elapsedTime } from '../utils/time'
import { networkAlert } from '../utils/finding.helpers'

export class BlockClient {
private provider: IProvider
private provider: IBaseClient
private logger: Logger
private cachedBlockDto: BlockDto | undefined = undefined

constructor(provider: IProvider, logger: Logger) {
constructor(provider: IBaseClient, logger: Logger) {
this.provider = provider
this.logger = logger
}
Expand Down
34 changes: 34 additions & 0 deletions l2-bridge-base/src/clients/base_client.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { App } from '../app'
import * as E from 'fp-ts/Either'
import { ETH_DECIMALS } from '../utils/constants'
import BigNumber from 'bignumber.js'

describe('base provider tests', () => {
test('should fetch block logs', async () => {
const app = await App.getInstance()

const latestBlock = await app.baseClient.getLatestL2Block()
if (E.isLeft(latestBlock)) {
throw latestBlock
}

const blocksDto = await app.baseClient.getL2Logs(latestBlock.right.number, latestBlock.right.number)
if (E.isLeft(blocksDto)) {
throw blocksDto
}

expect(blocksDto.right.length).toBeGreaterThan(1)
}, 120_000)

test('getWstEthTotalSupply is 1696.070092078019991932 wsETH', async () => {
const app = await App.getInstance()

const baseBlockNumber = 13_022_744
const balance = await app.baseClient.getWstEthTotalSupply(baseBlockNumber)
if (E.isLeft(balance)) {
throw balance.left
}

expect(balance.right.dividedBy(ETH_DECIMALS)).toEqual(new BigNumber('11430.956916416032084584'))
}, 120_000)
})
Loading

0 comments on commit 37a7e4a

Please sign in to comment.