Skip to content

Commit

Permalink
feat: l2-bridge-mantle moved 🚨🚨🚨 Mantle bridge balance mismatch 🚨🚨🚨fr…
Browse files Browse the repository at this point in the history
…om l2-bridge-balance
  • Loading branch information
sergeyWh1te committed Apr 12, 2024
1 parent 4736473 commit 1f99b51
Show file tree
Hide file tree
Showing 26 changed files with 1,097 additions and 904 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/test-l2-bridge-mantle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: Tests @ l2-bridge-mantle

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

jobs:
tests:
uses: ./.github/workflows/_tests.yml
with:
path: ./l2-bridge-mantle
secrets: inherit
5 changes: 0 additions & 5 deletions l2-bridge-balance/src/agent-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ export async function handleBlock(blockEvent: BlockEvent) {
findings,
BRIDGE_PARAMS_WSTETH.ZkSync,
),
handleBridgeBalanceWstETH(
blockEvent,
findings,
BRIDGE_PARAMS_WSTETH.Mantle,
),

handleBridgeBalanceLDO(blockEvent, findings, BRIDGE_PARAMS_LDO.Arbitrum),
handleBridgeBalanceLDO(blockEvent, findings, BRIDGE_PARAMS_LDO.Optimism),
Expand Down
6 changes: 0 additions & 6 deletions l2-bridge-balance/src/config/bot-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
"Optimism": {
"RpcUrl": "https://mainnet.optimism.io"
},
"Base": {
"RpcUrl": "https://mainnet.base.org"
},
"ZkSync": {
"RpcUrl": "https://mainnet.era.zksync.io"
},
"Mantle": {
"RpcUrl": "https://mantle.publicnode.com"
}
}
7 changes: 0 additions & 7 deletions l2-bridge-balance/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export interface BridgeParamsWstETH {
Arbitrum: BridgeParamWstETH;
Optimism: BridgeParamWstETH;
ZkSync: BridgeParamWstETH;
Mantle: BridgeParamWstETH;
}

export const BRIDGE_PARAMS_WSTETH: BridgeParamsWstETH = {
Expand All @@ -43,12 +42,6 @@ export const BRIDGE_PARAMS_WSTETH: BridgeParamsWstETH = {
wstEthBridged: "0x703b52F2b28fEbcB60E1372858AF5b18849FE867",
rpcUrl: config.ZkSync.RpcUrl,
},
Mantle: {
name: "Mantle",
l1Gateway: "0x2D001d79E5aF5F65a939781FE228B267a8Ed468B",
wstEthBridged: "0x458ed78EB972a369799fb278c0243b25e5242A83",
rpcUrl: config.Mantle.RpcUrl,
},
};

export const LDO_ADDRESS = "0x5a98fcbea516cf06857215779fd812ca3bef1b32";
Expand Down
27 changes: 10 additions & 17 deletions l2-bridge-mantle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ the cache.
## Alerts

1. Bridge events
1. 🚨🚨🚨 Mantle L2 Bridge: Implementation initialized
2. 🚨 Mantle L2 Bridge: Deposits Disabled
3. 🚨 Mantle L2 Bridge: Role Admin changed
4. 🚨 Mantle L2 Bridge: Withdrawals Disabled
5. ⚠️ Mantle L2 Bridge: Role granted
6. ⚠️ Mantle L2 Bridge: Role revoked
7. ℹ️ Mantle L2 Bridge: Deposits Enabled
8. ℹ️ Mantle L2 Bridge: Withdrawals Enabled
1. 🚨🚨🚨 Mantle bridge balance mismatch 🚨🚨🚨
2. 🚨🚨🚨 Mantle L2 Bridge: Implementation initialized
3. 🚨 Mantle L2 Bridge: Deposits Disabled
4. 🚨 Mantle L2 Bridge: Role Admin changed
5. 🚨 Mantle L2 Bridge: Withdrawals Disabled
6. ⚠️ Mantle L2 Bridge: Role granted
7. ⚠️ Mantle L2 Bridge: Role revoked
8. ℹ️ Mantle L2 Bridge: Deposits Enabled
9. ℹ️ Mantle L2 Bridge: Withdrawals Enabled
2. Gov Events
1. 🚨 Mantle Gov Bridge: Ethereum Governance Executor Updated
2. 🚨 Mantle Gov Bridge: Guardian Updated
Expand Down Expand Up @@ -55,13 +56,5 @@ yarn install
Running in a live mode:

```
yarn start:dev
```

Testing on a specific block/range/transaction:

```
yarn block 13626668
yarn range '13626667..13626668'
yarn tx 0x2d2774c04e3faf9f17cd26e0978bb812081b9d0b5cc6fd8bf04cc441f92c0a8c
yarn start
```
8 changes: 4 additions & 4 deletions l2-bridge-mantle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,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",
"eslint:lint": "eslint ./src",
"eslint:format": "eslint ./src --fix",
"prettier:check": "prettier --check ./src",
"prettier:format": "prettier --write ./src",
"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-mantle/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"
}
]
64 changes: 64 additions & 0 deletions l2-bridge-mantle/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-mantle functional test', () => {
test('should process app on 62_394_250 and 62_394_300 (50 l2 blocks)', async () => {
const app = await App.getInstance()

const l1Block = 19_639_035
const l2StartBlock = 62_394_250
const l2EndBlock = 62_394_300
const l2BlocksDto = await app.mantleClient.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.bridgeBalanceSrv.handleBlock(l1Block, l2BlockNumbers)

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

expect(findings.length).toEqual(0)
}, 360_000)
})
74 changes: 44 additions & 30 deletions l2-bridge-mantle/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,43 @@ export function initialize(): Initialize {
return async function (): Promise<InitializeResponse | void> {
const app = await App.getInstance()

const latestBlock = await app.mantleClient.getLatestBlock()
if (E.isLeft(latestBlock)) {
app.logger.error(latestBlock.left)

const latestL2Block = await app.mantleClient.getLatestL2Block()
if (E.isLeft(latestL2Block)) {
app.logger.error(latestL2Block.left)
process.exit(1)
}

const agentMeta = await app.proxyWatcher.initialize(latestBlock.right.number)
if (E.isLeft(agentMeta)) {
app.logger.error(agentMeta.left)
const agents: string[] = []
for (const proxyWatcher of app.proxyWatchers) {
const proxyWatcherErr = await proxyWatcher.initialize(latestL2Block.right.number)
if (proxyWatcherErr !== null) {
app.logger.error(proxyWatcherErr)
process.exit(1)
}

process.exit(1)
metadata[`${proxyWatcher.getName()}.lastAdmin`] = proxyWatcher.getAdmin()
metadata[`${proxyWatcher.getName()}.lastImpl`] = proxyWatcher.getImpl()

agents.push(proxyWatcher.getName())
}

const monitorWithdrawalsInitResp = await app.monitorWithdrawals.initialize(latestBlock.right.number)
const monitorWithdrawalsInitResp = await app.monitorWithdrawals.initialize(latestL2Block.right.number)
if (E.isLeft(monitorWithdrawalsInitResp)) {
app.logger.error(monitorWithdrawalsInitResp.left)

process.exit(1)
}

metadata[`${app.proxyWatcher.getName()}.lastAdmins`] = agentMeta.right.lastAdmins
metadata[`${app.proxyWatcher.getName()}.lastImpls`] = agentMeta.right.lastImpls
metadata[`${app.monitorWithdrawals.getName()}.currentWithdrawals`] =
monitorWithdrawalsInitResp.right.currentWithdrawals

const agents: string[] = [app.proxyWatcher.getName(), app.monitorWithdrawals.getName()]
agents.push(app.monitorWithdrawals.getName())

metadata.agents = '[' + agents.toString() + ']'

await app.findingsRW.write([
Finding.fromObject({
name: 'Agent launched',
name: `Agent launched`,
description: `Version: ${VERSION.desc}`,
alertId: 'LIDO-AGENT-LAUNCHED',
severity: FindingSeverity.Info,
Expand Down Expand Up @@ -80,41 +85,50 @@ 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 mantle blocks from ${blocksDto.right[0].number} to ${
blocksDto.right[blocksDto.right.length - 1].number
}. Total: ${blocksDto.right.length}`,
`ETH block ${blockEvent.blockNumber.toString()}. Fetched mantle 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.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 l2BlockNumberSet: Set<number> = new Set<number>()
for (const l2log of l2logs.right) {
l2BlockNumberSet.add(new BigNumber(l2log.blockNumber, 10).toNumber())
}

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 l2BlockNumbers = Array.from(l2BlockNumberSet).toSorted((a, b) => a - b)
const proxyWatcherFindings: Finding[] = []

const blockNumbers: Set<number> = new Set<number>()
for (const log of logs.right) {
blockNumbers.add(new BigNumber(log.blockNumber, 10).toNumber())
for (const proxyWatcher of app.proxyWatchers) {
const fnds = await proxyWatcher.handleL2Blocks(l2BlockNumbers)
proxyWatcherFindings.push(...fnds)
}

const proxyWatcherFindings = await app.proxyWatcher.handleBlocks(Array.from(blockNumbers))
const bridgeBalanceFindings = await app.bridgeBalanceSrv.handleBlock(blockEvent.block.number, l2BlockNumbers)

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

app.logger.info(elapsedTime('handleBlock', startTime) + '\n')
Expand Down
Loading

0 comments on commit 1f99b51

Please sign in to comment.