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

Eth steth #459

Merged
merged 22 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
36e80be
feat: eth-steth-v2
sergeyWh1te Jan 10, 2024
688160b
feat: StethOperation Service handle block
sergeyWh1te Jan 11, 2024
606e324
feat: StethOperation Service handle transaction
sergeyWh1te Jan 11, 2024
74fdd92
feat: eth-steth bot v2
sergeyWh1te Jan 17, 2024
d8b391c
feat: eth-steth bot v2. fix linter warnings
sergeyWh1te Jan 17, 2024
8fef2e3
feat: eth-steth bot v2. fix linter warnings
sergeyWh1te Jan 17, 2024
4e5e20c
feat: eth-steth bot v2. update packages
sergeyWh1te Jan 17, 2024
7d24e0f
feat: cover by tests StethOperationSrv initialize, handleBufferedEth …
sergeyWh1te Jan 22, 2024
8f4721a
feat: ethereum-steth-v2 moved functional tests
sergeyWh1te Jan 24, 2024
7c5cd86
feat: ethereum-steth-v2 fix code style
sergeyWh1te Jan 24, 2024
904b34a
feat: ethereum-steth-v2 handle tokenRebased event
sergeyWh1te Jan 25, 2024
da09ac6
feat: ethereum-steth-v2 added ScannerId
sergeyWh1te Jan 25, 2024
42bc03e
feat: ethereum-steth-v2 fix cs
sergeyWh1te Jan 25, 2024
8f4311b
feat: ethereum-steth-v2 fix cs
sergeyWh1te Jan 26, 2024
e572e37
feat: ethereum-steth-v2 fix cs
sergeyWh1te Jan 26, 2024
61cc10e
feat: ethereum-steth-v2 moved mocks
sergeyWh1te Jan 26, 2024
a39e0a2
feat: ethereum-steth-v2 fix tests
sergeyWh1te Jan 26, 2024
28db487
feat: ethereum-steth-v2 remove unnecessary ts compiler configs
sergeyWh1te Jan 26, 2024
cfac870
feat: ethereum-steth-v2 cs fixes
sergeyWh1te Jan 26, 2024
7d65e17
fix: eth-steth fix cs
sergeyWh1te Jan 29, 2024
a9f30ab
fix: eth-steth fix cs
sergeyWh1te Jan 29, 2024
7eeb120
fix: eth-steth pasted touched files from main branch
sergeyWh1te Jan 29, 2024
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: 3 additions & 0 deletions ethereum-steth-v2/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
forta.config.json
14 changes: 14 additions & 0 deletions ethereum-steth-v2/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"parser": "@typescript-eslint/parser",
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"plugins": ["@typescript-eslint", "prettier"],
"env": {
"node": true,
"es6": true
},
"rules": {
"prettier/prettier": "error",
"curly": "error",
"semi": "off"
}
}
9 changes: 9 additions & 0 deletions ethereum-steth-v2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
dist
forta.config.json
.yarn/*
!.yarn/releases/
*.log
version.json
.DS_Store
/coverage/
7 changes: 7 additions & 0 deletions ethereum-steth-v2/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": false,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2
}
24 changes: 24 additions & 0 deletions ethereum-steth-v2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Build stage: compile Typescript to Javascript
FROM node:20.10.0-alpine3.18 AS base

FROM base as builder

WORKDIR /app

COPY . .
RUN yarn install --immutable && yarn run build
# Build app
RUN yarn run build

# Final stage: copy compiled Javascript from previous stage and install production dependencies
FROM base as production
LABEL "network.forta.settings.agent-logs.enable"="true"
ENV NODE_ENV=production
WORKDIR /app

COPY package*.json yarn.lock ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./src
COPY version.json ./

CMD ["yarn", "run", "start:prod"]
107 changes: 107 additions & 0 deletions ethereum-steth-v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Lido Ethereum StETH bot

## Supported chains

- Ethereum mainnet

## Alerts

1. StETH operations
TheDZhon marked this conversation as resolved.
Show resolved Hide resolved
1. HandleBlock
1. 🚨🚨🚨 Buffered ETH drain (checks each block)
2. 🚨 Huge depositable ETH amount (checks every 100 blocks)
3. ⚠️ High depositable ETH amount (checks every 100 blocks)
4. ⚠️ Low deposit executor balance (checks every 100 blocks)
5. ⚠️ Unspent staking limit below 10% (checks every 25 blocks)
6. πŸ“‰ Unspent staking limit below 30% (checks every 25 blocks)
2. HandleTransaction
1. Deposit Security events
2. 🚨 Deposit Security: Deposits paused
3. 🚨 Deposit Security: Guardian quorum changed
4. 🚨 Deposit Security: Owner changed
5. ⚠️ Deposit Security: Deposits resumed
6. ⚠️ Deposit Security: Guardian added
7. ⚠️ Deposit Security: Guardian removed
8. ⚠️ Deposit Security: Max deposits changed
9. ⚠️ Deposit Security: Min deposit block distance changed
3. Lido events
1. 🚨🚨🚨 Lido: Stopped 🚨🚨🚨
2. 🚨🚨🚨 Share rate unexpected has changed
3. 🚨 Lido: Staking limit removed
4. 🚨 Lido: Locator set
5. ⚠️ Lido: Resumed
6. 🚨 Lido: Staking paused
7. ⚠️ Lido: Staking resumed
8. ⚠️ Lido: Staking limit set
9. ⚠️ Lido: Funds recovered to vault
10. ⚠️ Lido: Contract version set
11. ℹ️ Lido: Token rebased
4. Insurance fund events
1. 🚨 Insurance fund: ERC20 transferred
2. 🚨 Insurance fund: Ownership transferred
3. ⚠️ Insurance fund: ETH transferred
4. ⚠️ Insurance fund: ERC1155 transferred
5. ⚠️ Insurance fund: ERC721 transferred
5. Burner events
1. ℹ️ Lido Burner: ERC20 recovered
2. ℹ️ Lido Burner: ERC721 recovered
2. Withdrawals
1. HandleBlock runs on each 100-th block or one per 20 minutes
1. ⚠️ Withdrawals: <limitRate>% of stake limit is spent and unfinalized queue is on par with drained stake
limit
2. ⚠️ Withdrawals: unfinalized queue is more than 100_000 stETH
3. ⚠️ Withdrawals: unfinalized queue wait time is <hours> more than 1 day
4. ⚠️ Withdrawals: ${unclaimedSizeRate.times(100).toFixed(2)}% of finalized requests are unclaimed
5. ⚠️ Withdrawals: unclaimed requests size is more than withdrawal queue balance
2. HandleTransaction
1. 🚨 Withdrawals: BUNKER MODE ON! 🚨
2. 🚨 Withdrawals: contract was paused
3. ⚠️ Withdrawals: BUNKER MODE OFF! βœ…
4. ℹ️ Huge stETH withdrawal requests batch
5. ⚠️ Withdrawals: the sum of received withdrawal requests since the last rebase greater than 150_000 stETH (max
staking limit)
6. ⚠️ Withdrawals: claimed amount is more than requested
7. ⚠️ Withdrawals: contract was unpaused
3. GateSeal
1. HandleBlock runs on each next block
1. 🚨 GateSeal: actual address doesn't have PAUSE_ROLE for contracts
2. 🚨 GateSeal: is expired!
3. 🚨️ GateSeal: is expired. Update code!
4. ⚠️ GateSeal: default GateSeal address in forta agent is expired
5. ⚠️️ GateSeal: default GateSeal address in forta agent doesn't have PAUSE_ROLE for contracts
6. ⚠️ GateSeal: is about to be expired
2. HandleTransaction
1. 🚨🚨🚨 GateSeal: is sealed 🚨🚨🚨
2. 🚨 GateSeal: is expired
4. Vaults
1. Handleblock
1. 🚨🚨🚨 Withdrawal Vault balance mismatch. [without oracle report]
2. 🚨🚨🚨 Withdrawal Vault balance mismatch. [within oracle report]
3. 🚨🚨🚨 EL Vault balance mismatch. [without oracle report]
4. 🚨🚨🚨 EL Vault balance mismatch. [within oracle report]
5. πŸ’΅ Withdrawal Vault Balance significant change (checks every on 100-th block)
6. πŸ’΅ EL Vault Balance significant change
2. HandleTransaction
1. 🚨 Burner shares transfer

## Development (Forta specific)

Edit `alerting-forta/<SUBMODULE>/forta.config.json` and set `jsonRpcUrl` to your JSON-RPC provider. Install deps:

```
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
```
6 changes: 6 additions & 0 deletions ethereum-steth-v2/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import("ts-jest").JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['dist'],
}
87 changes: 87 additions & 0 deletions ethereum-steth-v2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"name": "lido-steth-forta-bot",
"version": "1.0.0",
"description": "Forta Bot for Lido stETH",
"repository": {
"type": "git",
"directory": "https://github.com/lidofinance/alerting-forta/tree/main/ethereum-steth"
},
"license": "MIT",
"chainIds": [
1
],
"husky": {
"hooks": {
"pre-commit": "yarn run lint"
}
},
"scripts": {
"update-version": "node ../utils/write-version.js",
"build": "tsc && yarn run copy-version",
"copy-version": "cp version.json dist",
"start": "yarn run update-version && yarn run start:dev",
"start:dev": "nodemon --watch src --watch forta.config.json -e js,ts,json --exec \"yarn run build && yarn run copy-version && forta-agent run\"",
"start:prod": "forta-agent run --prod",
"tx": "yarn run build && forta-agent run --tx",
"block": "yarn run build && forta-agent run --block",
"range": "yarn run build && forta-agent run --range",
"alert": "yarn run build && forta-agent run --alert",
"sequence": "yarn run build && forta-agent run --sequence",
"file": "yarn run build && forta-agent run --file",
"publish": "yarn run update-version && forta-agent publish",
"info": "forta-agent info",
"logs": "forta-agent logs",
"push": "yarn run update-version && forta-agent push",
"disable": "forta-agent disable",
"enable": "forta-agent enable",
"keyfile": "forta-agent keyfile",
"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",
"lint": "yarn run prettier:check && yarn run eslint:lint",
"format": "yarn run eslint:format && yarn run prettier:format",
"postinstall": "yarn generate-types"
},
"dependencies": {
"@types/lodash": "^4.14.202",
"async-mutex": "^0.4.0",
"bignumber.js": "^9.1.2",
"ethers": "^5.5.1",
"forta-agent": "^0.1.48",
"fp-ts": "^2.16.1",
"lodash": "^4.17.21",
"ts-retry": "^4.2.4",
"winston": "^3.11.0",
"@ethersproject/abi": "^5.0.0",
"@ethersproject/providers": "^5.0.0"
},
"devDependencies": {
"@faker-js/faker": "^8.3.1",
"@jest/globals": "^29.7.0",
"@tsconfig/node20": "^20.1.2",
"@typechain/ethers-v5": "^11.1.2",
"@types/jest": "^29.5.11",
"@types/nodemon": "^1.19.0",
"@types/ws": "^8.5.10",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-prettier": "^5.0.1",
"husky": "^8.0.3",
"jest": "^29.7.0",
"nodemon": "^3.0.1",
"postinstall": "^0.8.0",
"prettier": "^3.1.0",
"ts-generator": "^0.1.1",
"ts-jest": "^29.1.2",
"typechain": "^8.3.2",
"typescript": "^5.3.2"
},
"packageManager": "yarn@1.22.21"
}
67 changes: 67 additions & 0 deletions ethereum-steth-v2/src/abi/GateSeal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[
{
"name": "Sealed",
"inputs": [
{ "name": "gate_seal", "type": "address", "indexed": false },
{ "name": "sealed_by", "type": "address", "indexed": false },
{ "name": "sealed_for", "type": "uint256", "indexed": false },
{ "name": "sealable", "type": "address", "indexed": false },
{ "name": "sealed_at", "type": "uint256", "indexed": false }
],
"anonymous": false,
"type": "event"
},
{
"stateMutability": "nonpayable",
"type": "constructor",
"inputs": [
{ "name": "_sealing_committee", "type": "address" },
{ "name": "_seal_duration_seconds", "type": "uint256" },
{ "name": "_sealables", "type": "address[]" },
{ "name": "_expiry_timestamp", "type": "uint256" }
],
"outputs": []
},
{
"stateMutability": "view",
"type": "function",
"name": "get_sealing_committee",
"inputs": [],
"outputs": [{ "name": "", "type": "address" }]
},
{
"stateMutability": "view",
"type": "function",
"name": "get_seal_duration_seconds",
"inputs": [],
"outputs": [{ "name": "", "type": "uint256" }]
},
{
"stateMutability": "view",
"type": "function",
"name": "get_sealables",
"inputs": [],
"outputs": [{ "name": "", "type": "address[]" }]
},
{
"stateMutability": "view",
"type": "function",
"name": "get_expiry_timestamp",
"inputs": [],
"outputs": [{ "name": "", "type": "uint256" }]
},
{
"stateMutability": "view",
"type": "function",
"name": "is_expired",
"inputs": [],
"outputs": [{ "name": "", "type": "bool" }]
},
{
"stateMutability": "nonpayable",
"type": "function",
"name": "seal",
"inputs": [{ "name": "_sealables", "type": "address[]" }],
"outputs": []
}
]
33 changes: 33 additions & 0 deletions ethereum-steth-v2/src/abi/GateSealFactory.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[
{
"name": "GateSealCreated",
"inputs": [{ "name": "gate_seal", "type": "address", "indexed": false }],
"anonymous": false,
"type": "event"
},
{
"stateMutability": "nonpayable",
"type": "constructor",
"inputs": [{ "name": "_blueprint", "type": "address" }],
"outputs": []
},
{
"stateMutability": "view",
"type": "function",
"name": "get_blueprint",
"inputs": [],
"outputs": [{ "name": "", "type": "address" }]
},
{
"stateMutability": "nonpayable",
"type": "function",
"name": "create_gate_seal",
"inputs": [
{ "name": "_sealing_committee", "type": "address" },
{ "name": "_seal_duration_seconds", "type": "uint256" },
{ "name": "_sealables", "type": "address[]" },
{ "name": "_expiry_timestamp", "type": "uint256" }
],
"outputs": []
}
]
Loading
Loading