Skip to content

Commit

Permalink
Merge pull request #525 from lidofinance/linea-bridge-balance-mismatch
Browse files Browse the repository at this point in the history
feat: linea bridge balance mismatch moved to l2-bridge-linea
  • Loading branch information
TheDZhon authored Apr 10, 2024
2 parents 6a53e46 + b7ea207 commit 999a602
Show file tree
Hide file tree
Showing 24 changed files with 400 additions and 231 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Install node
uses: actions/setup-node@v3
with:
node-version-file: "${{ inputs.path }}/.nvmrc"
node-version: 20.10.0
cache: yarn
cache-dependency-path: "**/yarn.lock"

Expand All @@ -42,7 +42,6 @@ jobs:
$HOME/.forta/forta.config.json
env:
URL: ${{ secrets.ETHEREUM_RPC_URL }}
if: ${{ steps.check_scripts.outputs.has_e2e == 'true' }}

- name: Run unit tests
run: yarn test
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/test-l2-bridge-linea.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: Tests @ l2-bridge-linea

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

jobs:
tests:
uses: ./.github/workflows/_tests.yml
with:
path: ./l2-bridge-linea
secrets: inherit
2 changes: 1 addition & 1 deletion l2-bridge-balance/src/agent-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export async function handleBlock(blockEvent: BlockEvent) {
findings,
BRIDGE_PARAMS_WSTETH.Mantle,
),
handleBridgeBalanceWstETH(blockEvent, findings, BRIDGE_PARAMS_WSTETH.Linea),

handleBridgeBalanceLDO(blockEvent, findings, BRIDGE_PARAMS_LDO.Arbitrum),
handleBridgeBalanceLDO(blockEvent, findings, BRIDGE_PARAMS_LDO.Optimism),
]);
Expand Down
3 changes: 0 additions & 3 deletions l2-bridge-balance/src/config/bot-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,5 @@
},
"Mantle": {
"RpcUrl": "https://mantle.publicnode.com"
},
"Linea": {
"RpcUrl": "https://linea.blockpi.network/v1/rpc/public"
}
}
7 changes: 0 additions & 7 deletions l2-bridge-balance/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export interface BridgeParamsWstETH {
Base: BridgeParamWstETH;
ZkSync: BridgeParamWstETH;
Mantle: BridgeParamWstETH;
Linea: BridgeParamWstETH;
}

export const BRIDGE_PARAMS_WSTETH: BridgeParamsWstETH = {
Expand Down Expand Up @@ -57,12 +56,6 @@ export const BRIDGE_PARAMS_WSTETH: BridgeParamsWstETH = {
wstEthBridged: "0x458ed78EB972a369799fb278c0243b25e5242A83",
rpcUrl: config.Mantle.RpcUrl,
},
Linea: {
name: "Linea",
l1Gateway: "0x051f1d88f0af5763fb888ec4378b4d8b29ea3319",
wstEthBridged: "0xB5beDd42000b71FddE22D3eE8a79Bd49A568fC8F",
rpcUrl: config.Linea.RpcUrl,
},
};

export const LDO_ADDRESS = "0x5a98fcbea516cf06857215779fd812ca3bef1b32";
Expand Down
7 changes: 4 additions & 3 deletions l2-bridge-linea/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ the cache.
## Alerts

1. Bridge events
1. 🚨 Linea L2 Bridge: Paused
2. 🚨 Linea L2 Bridge: Implementation initialized
3. ⚠️ Linea L2 Bridge: Unpaused
1. 🚨🚨🚨 Linea bridge balance mismatch 🚨🚨🚨
2. 🚨 Linea L2 Bridge: Paused
3. 🚨 Linea L2 Bridge: Implementation initialized
4. ⚠️ Linea L2 Bridge: Unpaused
2. Gov Events
1. 🚨 Linea Gov Bridge: Ethereum Governance Executor Updated
2. 🚨 Linea Gov Bridge: Guardian Updated
Expand Down
4 changes: 2 additions & 2 deletions l2-bridge-linea/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"generate-types": "typechain --target=ethers-v5 --out-dir=./src/generated ./src/abi/*",
"eslint:lint": "eslint ./src",
"eslint:format": "eslint ./src --fix",
"prettier:check": "prettier --check .",
"prettier:format": "prettier --write .",
"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
34 changes: 34 additions & 0 deletions l2-bridge-linea/src/abi/ERC20Short.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { App } from '../src/app'
import { App } from './app'
import * as E from 'fp-ts/Either'
import { Finding } from 'forta-agent'
import { handleBlock, initialize } from '../src/agent'
import { etherBlockToFortaBlockEvent } from './utils'

describe('agent-linea e2e tests', () => {
test('should process handleBlocks', async () => {
Expand All @@ -20,7 +18,7 @@ describe('agent-linea e2e tests', () => {
throw monitorWithdrawalsInitResp
}

const logs = await app.blockSrv.getLogs(blocksDto)
const logs = await app.blockSrv.getL2Logs(blocksDto)
if (E.isLeft(logs)) {
throw logs
}
Expand All @@ -30,9 +28,9 @@ describe('agent-linea e2e tests', () => {
blockNumbers.push(block.number)
}

const bridgeEventFindings = app.bridgeWatcher.handleLogs(logs.right)
const govEventFindings = app.govWatcher.handleLogs(logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleLogs(logs.right)
const bridgeEventFindings = app.bridgeWatcher.handleL2Logs(logs.right)
const govEventFindings = app.govWatcher.handleL2Logs(logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleL2Logs(logs.right)
const monitorWithdrawalsFindings = app.monitorWithdrawals.handleBlocks(logs.right, blocksDto)
const proxyWatcherFindings = await app.proxyWatcher.handleBlocks(blockNumbers)

Expand All @@ -47,24 +45,4 @@ describe('agent-linea e2e tests', () => {

expect(findings.length).toEqual(0)
}, 120_000)

test('should process app', async () => {
const init = initialize()
await init()

const handleBlocks = handleBlock()
const app = await App.getInstance()

const blocksDto = await app.LineaClient.fetchBlocks(2476530, 2476540)
const out: Finding[] = []
for (const b of blocksDto) {
const blockEvent = etherBlockToFortaBlockEvent(b)
const findings = await handleBlocks(blockEvent)

out.push(...findings)
}

expect(out.length).toEqual(1)
expect(out[0].name).toEqual(`Agent launched`)
}, 120_000)
})
40 changes: 23 additions & 17 deletions l2-bridge-linea/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,41 +83,47 @@ export const handleBlock = (): HandleBlock => {
findings.push(...findingsAsync)
}

const blocksDto = await app.blockSrv.getBlocks()
if (E.isLeft(blocksDto)) {
const l2blocksDto = await app.blockSrv.getL2Blocks()
if (E.isLeft(l2blocksDto)) {
isHandleBLockRunning = false
return [blocksDto.left]
return [l2blocksDto.left]
}
app.logger.info(
`ETH block ${blockEvent.blockNumber.toString()}. Fetched linea blocks from ${blocksDto.right[0].number} to ${
blocksDto.right[blocksDto.right.length - 1].number
}. Total: ${blocksDto.right.length}`,
`ETH block ${blockEvent.block.number}. Fetched linea blocks from ${l2blocksDto.right[0].number} to ${
l2blocksDto.right[l2blocksDto.right.length - 1].number
}. Total: ${l2blocksDto.right.length}`,
)

const logs = await app.blockSrv.getLogs(blocksDto.right)
if (E.isLeft(logs)) {
const l2logs = await app.blockSrv.getL2Logs(l2blocksDto.right)
if (E.isLeft(l2logs)) {
isHandleBLockRunning = false
return [logs.left]
return [l2logs.left]
}

const bridgeEventFindings = app.bridgeWatcher.handleLogs(logs.right)
const govEventFindings = app.govWatcher.handleLogs(logs.right)
const proxyAdminEventFindings = app.proxyEventWatcher.handleLogs(logs.right)
const monitorWithdrawalsFindings = app.monitorWithdrawals.handleBlocks(logs.right, blocksDto.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.handleBlocks(l2logs.right, l2blocksDto.right)

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

const proxyWatcherFindings = await app.proxyWatcher.handleBlocks(Array.from(blockNumbers))
const l2blockNumbers = Array.from(l2blockNumbersSet)

const [proxyWatcherFindings, bridgeBalanceFindings] = await Promise.all([
app.proxyWatcher.handleBlocks(l2blockNumbers),
app.BridgeBalanceSrv.handleBlock(blockEvent.block.number, l2blockNumbers),
])

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

app.logger.info(elapsedTime('handleBlock', startTime) + '\n')
Expand Down
42 changes: 31 additions & 11 deletions l2-bridge-linea/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { FortaGuardClient } from './clients/forta_guard_client'
import { ethers } from 'forta-agent'
import { ILineaProvider, LineaProvider } from './clients/linea_provider'
import { LineaProvider } from './clients/linea_provider'
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 { ProxyContract } from './clients/proxy_contract_client'
import { Address } from './utils/constants'
import { ProxyAdmin__factory, TokenBridge__factory } from './generated'
import { ERC20Short__factory, ProxyAdmin__factory, TokenBridge__factory } from './generated'
import { BlockClient } from './clients/linea_block_client'
import { ProxyWatcher } from './services/proxy_watcher'
import { MonitorWithdrawals } from './services/monitor_withdrawals'
import { FindingsRW } from './utils/mutex'
import * as Winston from 'winston'
import { Logger } from 'winston'
import { ETHProvider } from './clients/eth_provider_client'
import { BridgeBalanceSrv } from './services/bridge_balance'
import { getJsonRpcUrl } from 'forta-agent/dist/sdk/utils'
import { ethers } from 'ethers'

export type Container = {
LineaClient: ILineaProvider
ethClient: ETHProvider
LineaClient: LineaProvider
proxyWatcher: ProxyWatcher
monitorWithdrawals: MonitorWithdrawals
blockSrv: BlockClient
bridgeWatcher: EventWatcher
BridgeBalanceSrv: BridgeBalanceSrv
govWatcher: EventWatcher
proxyEventWatcher: EventWatcher
findingsRW: FindingsRW
Expand All @@ -39,14 +43,17 @@ export class App {
transports: [new Winston.transports.Console()],
})

const LineaRpcURL = FortaGuardClient.getSecret()
const LineaRpcURL = 'https://linea.drpc.org'

const lineaNetworkID = 59144
const nodeClient = new ethers.providers.JsonRpcProvider(LineaRpcURL, lineaNetworkID)
const drpcLineaProvider = new ethers.providers.JsonRpcProvider(LineaRpcURL, lineaNetworkID)
const adr: Address = Address

const l2Bridge = TokenBridge__factory.connect(adr.LINEA_TOKEN_BRIDGE, nodeClient)
const lineaClient = new LineaProvider(nodeClient, l2Bridge, logger)
const l2Bridge = TokenBridge__factory.connect(adr.LINEA_TOKEN_BRIDGE, drpcLineaProvider)

const bridgedWSthEthRunner = ERC20Short__factory.connect(adr.LINEA_WST_CUSTOM_BRIDGED_TOKEN, drpcLineaProvider)

const lineaClient = new LineaProvider(drpcLineaProvider, l2Bridge, logger, bridgedWSthEthRunner)

const bridgeEventWatcher = new EventWatcher(
'BridgeEventWatcher',
Expand All @@ -65,13 +72,13 @@ export class App {
adr.LINEA_L2_ERC20_TOKEN_BRIDGE.name,
adr.LINEA_L2_ERC20_TOKEN_BRIDGE.hash,
adr.ADMIN_OF_LINEA_L2_TOKEN_BRIDGE,
ProxyAdmin__factory.connect(adr.ADMIN_OF_LINEA_L2_TOKEN_BRIDGE, nodeClient),
ProxyAdmin__factory.connect(adr.ADMIN_OF_LINEA_L2_TOKEN_BRIDGE, drpcLineaProvider),
),
new ProxyContract(
adr.LINEA_WST_CUSTOM_BRIDGED.name,
adr.LINEA_WST_CUSTOM_BRIDGED.hash,
adr.LINEA_PROXY_ADMIN_FOR_WSTETH,
ProxyAdmin__factory.connect(adr.LINEA_PROXY_ADMIN_FOR_WSTETH, nodeClient),
ProxyAdmin__factory.connect(adr.LINEA_PROXY_ADMIN_FOR_WSTETH, drpcLineaProvider),
),
]

Expand All @@ -80,8 +87,21 @@ export class App {

const monitorWithdrawals = new MonitorWithdrawals(lineaClient, adr.LINEA_TOKEN_BRIDGE, 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.LINEA_L1_TOKEN_BRIDGE, lineaClient)

App.instance = {
ethClient: ethClient,
LineaClient: lineaClient,
BridgeBalanceSrv: bridgeBalanceSrv,
proxyWatcher: proxyWorker,
monitorWithdrawals: monitorWithdrawals,
blockSrv: blockSrv,
Expand Down
19 changes: 19 additions & 0 deletions l2-bridge-linea/src/clients/eth_provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { App } from '../app'
import * as E from 'fp-ts/Either'
import { Address, ETH_DECIMALS } from '../utils/constants'
import BigNumber from 'bignumber.js'

describe('eth provider tests', () => {
test('getBalanceByBlockHash is 1774.48511061073977627 wsETH', async () => {
const app = await App.getInstance()
const adr = Address

const blockNumber = 19_619_102
const balance = await app.ethClient.getWstEthBalance(blockNumber, adr.LINEA_L1_TOKEN_BRIDGE)
if (E.isLeft(balance)) {
throw balance.left
}

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

0 comments on commit 999a602

Please sign in to comment.