Quick Start Guide

This guide provides step-by-step instructions for setting up OpenZeppelin Monitor. It includes prerequisites, installation, and configuration examples.

Prerequisites

  • Rust 2021 edition

  • Docker (optional, for containerized deployment)

Environment Configuration

Logging Configuration

Configure the logging verbosity level:

  1. Error

  2. Warn

  3. Info

  4. Debug

  5. Trace

RUST_LOG=info

Local Configuration

Copy the example environment file and update values according to your needs

cp .env.example .env

For details on the supported values see User Documentation - Basic Configuration

Installation

Local Installation

  1. Clone the repository:

    git clone https://github.com/openzeppelin/openzeppelin-monitor
    cd openzeppelin-monitor
  2. Install dependencies:

    cargo build

Standalone CLI Usage

  1. View available options:

    ./openzeppelin-monitor --help
  2. Enable logging to file with --log-file

  3. Enable metrics server with --metrics

Docker Installation

Basic Setup

  1. Start the services using docker compose:

    docker compose up

By default, Docker Compose uses Dockerfile.development. To use production settings, set: DOCKERFILE=Dockerfile.production before running the command.

Metrics Configuration

The metrics server, Prometheus, and Grafana can be enabled by setting METRICS_ENABLED=true in your .env file.

You can start services directly with Docker Compose:

# without metrics profile ( METRICS_ENABLED=false by default )
docker compose up -d

# With metrics enabled
docker compose --profile metrics up -d

To view prometheus metrics in a UI, you can use http://localhost:9090 on your browser.

To view grafana dashboard, you can use http://localhost:3000 on your browser.

By default, predefined metrics within a dashboard is populated in grafana.

Management Commands

  1. Verify container status:

    docker ps -a
  2. Stop services:

    # without metrics profile
    docker compose down
    
    # or with metrics profile
    docker compose --profile metrics down
  3. View logs (stdout):

    docker compose logs -f

Examples:

Monitoring USDC transfers (EVM):

1. Network Configuration:

Create the Ethereum mainnet network configuration:

cp config/networks/ethereum_mainnet.json.example config/networks/ethereum_mainnet.json

The default configuration should work, but you may want to update the RPC URL to your preferred provider.

{
  "network_type": "EVM",
  "slug": "ethereum_mainnet",
  "name": "Ethereum Mainnet",
  "rpc_urls": [
    {
      "type_": "rpc",
      "url": "YOUR_RPC_URL_HERE",
      "weight": 100
    }
  ],
  "chain_id": 1,
  "block_time_ms": 12000,
  "confirmation_blocks": 12,
  "cron_schedule": "0 */1 * * * *",
  "max_past_blocks": 18,
  "store_blocks": false
}

2. Monitor Configuration:

Create the USDC transfer monitor configuration:

cp config/monitors/evm_transfer_usdc.json.example config/monitors/evm_transfer_usdc.json

This configuration monitors USDC transfers over 10,000 USDC. You can customize the notification channels by modifying the triggers array.

{
  "name": "Large Transfer of USDC Token",
  "paused": false,
  "networks": ["ethereum_mainnet"],
  "addresses": [
    {
      "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "abi": [
        {
          "anonymous": false,
          "inputs": [
            {
              "indexed": true,
              "internalType": "address",
              "name": "from",
              "type": "address"
            },
            {
              "indexed": true,
              "internalType": "address",
              "name": "to",
              "type": "address"
            },
            {
              "indexed": false,
              "internalType": "uint256",
              "name": "value",
              "type": "uint256"
            }
          ],
          "name": "Transfer",
          "type": "event"
        }
      ]
    }
  ],
  "match_conditions": {
    "functions": [],
    "events": [
      {
        "signature": "Transfer(address,address,uint256)",
        "expression": "value > 10000000000"
      }
    ],
    "transactions": [
      {
        "status": "Success",
        "expression": null
      }
    ]
  },
  "trigger_conditions": [
    {
      "script_path": "./config/filters/evm_filter_block_number.sh",
      "language": "bash",
      "arguments": ["--verbose"],
      "timeout_ms": 1000
    }
  ],
  "triggers": ["evm_large_transfer_usdc_slack", "evm_large_transfer_usdc_email"]
}

Remove the trigger_conditions array to disable additional filtering.

3. Notification Configuration:

For Slack Notifications:
cp config/triggers/slack_notifications.json.example config/triggers/slack_notifications.json

Update the webhook URL in the configuration.

{
    "evm_large_transfer_usdc_slack": {
        "name": "Large Transfer Slack Notification",
        "trigger_type": "slack",
        "config": {
            "slack_url": "https://hooks.slack.com/services/A/B/C",
            "message": {
                "title": "large_transfer_slack triggered",
                "body": "Large transfer of ${event_0_value} USDC from ${event_0_from} to ${event_0_to} | https://etherscan.io/tx/${transaction_hash}#eventlog"
            }
        }
    }
}
For Email Notifications:
cp config/triggers/email_notifications.json.example config/triggers/email_notifications.json

Update the SMTP settings in the configuration.

{
    "evm_large_transfer_usdc_email": {
        "name": "Large Transfer Email Notification",
        "trigger_type": "email",
        "config": {
            "host": "smtp.gmail.com",
            "port": 465,
            "username": "[email protected]",
            "password": "your_password",
            "message": {
                "title": "large_transfer_usdc_email triggered",
                "body": "Large transfer of ${event_0_value} USDC from ${event_0_from} to ${event_0_to} | https://etherscan.io/tx/${transaction_hash}#eventlog"
            },
            "sender": "[email protected]",
            "recipients": [
                "[email protected]",
                "[email protected]"
            ]
        }
    }
}

4. Run the Monitor:

Local Deployment

cargo run

Docker Deployment

cargo make docker-compose-up

The monitor will now:

  1. Check for new Ethereum blocks every minute.

  2. Watch for USDC transfers over 10,000 USDC.

  3. Send notifications via Slack and email when large transfers occur.

5. Next Steps:

  • Adjust the transfer threshold by modifying the expression value.

  • Monitor additional ERC20 tokens by creating new monitor configurations.

  • Explore other examples in the config/monitors directory.

Monitoring Dex Swaps (Stellar):

1. Network Configuration:

Create the Stellar mainnet network configuration:

cp config/networks/stellar_mainnet.json.example config/networks/stellar_mainnet.json

The default configuration should work, but you may want to update the RPC URL to your preferred provider.

{
  "network_type": "Stellar",
  "slug": "stellar_mainnet",
  "name": "Stellar Mainnet",
  "rpc_urls": [
     {
      "type_": "rpc",
      "url": "YOUR_RPC_URL_HERE",
      "weight": 100
    }
  ],
  "network_passphrase": "Public Global Stellar Network ; September 2015",
  "block_time_ms": 5000,
  "confirmation_blocks": 2,
  "cron_schedule": "0 */1 * * * *",
  "max_past_blocks": 20,
  "store_blocks": true
}

2. Monitor Configuration:

Create the large swap monitor configuration:

cp config/monitors/stellar_swap_dex.json.example config/monitors/stellar_swap_dex.json

This configuration monitors large swaps of over 1,000,000,000 tokens. You can customize the notification channels by modifying the triggers array.

{
  "name": "Large Swap By Dex",
  "paused": false,
  "networks": [
    "stellar_mainnet"
  ],
  "addresses": [
    {
      "address": "CA6PUJLBYKZKUEKLZJMKBZLEKP2OTHANDEOWSFF44FTSYLKQPIICCJBE"
    }
  ],
  "match_conditions": {
    "functions": [
      {
        "signature": "swap(Address,U32,U32,U128,U128)",
        "expression": "4 > 1000000000"
      }
    ],
    "events": [],
    "transactions": [
      {
        "status": "Success",
        "expression": null
      }
    ]
  },
  "trigger_conditions": [
    {
      "script_path": "./config/filters/stellar_filter_block_number.sh",
      "language": "bash",
      "arguments": ["--verbose"],
      "timeout_ms": 1000
    }
  ],
  "triggers": [
    "stellar_large_swap_by_dex_slack"
  ]
}

Remove the trigger_conditions array to disable additional filtering.

3. Notification Configuration:

For Slack Notifications:
cp config/triggers/slack_notifications.json.example config/triggers/slack_notifications.json

Update the webhook URL in the configuration.

{
  "stellar_large_swap_by_dex_slack": {
    "name": "Large Swap By Dex Slack Notification",
    "trigger_type": "slack",
    "config": {
      "slack_url": "https://hooks.slack.com/services/A/B/C",
      "message": {
        "title": "large_swap_by_dex_slack triggered",
        "body": "${monitor_name} triggered because of a large swap of ${function_0_4} tokens | https://stellar.expert/explorer/public/tx/${transaction_hash}"
      }
    }
  }
}

4. Run the Monitor:

Local Deployment

cargo run

Docker Deployment

cargo make docker-compose-up

The monitor will now:

  1. Check for new Stellar blocks every minute.

  2. Watch for large dex swaps.

  3. Send notifications via Slack when large swaps occur.

5. Next Steps:

  • Adjust the swap threshold by modifying the expression value.

  • Monitor additional dex swaps by creating new monitor configurations.

  • Explore other examples in the config/monitors directory.