Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: linea bridge balance mismatch moved to l2-bridge-linea #525

Merged
merged 6 commits into from
Apr 10, 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
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
Loading