← Writing

The Guardian of the Chain: In Practice & Future (Part 3/3)

7 min read

TL;DR

Table of Contents

Introduction

Hook: On March 13, 2023, Euler Finance was exploited for nearly $197 million. The exploit-analyzer lets you replay that timeline with invariant checks and see exactly when a violation would have been detected.

Context: In Part 1 we introduced the CLI and invariant-based replay; in Part 2 we walked through the Rust architecture. Here we run the Euler Finance case study step-by-step, interpret the outputs, and outline the roadmap.

Preview: You’ll get a concrete walkthrough (clone, build, seed, list, analyze, view results), correct clone and config examples with no private keys in files, and a concise roadmap for where the project is headed.

Background: Euler Finance Exploit

Euler Finance was a lending protocol: users deposit assets and borrow against them. Solvency is the core invariant: reserves ≥ liabilities. In March 2023, an attacker exploited a flaw in the protocol’s internal accounting (a “donation” that skewed accounting), leading to a ~$197M drain.

Replaying blocks with a reserve_ratio_min invariant (e.g. reserves / liabilities ≥ 1.0) shows the first block where that invariant is violated and the detection lead time—how many blocks or minutes before the main exploit. That’s what the analyzer produces.

Case Study: Replay and Results

The Invariant

For the Euler case study, the config uses a solvency-style invariant:

When the ratio drops below 1.0, the analyzer records a violation and the block number.

What the Replay Shows

The analyzer replays a block range around the exploit (e.g. 100 blocks before, 10 after) and evaluates the invariant every block. From the Quick Start guide, a typical run reports something like:

So the same invariant logic would have flagged the issue 7 minutes before the major drain—proof that invariant-based replay can answer “when could we have known?”

Interpreting the Artifacts

Step-by-Step: Run the Euler Analysis Yourself

1. Clone and build

git clone https://github.com/RahilBhavan/Smart-Contract-Invariant-Monitor-and-Guardian-.git
cd "Smart Contract Invariant Monitor and Guardian "
cd monitor
cargo build --release

2. Seed the exploit database

cargo run --bin exploit-analyzer -- seed

This populates known exploits, including Euler Finance.

3. List exploits and get the Euler ID

cargo run --bin exploit-analyzer -- list

Use the exploit ID shown for the Euler Finance entry (e.g. in the format suggested by the list output). You’ll pass it as --exploit-id in the next step.

4. Set RPC URL and run analysis

Use a mainnet RPC endpoint (e.g. Alchemy or Infura). Never commit API keys or secrets to the repo.

export RPC_URL="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"

# Replace <EXPLOIT_ID> with the ID from `list`
cargo run --bin exploit-analyzer -- analyze \
  --exploit-id "<EXPLOIT_ID>" \
  --config config/case-studies/euler.json \
  --rpc-url "$RPC_URL" \
  --blocks-before 100 \
  --blocks-after 10 \
  --output output/euler-analysis

5. View results

ls output/euler-analysis/
cat output/euler-analysis/Euler-Finance-*/report.md
cat output/euler-analysis/Euler-Finance-*/violations.json
cat output/euler-analysis/Euler-Finance-*/run-metadata.json

You should see the first violation block, detection lead time (~35 blocks / ~7 minutes), and full violation timeline.

Getting Started With Your Own Config

To replay a custom block range with your own invariants:

  1. Define invariants in a JSON config (see Part 2 for structure). Use the same schema as config/case-studies/euler.json or config/invariants.json in the repo.

  2. Use environment variables for secrets. Do not put RPC API keys or private keys in config files or in git.

    export RPC_URL="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"

    If you later use Guardian or other features that need a signing key, keep it in an env var (e.g. GUARDIAN_PRIVATE_KEY) and load it in code or tooling—never commit it.

  3. Run a replay:

    cargo run --bin exploit-analyzer -- replay \
      --config config/invariants.json \
      --rpc-url "$RPC_URL" \
      --start-block 18000000 \
      --end-block 18000100 \
      --output output/custom-replay

Warning: Never store private keys or API keys in config files or version control. Use environment variables or a secrets manager and restrict access.

The Road Ahead: Future Improvements

The project is open source and evolving. Possible directions (not commitments):

  1. Multi-chain: Support for L2s (Arbitrum, Optimism, Base) and different finality rules; cross-chain invariant analysis.
  2. Anomaly detection: ML or statistical methods beyond binary invariants (e.g. gas or volume anomalies).
  3. Enterprise integrations: Secret management (e.g. Azure Key Vault, GCP Secret Manager, AWS Secrets Manager), SSO.
  4. Alerting: Richer alert channels (e.g. SMTP, SMS, custom webhooks) and aggregation.
  5. Performance: Parallel block and invariant processing, horizontal scaling for large replays.
  6. Invariant types: Time-based, cross-protocol, or composite invariants; pluggable types.

Check the GitHub repo and docs for the latest roadmap and contribution guidelines.

Common Pitfalls to Avoid

Pitfall 1: Over-reliance on a single invariant type

What goes wrong: You only check one thing (e.g. reserve ratio) and miss other failure modes.

How to avoid it: Start with critical invariants (e.g. solvency), then add others (health factors, oracle deviation) and tune severity. Replay past incidents to validate.

Pitfall 2: Secrets in config or git

What goes wrong: RPC API keys or private keys end up in JSON files and get committed.

How to avoid it: Use environment variables (e.g. RPC_URL, GUARDIAN_PRIVATE_KEY) and never commit secrets. Add *.env and secret-containing configs to .gitignore.

Pitfall 3: Wrong block range or exploit ID

What goes wrong: Replay misses the exploit or analyzes the wrong event.

How to avoid it: Use list and show <id> to confirm exploit IDs and block numbers. For custom replays, choose start/end blocks so the range covers the event you care about.

Conclusion

Summary: Part 3 walked through the Euler Finance case study: what the exploit was, how the exploit-analyzer replays it with a reserve-ratio invariant, and how to run the same analysis yourself. The replay shows invariant violation would have been detected 7 minutes before the major drain. We also covered clone/build/seed/list/analyze, correct use of env vars for secrets (no private keys in config), and a concise roadmap.

Key takeaways:

Call to action:

Tip: Start with the built-in Euler case study and config; then duplicate and adapt the config for your own protocol and block ranges.

Additional Resources


Tags: case-study, defi, security, euler-finance, roadmap