Перейти к основному содержанию
Это руководство описывает настройку как простых, так и сложных правил оповещений с помощью API Tenderly. Мы рассмотрим каждый тип выражения, а затем объединим их в комплексные решения для мониторинга.

Справочник Alerting API

Введение

Tenderly Alert API позволяет создавать как простые, так и сложные оповещения (Alerts). Простое оповещение состоит из одного правила, например, method_call будет срабатывать, когда транзакция вызывает ваш публичный или внешний метод. Сложное оповещение может содержать несколько условий и сработает только когда все они выполняются. Например, оповещение с method_call и state_change сработает, когда транзакция вызовет указанный метод и изменит указанный слот хранилища. При определении оповещения через API вам необходимо указать следующее:
  • каналы доставки (delivery channels), которые получат уведомление при срабатывании правила. Подробнее о каналах доставки (Delivery Channels).
  • массив выражений (expressions), которые вызовут срабатывание оповещения, если все условия, представленные отдельными выражениями, будут выполнены.
Каналы доставки можно создавать только через Dashboard, но получить их можно через API.

Аутентификация

Прежде чем создавать оповещения, вам нужно настроить аутентификацию и идентифицировать ваш проект:
const TENDERLY_API_KEY = 'your_api_key';
const PROJECT_SLUG = 'your_project_slug';
const ACCOUNT_ID = 'me';  // Use 'me' or your specific account ID

// Base configuration for axios
const baseConfig = {
  baseURL: 'https://api.tenderly.co/api/v1',
  headers: {
    'X-Access-Key': TENDERLY_API_KEY,
    'Content-Type': 'application/json'
  }
};

Типы выражений

Для задания правил срабатывания оповещений можно использовать различные типы выражений.
Тип выраженияМониторингОсновной сценарий использованияОбязательные аргументыНеобязательные аргументы
method_callОпределённые вызовы функций в контрактах (прямые или внутренние транзакции)Отслеживание вызовов важных функций- line_number: строка, в которой определена функция; call_position: позиция вызова (“first”, “last”, “any”)Нет
whitelisted_caller_addressesВызовы от определённых адресовКонтроль доступа по allow-list- addresses: массив Ethereum-адресовНет
blacklisted_caller_addressesВызовы от заблокированных адресовКонтроль доступа по block-list- addresses: массив Ethereum-адресовНет
contract_addressВзаимодействия с конкретным контрактомОтслеживание всех взаимодействий с контрактом- address: адрес контракта- transaction_type: “direct”, “source” или “internal”
networkСобытия в определённых сетяхМультичейн-мониторинг- network_id: ID сети/цепочкиНет
tagКонтракты с определёнными тегамиМониторинг по группам- tag: строка тега- transaction_type: “direct”, “source” или “internal”
tx_statusУспех/неуспех транзакцииОтслеживание неудачных транзакцийНет- transaction_success: boolean
function_paramsЗначения параметров функцийОтслеживание конкретных входных параметров функций- address: адрес контракта; function_line_number: строка определения функции; parameter_conditions: массив условий- Специфичные для параметра опции
tx_valueЗначение транзакцииОтслеживание крупных переводов- transaction_value: сумма в wei; operator: оператор сравненияНет
emitted_logСобытия контрактаОтслеживание конкретных событий- address: адрес контракта; event_name: имя события; event_id: сигнатура события- match_any: boolean; decode_events: boolean; parameter_conditions: массив условий
state_changeИзменения состояния контрактаОтслеживание изменений в хранилище- address: адрес контракта; parameter_conditions: массив условий- Параметры сравнения (пороговое значение, процент)
view_functionРезультаты read-only функцийОтслеживание вычисляемых значений- address: адрес контракта; input: ABI-закодированные данные функции; network_id: ID сети- parameter_condition: сравнение значений
eth_balanceИзменения баланса ETHОтслеживание пороговых значений баланса- address: адрес контракта; threshold: баланс в wei; operator: оператор сравненияНет
erc20_transfer_matcherСогласованность ERC20-переводовПроверка корректности переводов- address: адрес токена; log_name: имя события; balances: имя переменной состоянияНет
tx_errorОшибки транзакцииОтслеживание непредвиденных сбоевНет- addresses_to_ignore: массив адресов
tx_internal_errorВнутренние ошибки транзакцииОтслеживание сбоев внутренних вызововНет- addresses_to_match: массив адресов
no_actionОтсутствие активностиОтслеживание бездействия контракта- check_after_seconds: пороговое время- no_log: условия по событиям; no_transaction: условия по транзакциям
sandwich_transactionСэндвич-атакиОтслеживание MEV-активности- address: адрес контракта- transaction_type: “direct”, “source” или “internal”

Примечания

  • Для операторов сравнения (operator) допустимые значения: >, >=, <, <=, ==, !=, contains, notContains
  • Типы параметров (parameter_type) включают: uint, int, bool, address, string, byte
  • Все адреса должны быть валидными Ethereum-адресами (с префиксом 0x, 40 hex-символов)
  • Значения в wei следует передавать в виде строк для работы с большими числами
  • ID сети должны соответствовать целевому блокчейну (например, “1” для Ethereum mainnet)
Подробнее см. в справочнике Alerting API.

Примеры простых выражений

Рассмотрим примеры настройки простых правил-выражений.

1. Мониторинг вызовов методов

Сценарий: отслеживание вызовов определённых функций в вашем смарт-контракте.
const methodCallAlert = {
  name: "Critical Function Call Alert",
  description: "Monitors calls to critical functions",
  enabled: true,
  expressions: [{
    type: "method_call",
    expression: {
      line_number: 123, // Line where function is defined
      call_position: "any" // "first", "last", or "any"
    }
  },
  {
      "type": "contract_address",
      "expression": {
          "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
      }
  }
  ],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  methodCallAlert,
  baseConfig
);

2. Мониторинг изменений состояния

Сценарий: мониторинг изменений переменных состояния контракта, особенно полезен для отслеживания критичных параметров, таких как состояние паузы или пороговые значения баланса.
const stateChangeAlert = {
  name: "Critical State Change Alert",
  description: "Monitors important state changes",
  enabled: true,
  expressions: [{
    type: "state_change",
    expression: {
      address: "0x1234....",
      parameter_conditions: [
        {
          parameter_name: "pause",
          parameter_type: "bool",
          compare_change: true
        },
        {
          parameter_name: "totalSupply",
          parameter_type: "uint",
          compare_percentage: true,
          comparison_value: "5",
          operator: ">="
        }
      ]
    }
  }],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  stateChangeAlert,
  baseConfig
);

3. Мониторинг событий

Сценарий: мониторинг определённых событий, генерируемых вашими контрактами, с фильтрацией по параметрам.
const eventAlert = {
  name: "Large Transfer Event Alert",
  description: "Monitors large transfer events",
  enabled: true,
  expressions: [{
    type: "emitted_log",
    expression: {
      address: "0x1234....",
      event_name: "Transfer",
      event_id: "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
      parameter_conditions: [
        {
          parameter_name: "amount",
          parameter_type: "uint",
          operator: ">=",
          comparison_value: "1000000000000000000" // 1 ETH
        }
      ],
      decode_events: true
    }
  }],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  eventAlert,
  baseConfig
);

4. Мониторинг баланса нативного ETH

Сценарий: оповещение о снижении баланса нативного ETH некоторого адреса ниже порогового значения, например, для релеера или операционного кошелька, который должен оставаться пополненным. Ограничьте оповещение сетью и адресом, затем сравните нативный баланс с пороговым значением (в wei).
const balanceAlert = {
  name: "Low ETH balance alert",
  description: "Alerts when the native ETH balance falls below 0.1 ETH",
  enabled: true,
  expressions: [
    // Scope to a specific network
    {
      type: "network",
      expression: {
        network_id: "1" // Ethereum mainnet
      }
    },
    // Scope to the watched address
    {
      type: "contract_address",
      expression: {
        address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
      }
    },
    // Trigger when the native balance drops below the threshold
    {
      type: "eth_balance",
      expression: {
        address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
        threshold: "100000000000000000", // 0.1 ETH in wei
        operator: "<"
      }
    }
  ],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  balanceAlert,
  baseConfig
);

Примеры сложных оповещений

Далее приведены примеры сложных правил-выражений. Оповещение сработает, когда каждое выражение в массиве expressions выполнено.

1. Система мониторинга безопасности

Сценарий: комплексный мониторинг безопасности, объединяющий несколько условий:
  • Мониторинг вызовов административных функций
  • Отслеживание крупных переводов
  • Отслеживание адресов из чёрного списка
  • Оповещения об изменениях критичных параметров состояния
const securityAlert = {
  name: "Security Monitoring System",
  description: "Comprehensive security monitoring for contract",
  enabled: true,
  expressions: [
    {
      "type": "contract_address",
      "expression": {
          "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
      }
    },
    // Admin function monitoring
    {
      type: "method_call",
      expression: {
        line_number: 123,
        call_position: "any"
      }
    },
    // Blacklist checking
    {
      type: "blacklisted_caller_addresses",
      expression: {
        addresses: [
          "0xblacklisted1...",
          "0xblacklisted2..."
        ]
      }
    },
    // Large value transfers
    {
      type: "tx_value",
      expression: {
        transaction_value: "100000000000000000000", // 100 ETH
        operator: ">"
      }
    },
    // Critical state changes
    {
      type: "state_change",
      expression: {
        address: "0x1234....",
        parameter_conditions: [
          {
            parameter_name: "pause",
            parameter_type: "bool",
            compare_change: true
          },
          {
            parameter_name: "owner",
            parameter_type: "address",
            compare_change: true
          }
        ]
      }
    }
  ],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  securityAlert,
  baseConfig
);

2. Мониторинг DeFi-протокола

Сценарий: мониторинг DeFi-протокола для:
  • Крупных сделок/свопов
  • Значительного влияния на цену
  • Изменений ликвидности
  • Неудачных транзакций
  • Сэндвич-атак
const defiMonitor = {
  name: "DeFi Protocol Monitor",
  description: "Comprehensive DeFi protocol monitoring system",
  enabled: true,
  expressions: [
    // Monitor large swaps via events
    {
      type: "emitted_log",
      expression: {
        address: "0xpool_address",
        event_name: "Swap",
        event_id: "0x...", // Swap event signature
        parameter_conditions: [
          {
            parameter_name: "amountOut",
            parameter_type: "uint",
            operator: ">=",
            comparison_value: "1000000000000000000000" // 1000 tokens
          }
        ],
        decode_events: true
      }
    },
    // Monitor liquidity changes
    {
      type: "state_change",
      expression: {
        address: "0xpool_address",
        parameter_conditions: [
          {
            parameter_name: "reserve0",
            parameter_type: "uint",
            compare_percentage: true,
            comparison_value: "10",
            operator: ">="
          },
          {
            parameter_name: "reserve1",
            parameter_type: "uint",
            compare_percentage: true,
            comparison_value: "10",
            operator: ">="
          }
        ]
      }
    },
    // Monitor for sandwich attacks
    {
      type: "sandwich_transaction",
      expression: {
        address: "0xpool_address",
        transaction_type: "direct"
      }
    },
    // Monitor failed transactions
    {
      type: "tx_error",
      expression: {
        addresses_to_ignore: [] // Monitor all addresses
      }
    }
  ],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  defiMonitor,
  baseConfig
);

3. Мониторинг ERC20-токена с оповещениями о бездействии

Сценарий: комплексный мониторинг токена, включающий:
  • Мониторинг переводов
  • Проверки баланса
  • Проверки согласованности состояния
  • Мониторинг бездействия
const tokenMonitor = {
  name: "ERC20 Token Monitor",
  description: "Comprehensive ERC20 token monitoring with inactivity alerts",
  enabled: true,
  expressions: [
    // Monitor Transfer event consistency
    {
      type: "erc20_transfer_matcher",
      expression: {
        address: "0xtoken_address",
        log_name: "Transfer",
        balances: "balances"
      }
    },
    // Monitor large transfers
    {
      type: "emitted_log",
      expression: {
        address: "0xtoken_address",
        event_name: "Transfer",
        event_id: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        parameter_conditions: [
          {
            parameter_name: "value",
            parameter_type: "uint",
            operator: ">=",
            comparison_value: "1000000000000000000000" // 1000 tokens
          }
        ]
      }
    },
    // Monitor total supply changes
    {
      type: "state_change",
      expression: {
        address: "0xtoken_address",
        parameter_conditions: [
          {
            parameter_name: "totalSupply",
            parameter_type: "uint",
            compare_percentage: true,
            comparison_value: "1",
            operator: ">="
          }
        ]
      }
    },
    // Monitor for inactivity
    {
      type: "no_action",
      expression: {
        no_log: {
          address: "0xtoken_address",
          event_name: "Transfer",
          event_id: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        },
        check_after_seconds: 86400 // 24 hours
      }
    }
  ],
  delivery_channels: [{
    id: "your_channel_id",
    enabled: true
  }]
};

await axios.post(
  `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
  tokenMonitor,
  baseConfig
);