Git Product home page Git Product logo

lidofinance / alerting-forta Goto Github PK

View Code? Open in Web Editor NEW
35.0 23.0 7.0 11.08 MB

Forta Detection bots for Lido

Home Page: https://app.forta.network/bots?search=0x6aea36c4a9cf8ac053c07e662fa27e8bdf047121&sort=recent

License: GNU General Public License v3.0

Dockerfile 0.77% JavaScript 0.85% TypeScript 98.19% Makefile 0.20%
ethereum polygon optimism-l2 arbitrum-l2 tools base-l2 linea-l2 mantle-l2 zksync-l2

alerting-forta's People

Contributors

alexandrmov avatar arwer13 avatar batmah69 avatar bulbozaur avatar dependabot[bot] avatar dgusakov avatar diraiks avatar f4ever avatar gregshestakovlido avatar ivan-feofanov avatar katamarinaki avatar larmork avatar madlabman avatar ptqa avatar sergeywh1te avatar skhomuti avatar skozin avatar thedzhon avatar vgorkavenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alerting-forta's Issues

Using `blockNumber - 1` instead of `block.parentHash` is a subject to reorg false alarms

tl;dr

When the alert logic requires to query something from the previous block, it's better to use the block.parentHash instead of blockNumber - 1 to avoid issues with the Ethereum chain reorganizations.

How to fix

See the following reference code:
https://github.com/lidofinance/alerting-forta/blob/main/ethereum-steth/src/clients/eth_provider.ts#L181-L196

  public async getBalanceByBlockHash(address: string, blockHash: string): Promise<E.Either<Error, BigNumber>> {
    try {
      const out = await retryAsync<EtherBigNumber>(
        async (): Promise<EtherBigNumber> => {
          return await this.jsonRpcProvider.getBalance(address, {
            blockHash: blockHash,
          } as never)
        },
        { delay: DELAY_IN_500MS, maxTry: ATTEMPTS_5 },
      )

      return E.right(new BigNumber(String(out)))
    } catch (e) {
      return E.left(new NetworkError(e, `Could not fetch balance by address ${address} and blockHash ${blockHash}`))
    }
  }

https://github.com/lidofinance/alerting-forta/blob/main/ethereum-steth/src/services/vault/Vault.srv.ts#L60-L63

const prevBlockWithdrawalVaultBalance = await this.ethProvider.getBalanceByBlockHash(
  this.withdrawalsVaultAddress,
  blockEvent.block.parentHash,
)

Affected scope

List of the files that affected by the issue:

grep --include=\*.ts -rnw '.' -e ".*umber - 1" --exclude-dir=node_modules

./ethereum-validators-set/src/subagents/lido-report/agent-lido-report.ts:841:    blockTag: txEvent.blockNumber - 1,
./ethereum-validators-set/src/subagents/exitbus-oracle/agent-exitbus-oracle.ts:283:      blockEvent.blockNumber - 1,
./ethereum-validators-set/src/subagents/accounting-oracle/agent-accounting-oracle.ts:140:      blockEvent.blockNumber - 1,
./ethereum-validators-set/src/subagents/accounting-oracle/agent-accounting-oracle.ts:148:        blockEvent.blockNumber - 1,
./l2-bridge-linea/src/clients/linea_block_client.ts:72:      const blocks = await this.provider.fetchBlocks(this.cachedBlockDto.number, latestBlock.right.number - 1)
./l2-bridge-mantle/src/clients/mantle_block_client.ts:72:      const blocks = await this.mantleProvider.fetchBlocks(this.cachedBlockDto.number, latestBlock.right.number - 1)
./voting-watcher/src/agent-voting-watcher.ts:156:  const prevBlock = await ethersProvider.getBlock(blockEvent.blockNumber - 1);
./ethereum-steth/src/services/steth_operation/StethOperation.srv.ts:230:      this.ethProvider.getBufferedEther(shiftedBlockNumber - 1),
./l2-bridge-base/src/services/monitor_withdrawals.ts:54:    const withdrawalEvents = await this.withdrawalsClient.getWithdrawalEvents(pastl2Block, l2BlockNumber - 1)
./l2-bridge-base/src/clients/base_block_client.ts:72:      const blocks = await this.provider.fetchL2Blocks(this.cachedBlockDto.number, latestBlock.right.number - 1)
./ethereum-financial/src/services/aave/Aave.srv.ts:63:        this.ethProvider.getStethBalance(this.aaveAstethAddress, blockEvent.number - 1),
./ethereum-financial/src/services/aave/Aave.srv.ts:64:        await this.ethProvider.getTotalSupply(blockEvent.number - 1),
./ethereum-financial/src/services/aave/Aave.srv.ts:101:              `${blockEvent.number - 1}`,
./l2-bridge-zksync/src/clients/zksync_block_client.ts:72:      const blocks = await this.provider.fetchBlocks(this.cachedBlockDto.number, latestBlock.right.number - 1)

Explanations and references

References

Helpful picture

image

GateSeal expiration alert hadn't been fired timely

tl;dr

GateSeal expiration alert should have been fired three days ago because the contract's expiration date is set to May, 1st and the expiration threshold for the alert is four weeks (28 days).

Description

The currently deployed GateSeal instance has an expiration timestamp set at 1714521600, i.e., 25 days away.

However, the following code should have fired an alert three days ago:

const GATE_SEAL_EXPIRY_THRESHOLD = ONE_MONTH
const GATE_SEAL_EXPIRY_TRIGGER_EVERY = ONE_WEEK
...
    } else if (
      currentBlockTimestamp - this.cache.getLastExpiryGateSealAlertTimestamp() >
      GATE_SEAL_EXPIRY_TRIGGER_EVERY
    ) {
      if (Number(expiryTimestamp) - currentBlockTimestamp <= GATE_SEAL_EXPIRY_THRESHOLD) {
        out.push(
          Finding.fromObject({
            name: '⚠️ GateSeal: is about to be expired',
            description: `GateSeal address: ${etherscanAddress(this.gateSealAddress)}\nExpiry date ${new Date(
              String(expiryTimestamp),
            )}`,
            alertId: 'GATE-SEAL-IS-ABOUT-TO-BE-EXPIRED',
            severity: FindingSeverity.Medium,
            type: FindingType.Degraded,
          }),
        )
        this.cache.setLastExpiryGateSealAlertTimestamp(currentBlockTimestamp)
      }
    }

Unluckily, it hadn't been fired due to the unknown reason (edited)

References

How to reproduce

Given the expiration timestamp value is 1714521600, substracting GATE_SEAL_EXPIRY_THRESHOLD (which is 60 * 60 * 24 * 7 * 4 = 2419200 gives us 1714521600 - 2419200 = 1712102400, using the following API to fetch the block just after the threshold value:

https://api.findblock.xyz/v1/chain/1/block/after/1712102400
can conclude that the alert should have fired in the block 19571532

Add more networks for `l2-bridge-ethereum`

Currently, the l2-bridge-ethereum agent supports only:

  • wstETH on Arbitrum bridge (L1 part)
  • wstETH on Arbitrum bridge (L2 part)

Worth extending support for:

  • wstETH on Base (L1 part, as the network in production atm)
  • wstETH on zkSync (L1 part, as the network in the proposed state)

@sergeyWh1te, it would be great if you could take over the initiative here
cc: @arwer13 for future improvement (we missed this part for Base I guess)

L2-bridge-balance is sunsetting

Need to move alerts to relevant bots:

  • - l2-bridge-linea
  • - l2-bridge-base
  • - l2-bridge-mantle
  • - l2-bridge-zkSync
  • - l2-bridge-Arbitrum
  • - l2-bridge-Optimism

Alerting for a.DI on BSC: follow up

Target bot: bsc-adi-governance

There are still things that needed to be done in order to achieve ✨ perfection ✨:

Alerts

  • 🚨 BSC a.DI: Allowed Bridges quorum updated
  • 🚨 BSC a.DI: Allowed bridges set updated

Changing GateSeal address

Context
Today we are starting the on-chain vote to change GateSeal address to pause wq and vebo contracts.
The vote will end on Fri, Apr, 26 at about 5 PM.

Proposal

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.