> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenderly.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Функции, события и триггеры Action

> Исследуйте основные элементы Web3 Actions, настраивайте триггеры для поддерживаемых событий и связывайте триггеры с функциями actions в tenderly.yaml.

В этом руководстве представлены три основных понятия Web3 Actions: **триггеры, события и функции**. Вы узнаете, как они работают и как использовать их для создания собственных Web3 Actions.

Три основных компонента, из которых состоит Web3 Action:

* **Функции:** пользовательский код на JavaScript или TypeScript, который вы хотите выполнить при возникновении внешнего события. Это ядро вашей автоматизации.
* **Триггеры:** предопределённые внешние события, которые ваш Web3 Action настроен отслеживать. Когда событие происходит, триггер указывает Tenderly выполнить ваш пользовательский код (функцию).
* **События (типы триггеров):** предопределённые внешние события, которые вы можете отслеживать, установив триггер. Когда событие происходит, триггер вызовет ваш пользовательский код (функции).

### Типы выполнения

Web3 Actions в Tenderly могут выполняться в двух режимах: **Sequential** (последовательный) и **Parallel** (параллельный).

<Frame caption="Шаг Web3 Action Execution Type в UI-конструкторе Web3 Action">
  <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/web3-actions/project-structure-1.webp?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=a6d7ce9f20d3a653c1937ea05e646801" alt="Web3 Action Execution Type step in the Web3 Action UI Builder" width="3364" height="2262" data-path="images/web3-actions/project-structure-1.webp" />
</Frame>

#### Последовательное выполнение (Sequential)

При последовательном выполнении actions запускаются один за другим в том порядке, в котором они были вызваны. Это режим по умолчанию. В этом режиме каждый action ждёт, пока предыдущий завершит выполнение, прежде чем начать своё. Вот пример конфигурации action для последовательного выполнения:

```diff title="example" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
our-org/our-cool-project:
  runtime: v2
  sources: actions
  specs:
    bestActionEver:
      description: Does the best thing ever
+     execution_type: sequential
      function: very/organized/file:bestActionEver
      trigger:
        ...
```

#### Параллельное выполнение (Parallel)

При параллельном выполнении actions запускаются параллельно, что приводит к более высокой пропускной способности. В этом режиме порядок выполнения не гарантируется и возможны состояния гонки при работе с [action storage](/monitoring/web3-actions/references/context#storage). Вот пример конфигурации action для параллельного выполнения:

```diff title="example" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
our-org/our-cool-project:
  runtime: v2
  sources: actions
  specs:
    bestActionEver:
      description: Does the best thing ever
+     execution_type: parallel
      function: very/organized/file:bestActionEver
      trigger:
        ...
```

### Функции action

Функции Web3 Action — это пользовательский код, написанный как обычные функции JavaScript или TypeScript, но они должны соответствовать некоторым правилам.

* Функции должны быть асинхронными и возвращать `Promise<void>`
* Функции принимают два параметра: `context` и `event`
* Функция должна быть именованным экспортом из файла
* Функции можно размещать в любом файле в каталоге *корня actions* (actions root)

Узнайте о [структуре проекта и файлов Web3 Actions](/monitoring/web3-actions/references/project-structure).

Когда функция Web3 Action развёрнута, runtime Tenderly передаст следующие аргументы при её вызове:

* Параметр `context`, дающий доступ к [Storage и Secrets](/monitoring/web3-actions/references/context).
* Параметр `event` — объект с информацией, отвечающей на вопрос *«что только что произошло?»*. Этот параметр содержит данные, специфичные для типа триггера, на который подписана функция Web3 Action. Раздел [Задание триггеров для внешних событий](/monitoring/web3-actions/references/functions-events-triggers#specifying-triggers-for-external-events) подробно рассматривает внешние события.

<Note>
  Выполнение функций Web3 Action ограничено 30 секундами. Если ваша функция выполняется дольше
  30 секунд, она будет прервана.
</Note>

Вот пример функции Web3 Action, написанной на TypeScript. Параметр `event` может быть любым из поддерживаемых типов триггеров (событий).

```typescript title="example.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
// File: actions/myCoolTsFile.ts

// importing ethers available in Tenderly Runtime

export const awesomeActionFunction: ActionFn = async (context: Context, event: Event) => {
  // cast the event parameter to an appropriate type, based on the Trigger
  // this function subscribed to.
  // Of course, only one of these casts makes sense
  const blockEvent = event as BlockEvent;
  const periodicEvent = event as PeriodicEvent;
  const transactionEvent = event as TransactionEvent;
  const webhookEvent =  event as WebhookEvent;
	...
}
```

#### Доступные библиотеки для actions на базе dashboard

Runtime Tenderly поставляется с несколькими предустановленными JavaScript-библиотеками, которые вы можете импортировать при создании Web3 Actions через Tenderly Dashboard. Доступные библиотеки:

* [Ethers.js](https://docs.ethers.io/v5/)
* [Bignumber.js](https://mikemcl.github.io/bignumber.js/)
* [Axios](https://axios-http.com/docs/intro)
* [Luxon](https://moment.github.io/luxon/#/?id=luxon)

Чтобы импортировать любую из этих библиотек, используйте функцию `require()` так же, как в стандартном npm-проекте (без ES6).

Пример импорта Axios выглядит так:

```jsx title="example.jsx" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
const axios = require('axios');
```

#### Использование npm-библиотек для Web3 Actions на базе CLI

Проект, создаваемый Tenderly CLI, по сути является npm-модулем. Вы можете установить любой npm-пакет в каталоге *корня actions*.

### Внешние события и типы триггеров

Когда происходит внешнее событие, оно *запускает выполнение вашего пользовательского кода* (функций). Вы можете выбрать одно из четырёх внешних событий для отслеживания:

* **Block event**: блок заминирован в выбранной сети.
* **Periodic event:** этот триггер срабатывает при прохождении определённых интервалов времени или на основе CRON-выражений.
* **Webhook event:** HTTP-запрос отправлен на URL webhook (Web3 Action предоставляет webhook)
* **Transaction event:** транзакция, соответствующая заданным критериям фильтра, выполняется в выбранной сети.

При определении Web3 Action вы фактически задаёте триггеры, реагирующие на важные для вашего проекта внешние события. В контексте спецификации триггеров мы будем использовать термин **тип триггера**.

<Info>
  Вы должны писать отдельные функции для каждого типа триггера. Использовать одну функцию для разных
  типов триггеров не рекомендуется.
</Info>

### Подписка функций Web3 Action на события

Помимо определения функции action на JavaScript, вам также нужно предоставить конфигурацию триггера, которая сообщает Tenderly, **что его запускает — внешнее событие, на которое подписана ваша функция.**

При создании Web3 Actions через Tenderly Dashboard процесс создания в UI позаботится об этом за вас. Прочитайте руководство [Быстрый старт через Dashboard](/monitoring/web3-actions/tutorials/deploy-via-dashboard).

При работе с Web3 Actions на основе кода функции и их триггеры должны быть определены в файле `tenderly.yaml`, генерируемом Tenderly CLI. Прочитайте руководство [Быстрый старт через CLI](/monitoring/web3-actions/tutorials/deploy-via-cli).

**Пример**

В примере ниже мы объявляем Web3 Action под именем **bestActionEver** и ссылаемся на функцию **awesomeActionFunction**, экспортированную из файла **actions/myCoolTsFile.ts**. Это функция, которую Tenderly вызовет при срабатывании Web3 Action. Выполнение контролируется через **`execution_type`**, в этом случае оно установлено в `parallel`.

```yaml title="tenderly.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
account_id: ""
actions:
  our-cool-org/our-cool-project:
    runtime: v1
    sources: actions
    specs:
      bestActionEver:
        execution_type: parallel # or sequential
        description: Does the best thing ever
        function: myCoolTsFile:awesomeActionFunction
        trigger:           # trigger declaration start
          type: ...        # type
          ...              # configuration map (external event specific)
```

### Задание триггеров для внешних событий

В этом разделе мы рассмотрим объявление `trigger`. Для получения дополнительной информации о написании файла tenderly.yaml обратитесь к [этому руководству](/monitoring/web3-actions/references/project-structure#the-tenderlyyaml-file-structure).

Тип триггера и соответствующая конфигурация задаются в файле **tenderly.yaml**. Сначала нужно определить объект `trigger`, у которого есть два обязательных свойства:

* Свойство `type`, указывающее тип триггера, который может быть: `periodic | webhook | block | transaction`
* Объект с конфигурацией, специфичной для выбранного типа триггера

Ниже приведено подробное описание конфигурации для каждого типа триггера.

### Periodic event

Periodic event используется, когда вы хотите, чтобы ваш Web3 Action срабатывал через определённые интервалы времени. Оно несёт в себе **time**: время вызова.

```typescript title="example.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
type PeriodicEvent = {
  time: Date;
};
```

Объявление триггера имеет тип `periodic`. Оно может быть основано на интервале или на cron:

```yaml title="trigger.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: periodic
  periodic:
    interval: 5m
```

Свойство `interval` может принимать любое из следующих значений: `5m | 10m | 15m | 30m | 1h | 3h | 6h | 12h | 1d`

Используйте периодический триггер на основе CRON, если вам нужен более гранулярный контроль над тем, когда выполняется ваш Web3 Action:

```yaml title="trigger.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: periodic
  periodic:
    cron: '5 */1 * * *'
```

Свойство `cron` может быть любой валидной [CRON-строкой](https://crontab.guru/).

### Webhook event

Web3 Actions на основе webhook предоставляют пользовательский URL webhook, что позволяет запускать их из внешних систем с помощью простого HTTP POST запроса.

Соответствующий тип триггера содержит два свойства: **time** вызова и любую **payload** (JSON-объект). Tenderly не выполняет никаких проверок или инспекций вашей полезной нагрузки.

```typescript title="example.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
type WebhookEvent = {
  time: Date;
  payload: any;
};
```

Пример конфигурации триггера:

```yaml title="webhook-trigger.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: webhook
  webhook:
    authenticated: true
```

Если `authenticated` установлено в **true**, вы должны включить Tenderly Access Token в свой запрос как значение `x-access-key`, чтобы иметь возможность запустить Web3 Action. cURL для предоставленного webhook можно найти в обзоре Web3 Action в Tenderly Dashboard.

```bash title="example" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
curl -X POST \
-H "x-access-key: $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
https://api.tenderly.co/api/v1/actions/7acc7db2-00d6-4872-b2d2-d9430bd8fe7b/webhook \
-d '{"foo": "bar"}'
```

### Block event

Block event используется, когда вы хотите отслеживать майнинг блоков в одной или нескольких сетях. Вы можете сделать ваш Web3 Action «блочно-периодическим», указав количество заминированных блоков между двумя последовательными вызовами.

```typescript title="example.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
type BlockEvent = {
  blockHash: string;
  blockNumber: number;
  network: string;
};
```

При объявлении блочного триггера вы можете указать следующие свойства:

* `network`: одно значение или список [ID сетей](/monitoring/web3-actions/references/functions-events-triggers), которые вас интересуют
* `blocks`: количество заминированных блоков между двумя последовательными выполнениями Web3 Action. Например, выполнять Web3 Action на каждом 100-м заминированном блоке.

```yaml title="block-trigger.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: block
  block:
    network:
      - 1
      - 8453
    blocks: 100
```

### Transaction event

Тип триггера transaction позволяет отслеживать конкретные транзакции по мере их выполнения в цепочке.

<Note>
  Чтобы отслеживать транзакции со смарт-контракта, смарт-контракт должен быть верифицирован и добавлен в
  ваш проект в Tenderly Dashboard. CLI выдаст предупреждение, если это не так.
</Note>

Вы можете задать разные условия в виде **фильтров**, чтобы точно определить интересующие вас транзакции. Ваш пользовательский код будет вызван с той самой полезной нагрузкой транзакции, переданной через параметр `event`.

```typescript title="example.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
type TransactionEvent = {
  blockHash: string;
  blockNumber: number;
  from: string;
  hash: string;
  network: string;
  to?: string;
  logs: Array<{
    address: string;
    data: string;
    topics: string[];
  }>;
  input: string;
  value: string;
  nonce: string;
  gas: string;
  gasUsed: string;
  cumulativeGasUsed: string;
  gasPrice: string;
  gasTipCap: string;
  gasFeeCap: string;
  transactionHash: string;
};
```

При отслеживании событий транзакций вы также можете указать следующие настройки:

* **Статус майнинга транзакции**: `mined` (транзакция заминирована) или `confirmed10` (подтверждено 10 блоков после блока, содержащего транзакцию)
* **Фильтры:** список условий, включающих полезную нагрузку транзакции, с использованием списка `filters`. Только транзакции, соответствующие фильтрам, запустят выполнение вашего кода.

#### Фильтрация транзакций

Список `filters` позволяет задавать критерии срабатывания с использованием свойств транзакции для сопоставления конкретных транзакций.

Каждый фильтр в списке — это объект, где **все поля объединены логикой AND**. Каждое условие фильтра должно быть истинным, чтобы он совпал. Сам список `filters` **объединён логикой OR**: транзакция совпадает, если удовлетворяет **любому одному фильтру** из списка.

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
match = anyOf(
  (network AND status AND from AND eventEmitted),   # Filter 1
  (network AND to)                                  # Filter 2
)
```

Ниже приведён список всех доступных фильтров, которые можно комбинировать для построения критериев транзакций, запускающих выполнение вашего Web3 Action.

<br />

| Фильтр                                                                 | Описание                                                                                                                           |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| <p>\*обязательный / \*\*должен присутствовать хотя бы один из этих</p> |                                                                                                                                    |
| network\*                                                              | ID сети, из которой отправлена транзакция                                                                                          |
| status                                                                 | Статус транзакции: fail или success                                                                                                |
| from\*\*                                                               | Адрес отправителя транзакции                                                                                                       |
| to\*\*                                                                 | Адрес получателя транзакции                                                                                                        |
| eventEmitted\*\*                                                       | Событие определённого типа, сгенерированное конкретным контрактом                                                                  |
| logEmitted\*\*                                                         | Логи, сгенерированные конкретным контрактом, по совпадению префикса сырой записи лога                                              |
| function\*\*                                                           | Прямой вызов заданной функции. Не применяется к внутренним вызовам между контрактами                                               |
| ethBalance\*\*                                                         | Аккаунт или контракт, чей ETH-баланс удовлетворяет числовому условию в момент транзакции                                           |
| stateChanged\*\*                                                       | Контракт, у которого переменная состояния on-chain изменилась во время транзакции, с опциональными условиями по значению/проценту  |
| value                                                                  | Значение, передаваемое в транзакции, в wei                                                                                         |
| gasUsed                                                                | Количество газа, использованного транзакцией, в wei                                                                                |
| gasLimit                                                               | Лимит газа, установленный для транзакции, в wei                                                                                    |
| fee                                                                    | Комиссия транзакции в wei                                                                                                          |
| contract                                                               | Смарт-контракт, участвующий в транзакции (см. <a href="#filtering-transactions-involving-a-specific-contract">фильтр contract</a>) |

<Warning>
  Триггер должен содержать `network` и хотя бы один из следующих фильтров: `from`, `to`,
  `function`, `eventEmitted`, `logEmitted`, `ethBalance` или `stateChanged`
</Warning>

**Пример** транзакции в Ethereum mainnet или Base, отправленной на `0x236..fd62`.

```yaml title="transaction-trigger.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
failedTransactionToMyContract:
  execution_type: parallel
  description: When sent to my contract fails
  function: observingTransactions:failedAttempts
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        # Transaction must be from Ethereum mainnet
        - network: 1
          # Transaction must have failed
          status: fail
          # Transaction must have been sent to this address
          to: 0x2364259ACD20Bd2A8dEfDc628f4099302449fd62
        # Or from Base
        - network: 8453
          # Transaction must have failed
          status: fail
          # Transaction must have been sent to this address
          to: 0x2364259ACD20Bd2A8dEfDc628f4099302449fd62
```

В этом случае нас интересуют только транзакции, которые заминированы, и соответствующие одному из этих двух фильтров:

* **Фильтр 1**: network 1 (Ethereum) AND status fail AND to `0x2364...fd62`
* **Фильтр 2**: network 8453 (Base) AND status fail AND to `0x2364...fd62`

Поскольку мы не фильтровали по конкретному отправителю, все транзакции, приходящие на указанного получателя, приведут к срабатыванию Web3 Action.

#### Фильтрация транзакций по полям транзакции

Среди общих полей транзакции вы можете фильтровать по следующим свойствам с конкретными значениями.

* `from` — фильтрация по конкретному отправителю. Может быть одиночный адрес или список адресов (OR). Опционально.
* `to` — фильтрация по конкретному получателю. Может быть одиночный адрес или список адресов (OR). Опционально.
* `status` — фильтрация по статусу транзакции: `success` или `fail`. Может быть одиночное значение или список (OR). Опционально.
* `network` — фильтрация по сети. Может быть одиночный chain ID или список chain ID (OR). Обязательно.
* `contract.address` — фильтрация только транзакций, участие в которых принимает контракт с этим конкретным адресом. Опционально.

Все поля адресов должны иметь префикс 0x и содержать 40 hex-символов (например, `0xf63c48626f874bf5604D3Ba9f4A85d5cE58f8019`).

```yaml title="list-fields.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network:                  # list of networks (OR-ed)
      - 1
      - 8453
    status:                   # list of statuses (OR-ed)
      - success
      - fail
    from:                     # list of sender addresses (OR-ed)
      - 0x7ebB3Dca1C281b23D5B73175f10cA5A0a309B01F
      - 0xD3a02149A236b2547Cc3C897Fb41C1a962f881AE
    to:                       # list of recipient addresses (OR-ed)
      - 0x003b3625cDcb5958E9709F4Ba8E340Cb0783DeaE
      - 0x26997bd8473E0Dd0b37eB1711B7c1eE2354d78e4
```

Вы также можете запрашивать числовые значения, связанные с переводимой суммой и газом, используя операторы сравнения. Все следующие поля указываются в **wei**:

* `value`
* `gasUsed`
* `gasLimit`
* `fee`

Числовые поля принимают либо единственный объект сравнения, либо список объектов сравнения. Когда предоставлен список, сравнения объединяются логикой OR. Внутри одного объекта сравнения все операторы объединяются логикой AND.

Вы можете использовать любой из общих операторов сравнения: `eq`, `gte`, `gt`, `lt`, `lte`. Также можно использовать булев флаг `not` для инвертирования сравнения.

<br />

| Оператор | Значение                                                                                                           |
| -------- | ------------------------------------------------------------------------------------------------------------------ |
| `eq`     | Равно                                                                                                              |
| `gt`     | Больше чем                                                                                                         |
| `gte`    | Больше или равно                                                                                                   |
| `lt`     | Меньше чем                                                                                                         |
| `lte`    | Меньше или равно                                                                                                   |
| `not`    | Булев. Установите в `true`, чтобы инвертировать сравнение (например, совпадать, когда значение **не** в диапазоне) |

Ниже приведён пример фильтра, демонстрирующий фильтры с использованием скалярных значений в полезной нагрузке транзакции.

```yaml title="numeric-filters.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    to: 0x003b3625cDcb5958E9709F4Ba8E340Cb0783DeaE
    # Single comparison object (operators AND-ed within)
    value:
      gte: 100
      lte: 1000
    # List of comparison objects (OR-ed between entries)
    gasLimit:
      - lt: 100
      - gt: 1000
    gasUsed:
      eq: 9999
    fee:
      - lte: 100
      - gte: 1000
```

Использование флага `not` для инвертирования сравнения:

```yaml title="negated-comparison.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    to: 0x003b3625cDcb5958E9709F4Ba8E340Cb0783DeaE
    # Matches when value is NOT between 100 and 1000
    value:
      gte: 100
      lte: 1000
      not: true
```

#### Фильтрация транзакций с использованием сгенерированных событий EVM

Настройка Web3 Actions на отслеживание EVM-событий, генерируемых выполнением транзакции, позволяет реагировать на значимые изменения, регистрируемые этими событиями. Этого можно достичь с помощью оператора `eventEmitted`, поддерживающего следующие вложенные свойства:

* `contract` (обязательный): для указания источника события.
  * `contract.address`: адрес контракта, сгенерировавшего событие.
  * `contract.invocation`: контролирует, как контракт был вызван: `direct`, `internal` или `any` (по умолчанию). См. [фильтр contract](#filtering-transactions-involving-a-specific-contract) для деталей.
* `name`: имя события (требует верифицированного контракта).
* `id`: topic-хеш сигнатуры события (альтернатива `name`). Полезно для неверифицированных контрактов, где ABI недоступен. Например, событие `Transfer(address,address,uint256)` имеет topic-хеш `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`.
* `not`: булев. Установите в `true` для инвертирования всего совпадения события, включая параметры (срабатывает, когда событие **не** сгенерировано с указанными параметрами).
* `parameters`: список условий на декодированные значения аргументов события. Все условия объединены AND: каждое условие должно совпадать. Каждая запись поддерживает:
  * `name` (обязательный): имя аргумента события.
  * `string`: сравнение строк. Принимает обычную строку для точного совпадения либо объект с полями `exact` и `not`. См. [StringComparison](#shared-types) для деталей.
  * `int`: целочисленное сравнение. Поддерживает те же операторы, что и числовые фильтры (`eq`, `gt`, `gte`, `lt`, `lte`). Все операторы в одном блоке `int` объединены AND. Используйте флаг `not` для инвертирования комбинированного условия. См. [IntComparison](#shared-types) для деталей.

<Info>
  В пределах одной записи `eventEmitted` в `parameters` нет OR. Все условия объединены AND.
  Для OR-логики на одном параметре используйте несколько записей `eventEmitted` (которые объединены OR во внешнем списке).
</Info>

<Note>
  Чтобы использовать фильтр `eventEmitted` с `name` или `parameters`, контракт должен быть верифицирован и добавлен в проект в
  Tenderly Dashboard. Используйте `id` (topic-хеш) для неверифицированных контрактов.
</Note>

Полное описание полей см. в [EventFilter](#eventfilter-eventemitted).

Ниже приведён пример Web3 Action, который будет вызван при генерации события `TxSubmission` или `TxConfirmation` при выполнении смарт-контракта по адресу `0x418d..9d45` в Sepolia.

```yaml title="event-emitted-filter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
txSubmittedOrConfirmed:
  description: When any of TxSubmission and TxConfirmation is emitted
  execution_type: parallel
  function: myCoolJsFile:myCoolFunction
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        - network: 11155111
          eventEmitted:
            contract:
              address: 0x418ebb95eaa40c119408143056cad984c6129d45
            name: TxSubmission
        - network: 11155111
          eventEmitted:
            contract:
              address: 0x418ebb95eaa40c119408143056cad984c6129d45
            name: TxConfirmation
```

Вот пример фильтрации по декодированным параметрам события. Все условия параметров объединены AND:

```yaml title="event-parameters.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 8453
    eventEmitted:
      contract:
        address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
      name: Transfer
      parameters:
        - name: from
          string: "0x8F362C3dd5301Ce1b43ea3A278E3f12c1807C271"
        - name: value
          int:
            gte: 1000000           # >= 1 USDC (6 decimals)
```

Числовой диапазон с инвертированием параметров:

```yaml title="negated-parameter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    eventEmitted:
      contract:
        address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
      name: Transfer
      parameters:
        - name: value
          int:
            gte: 100
            lte: 1000
            not: true              # matches when value < 100 OR value > 1000
```

Для OR-логики по параметрам используйте несколько записей `eventEmitted`:

```yaml title="event-parameter-or.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    eventEmitted:
      # Entry 1: value < 100
      - contract:
          address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
        name: Transfer
        parameters:
          - name: value
            int:
              lt: 100
      # Entry 2: value > 1000 (OR-ed with entry 1)
      - contract:
          address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
        name: Transfer
        parameters:
          - name: value
            int:
              gt: 1000
```

Использование `not` на самом событии для инвертирования всего совпадения:

```yaml title="negated-event.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    eventEmitted:
      contract:
        address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
      name: Transfer
      parameters:
        - name: from
          string: "0x0000000000000000000000000000000000000000"
      not: true   # matches when no Transfer event from the zero address is found
```

#### Фильтрация транзакций по сгенерированным логам

Ещё один способ отслеживать EVM-события — запрашивать их по topic лога.

Фильтр `logEmitted` может быть одиночным объектом или списком (записи объединены OR). Он поддерживает следующие свойства:

* `startsWith` (обязательный): список значений topic для сопоставления с topic'ами логов транзакции. Каждая запись сравнивается по точному равенству (без учёта регистра) с соответствующим topic. На практике это полные 32-байтные topic-хеши (с префиксом 0x, 64 hex-символа), но поле принимает любую валидную hex-строку.
* `contract.address` (опционально): источник логов. Когда указан, сопоставляются только логи из этого контракта.
* `matchAny`: булев. При `true` достаточно совпадения **любого одного** topic из `startsWith`. При `false` (по умолчанию) должны совпасть все topic.
* `not`: булев. Установите в `true` для инвертирования всего совпадения лога (срабатывает, когда лог **не** сгенерирован).

<Note>
  Использование `logEmitted` позволяет использовать префикс topic события в сыром виде для фильтрации событий.
  Это полезно, если вы настраиваете Web3 Action на неверифицированном контракте.
</Note>

Полное описание полей см. в [LogFilter](#logfilter-logemitted).

Ниже приведён пример Web3 Action, который будет вызван, когда транзакция содержит записи логов, начинающиеся с заданных префиксов.

```yaml title="log-emitted-filter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
txEmittedSomeLogs:
  description: When particular logs are emitted
  function: observingTransactions:someLogsEmittedAction
  execution_type: parallel
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        - network: 11155111
          logEmitted:
            # Transaction must have emitted a log entry
            contract:
              address: 0x418ebb95eaa40c119408143056cad984c6129d45
            startsWith:
              # and topics of the log entry must start with either one of these
              - 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
              - 0x0000000000000000000000000000000000000000000000000000000000000000
```

#### Фильтрация транзакций, включающих конкретный контракт

Для фильтрации транзакций, вызывающих конкретный контракт во время своего выполнения, вы можете использовать необязательный фильтр `contract`.

Фильтр `contract` поддерживает следующие свойства:

* `address`: адрес контракта.
* `invocation`: контролирует, как контракт был вызван. Возможные значения:
  * `direct`: контракт был вызван напрямую отправителем транзакции (EOA). Используйте, когда вас интересуют только вызовы верхнего уровня к контракту.
  * `internal`: контракт был вызван внутренне другим контрактом во время выполнения (например, через опкоды `CALL`, `DELEGATECALL` или `STATICCALL`). Используйте, чтобы обнаружить, когда ваш контракт вызывается как часть многоконтрактного взаимодействия.
  * `any`: совпадает и для прямых, и для внутренних вызовов. Значение по умолчанию.

Поле `invocation` доступно везде, где используется объект `contract`, включая фильтры [`eventEmitted`](#filtering-transactions-using-emitted-evm-events). Например, вы можете использовать `invocation: internal` для контракта в `eventEmitted`, чтобы совпадать только с событиями, генерируемыми во время внутренних вызовов. См. [Contract](#shared-types) для схемы.

<Warning>
  `invocation` не поддерживается в `logEmitted`. Для ограничения сопоставления логов используется только `contract.address`; тип invocation игнорируется.
</Warning>

В примере ниже первый фильтр совпадает с любой успешной транзакцией, отправленной на `0x2364...fd62` в Sepolia. Второй фильтр более ограничивающий: только транзакции, которые также включают внутренний вызов контракта `0xad88...80d6`, запустят Web3 Action.

```yaml title="contract-filter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
contractInvocationAction:
  description: When my contract is called directly or internally
  execution_type: parallel
  function: observingTransactions:contractCalls
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        # Any successful transaction sent to this address
        - network: 11155111
          status: success
          to: 0x2364259ACD20Bd2A8dEfDc628f4099302449fd62
        # Only transactions that internally call this contract
        - network: 11155111
          status: success
          to: 0x2364259ACD20Bd2A8dEfDc628f4099302449fd62
          contract:
            address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
            invocation: internal
```

#### Фильтрация транзакций по вызову функции

Для фильтрации транзакций, напрямую вызывающих конкретную функцию, можно использовать необязательный фильтр `function`. Он требует адрес контракта `contract.address` и либо `name`, либо `signature` функции.

Фильтр `function` поддерживает следующие свойства:

* `contract` (обязательный): для указания целевого контракта.
  * `contract.address`: адрес вызываемого контракта.
  * `contract.invocation`: контролирует, как функция должна быть вызвана: `any` (по умолчанию, и прямые, и внутренние), `direct` (только инициированные EOA) или `internal` (только вложенные вызовы). См. [фильтр contract](#filtering-transactions-involving-a-specific-contract) для деталей.
* `name`: имя функции (требует верифицированного контракта).
* `signature`: 4-байтовый селектор функции (например, `0xa9059cbb`). Полезно для неверифицированных контрактов, где ABI недоступен.
* `not`: булев. Установите в `true` для инвертирования всего совпадения функции, включая параметры (срабатывает, когда функция **не** вызвана с указанными параметрами).
* `parameters`: список условий на декодированные значения входных аргументов функции. Все условия объединены AND: каждое условие должно совпадать. Каждая запись поддерживает:
  * `name` (обязательный): имя аргумента функции.
  * `string`: сравнение строк. Принимает обычную строку для точного совпадения либо объект с полями `exact` и `not`. См. [StringComparison](#shared-types) для деталей.
  * `int`: целочисленное сравнение. Поддерживает те же операторы, что и числовые фильтры (`eq`, `gt`, `gte`, `lt`, `lte`). Все операторы в одном блоке `int` объединены AND. Используйте флаг `not` для инвертирования комбинированного условия. См. [IntComparison](#shared-types) для деталей.

<Info>
  В пределах одной записи `function` в `parameters` нет OR. Все условия объединены AND.
  Для OR-логики по одному и тому же параметру используйте несколько записей `function` (которые объединены OR во внешнем списке).
</Info>

<Note>
  Чтобы использовать фильтр `function` с `name` или `parameters`, контракт должен быть верифицирован и добавлен в проект в
  Tenderly Dashboard. Используйте `signature` (4-байтовый селектор) для неверифицированных контрактов.
</Note>

Вы можете указать `function` как одиночный объект или как список. Когда предоставлен список, записи объединяются OR. Фильтр совпадает, если вызвана **любая** функция из списка. Полное описание полей см. в [FunctionFilter](#functionfilter).

Ниже приведён пример триггера Web3 Action, реагирующего на любой вызов (прямой или внутренний) функции `verySpecialFunction` контракта, развёрнутого по адресу `0xad88...80d6`.

```yaml title="function-filter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
failedTransactionToMyContract:
  description: When sent to my contract fails
  execution_type: parallel
  function: observingTransactions:failedAttempts
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        # Transaction must be from Ethereum mainnet
        - network: 1
          # Transaction must have failed
          status: fail
          function:
            # the function verySpecialFunction must have been called (direct or internal)
            name: verySpecialFunction
            contract:
              address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
```

Также можно сопоставлять по селектору функции и использовать несколько записей function:

```yaml title="function-selector.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      # Match by 4-byte selector (useful for unverified contracts)
      - signature: "0xa9059cbb"
        contract:
          address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
      # Match by name (requires verified contract)
      - name: approve
        not: true  # negate: trigger when approve is NOT called
        contract:
          address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
```

Вот пример фильтрации по декодированным входным параметрам функции. Все условия параметров объединены AND:

```yaml title="function-parameters.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      name: transfer
      contract:
        address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
      parameters:
        - name: to
          string: "0x8F362C3dd5301Ce1b43ea3A278E3f12c1807C271"
        - name: amount
          int:
            gte: 1000000           # >= 1 USDC (6 decimals)
```

Инвертирование строки — срабатывает, когда получатель **не** является конкретным адресом:

```yaml title="function-negated-string.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      name: transfer
      contract:
        address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
      parameters:
        - name: to
          string:
            exact: "0xa59a97Ab934aE02A1E0561ea0f4F6C275Fc148B4"
            not: true              # matches when 'to' is NOT this address
```

Числовой диапазон с инвертированием на параметрах:

```yaml title="function-negated-parameter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      name: transfer
      contract:
        address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
      parameters:
        - name: amount
          int:
            gte: 100
            lte: 1000
            not: true              # matches when amount < 100 OR amount > 1000
```

Для OR-логики по параметрам используйте несколько записей `function`:

```yaml title="function-parameter-or.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      # Entry 1: amount < 100
      - name: transfer
        contract:
          address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
        parameters:
          - name: amount
            int:
              lt: 100
      # Entry 2: amount > 1000 (OR-ed with entry 1)
      - name: transfer
        contract:
          address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
        parameters:
          - name: amount
            int:
              gt: 1000
```

Чтобы совпадать только с внутренними вызовами, например, с `transfer`, вызванным маршрутизатором или провайдером flash-loan, а не напрямую пользователем, установите `invocation: internal`. Этот пример срабатывает только когда другой контракт внутренне вызывает `transfer` для USDC на сумму не менее 1000 USDC:

```yaml title="function-internal-with-params.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      name: transfer
      contract:
        address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
        invocation: internal       # sub-calls only — excludes direct EOA calls
      parameters:
        - name: amount
          int:
            gte: 1000000000        # >= 1,000 USDC (6 decimals)
```

#### Фильтрация транзакций по балансу ETH

Фильтр `ethBalance` запускает ваш Web3 Action, когда ETH-баланс аккаунта или контракта удовлетворяет числовому условию во время транзакции. Это полезно для отслеживания крупных перемещений «китов», пороговых значений казны протокола или событий пополнения кошелька.

Фильтр поддерживает следующие свойства:

* `address` (обязательный): адрес аккаунта или контракта для отслеживания.
* `balanceCmp` (обязательный): числовое сравнение с балансом на момент транзакции. Использует операторы [`BigIntComparison`](#shared-types) (`eq`, `gt`, `gte`, `lt`, `lte`). Значения в **wei** и могут быть предоставлены как десятичные строки (например, `"1000000000000000000"`) или как hex с префиксом `0x` (например, `"0xde0b6b3a7640000"`).
* `not` (опционально): установите в `true` для инвертирования всего совпадения.

Можно предоставить одиночный объект `ethBalance` или список — записи объединены OR.

Полное описание полей см. в [`EthBalanceFilter`](#ethbalancefilter-ethbalance).

**Пример**: срабатывает, когда баланс кошелька достигает не менее 1 ETH:

```yaml title="eth-balance-filter.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
balanceWatcher:
  description: Alert when wallet reaches 1 ETH
  function: watchers:onBalanceReached
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        - network: 1
          ethBalance:
            address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"   # vitalik.eth
            balanceCmp:
              gte: "1000000000000000000"   # 1 ETH in wei
```

**Пример**: несколько аккаунтов отслеживаются в одном фильтре (OR):

```yaml title="eth-balance-multi.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    ethBalance:
      - address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"   # vitalik.eth
        balanceCmp:
          gte: "1000000000000000000"
      - address: "0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8"   # Binance cold wallet
        balanceCmp:
          lte: "500000000000000000"   # below 0.5 ETH
```

**Пример**: баланс в диапазоне:

```yaml title="eth-balance-range.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    ethBalance:
      address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"   # vitalik.eth
      balanceCmp:
        gte: "1000000000000000000"   # >= 1 ETH
        lte: "2000000000000000000"   # <= 2 ETH
```

**Пример**: срабатывает, когда баланс кошелька **не** ниже 1 ETH (то есть инвертирование условия):

```yaml title="eth-balance-not.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    ethBalance:
      address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"   # vitalik.eth
      balanceCmp:
        lt: "1000000000000000000"   # < 1 ETH
      not: true                     # negate: trigger when balance is NOT below 1 ETH
```

#### Фильтрация транзакций по изменениям состояния контракта

Фильтр `stateChanged` запускает ваш Web3 Action, когда переменная состояния контракта меняется во время транзакции. Вы можете сопоставлять по любой комбинации: изменилась ли переменная вообще, конкретное новое значение, процентное изменение или сырой ключ слота хранилища.

Фильтр поддерживает следующие свойства:

* `address` (обязательный, если не `matchAny: true`): адрес контракта для отслеживания.
* `matchAny` (опционально): при `true` совпадает с изменениями состояния **любого** контракта в транзакции, `address` можно опустить. Полезно для мониторинга на уровне протокола.
* `params` (опционально): список условий на переменные состояния. Все записи объединены AND. Когда опущен, фильтр совпадает с любым изменением состояния указанного адреса.
* `not` (опционально): установите в `true` для инвертирования всего совпадения.

Каждая запись в `params` требует:

* `name` (обязательный): имя переменной состояния.
* Хотя бы одно условие:
  * `change: true`: совпадает, когда значение переменной изменилось.
  * `valueCmp` ([`BigIntComparison`](#shared-types)) — совпадает, когда новое значение удовлетворяет числовому условию.
  * `percentageCmp` ([`BigIntComparison`](#shared-types)) — совпадает по **знаковому** процентному изменению, вычисленному как `(newValue - oldValue) * 100 / oldValue`. Положительные значения означают увеличение, отрицательные — уменьшение. Например, `gte: "10"` срабатывает при увеличении на 10%+; `lte: "-10"` срабатывает при уменьшении на 10%+. Примечание: когда `oldValue` равно 0, процент всегда 0, используйте `change: true` или `valueCmp`.
  * `storageSlotKey`: совпадает по сырому ключу слота хранилища (полезно для неверифицированных контрактов).

Полное описание полей см. в [`StateChangedFilter`](#statechangedfilter-statechanged).

<Note>
  Чтобы использовать сопоставление переменных состояния по `name`, контракт должен быть верифицирован и добавлен в ваш проект
  в Tenderly Dashboard.
</Note>

**Пример**: срабатывает при любом изменении `totalSupply`:

```yaml title="state-changed-basic.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
stateWatcher:
  description: Alert on any totalSupply change
  function: watchers:onStateChange
  trigger:
    type: transaction
    transaction:
      status:
        - mined
      filters:
        - network: 1
          stateChanged:
            address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
            params:
              - name: totalSupply
                change: true
```

**Пример**: срабатывает, когда `totalSupply` достигает порогового значения:

```yaml title="state-changed-value.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    stateChanged:
      address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
      params:
        - name: totalSupply
          valueCmp:
            gte: "1000000000000000000000"   # >= 1000 DAI (18 decimals)
```

**Пример**: срабатывает, когда `totalSupply` увеличивается на 50% или более:

```yaml title="state-changed-percentage-increase.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    stateChanged:
      address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
      params:
        - name: totalSupply
          percentageCmp:
            gte: "50"   # positive = increase; fires when totalSupply grew by >= 50%
```

**Пример**: срабатывает, когда `totalSupply` уменьшается на 10% или более:

```yaml title="state-changed-percentage-decrease.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    stateChanged:
      address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
      params:
        - name: totalSupply
          percentageCmp:
            lte: "-10"   # negative = decrease; fires when totalSupply dropped by >= 10%
```

**Пример**: несколько условий параметров, объединённых AND (`totalSupply` изменилось И новое значение выше порога):

```yaml title="state-changed-multi-params.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    stateChanged:
      address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
      params:
        - name: totalSupply
          change: true
        - name: totalSupply
          valueCmp:
            gte: "1000000000000000000000000"   # new totalSupply still >= 1 million DAI
```

**Пример**: отслеживание конкретного слота отображения (mapping), например `balances[bob]`, с использованием сырого ключа слота хранилища:

Для отображений нет именованной переменной на запись — используйте `storageSlotKey` со слотом, полученным через keccak256, для интересующего ключа. Слот для `mapping(address => uint256) balances` в слоте хранилища `N` и ключе `addr` — `keccak256(abi.encode(addr, N))`.

```yaml title="state-changed-slot.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    stateChanged:
      address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"   # DAI on mainnet
      params:
        # slot = keccak256(abi.encode(bob_address, mapping_slot_index))
        # compute this off-chain with ethers.js: ethers.solidityPackedKeccak256(["address", "uint256"], [bobAddress, slotIndex])
        - storageSlotKey: "0x<precomputed-slot-hash>"
          change: true
```

Подход с `storageSlotKey` работает для неверифицированных контрактов и любой схемы хранилища — он не требует, чтобы контракт был верифицирован или добавлен в ваш проект Tenderly.

**Пример**: `matchAny` для отслеживания любого контракта в транзакции:

```yaml title="state-changed-match-any.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 1
    function:
      name: liquidate
      contract:
        address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
    stateChanged:
      matchAny: true
      params:
        - name: collateralBalance
          change: true
```

`stateChanged` и `ethBalance` могут комбинироваться с любым другим фильтром в одном и том же объекте фильтра — все поля объединены AND. Приведённые ниже примеры показывают распространённые реальные комбинации.

**Пример**: `mint()` был вызван И `totalSupply` изменилось (подтверждение того, что вызов имел эффект в блокчейне):

```yaml title="state-changed-with-function.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 8453
    function:
      name: mint
      contract:
        address: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
    stateChanged:
      address: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
      params:
        - name: totalSupply
          change: true
```

**Пример**: сгенерировано событие `Transfer` И изменилось состояние `paused` (переключён флаг владения или паузы во время перевода):

```yaml title="state-changed-with-event.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 8453
    eventEmitted:
      contract:
        address: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
      name: Transfer
    stateChanged:
      address: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
      params:
        - name: paused
          change: true
```

**Пример**: любой вызов контракта И ETH-баланс вызывающего выше порогового значения:

```yaml title="eth-balance-with-to.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 8453
    to: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
    ethBalance:
      address: "0x4786f86f7d9d1467928b3518f123ea4fb65f1500"
      balanceCmp:
        gte: "500000000000000"   # caller has >= 0.0005 ETH
```

**Пример**: срабатывает, когда `togglePause()` был вызван, но `balances` **не** изменились (то есть транзакция затронула только флаг паузы):

```yaml title="state-changed-not.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
filters:
  - network: 8453
    to: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
    stateChanged:
      address: "0x0232b6c44752020C645b65CAA68c139ab456Ec37"
      params:
        - name: balances
          change: true
      not: true   # negate: trigger when balances did NOT change
```

#### Полная справка по триггеру transaction

Следующий аннотированный YAML-блок показывает в одном месте каждое доступное поле для триггеров transaction. Используйте его как быструю справку при построении вашей конфигурации триггера. Определения типов см. в разделе [Справочник схемы YAML-триггеров](#trigger-yaml-schema-reference) ниже.

```yaml title="complete-reference.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: transaction
  transaction:
    status:
      - mined              # or confirmed10

    # At least one filter must match (OR logic).
    # Within a filter, all fields are AND-ed.
    filters:
      - network: 1                                          # mandatory (single or list)
        status: success                                     # fail | success (single or list)
        from: "0xDB6Fd484cFA46eeB73c71165C6C004B50309BbE1" # single or list of addresses
        to: "0x2364259ACD20Bd2A8dEfDc628f4099302449fd62"   # single or list of addresses

        # --- Contract filter ---
        contract:
          address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
          invocation: any    # any | direct | internal

        # --- Numeric comparisons (all in wei) ---
        # Each can be a single object or a list (OR-ed between entries).
        # Within a single object, all operators are AND-ed.
        value:
          gte: 1000000000000000000   # >= 1 ETH
          not: false                 # set true to negate
        gasUsed:
          eq: 21000
        gasLimit:                    # list form (OR-ed)
          - lt: 100
          - gt: 1000
        fee:
          - lte: 100
          - gte: 1000

        # --- Event filter (single object or list, OR-ed) ---
        eventEmitted:
          - contract:
              address: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
            name: Transfer           # match by event name (verified contract)
            # id: "0xddf252..."      # alternative: match by topic hash
            not: false               # negate entire event match
            parameters:              # filter by decoded event arguments (AND-ed)
              - name: from
                string: "0x8F362C3dd5301Ce1b43ea3A278E3f12c1807C271"
              - name: value
                int:
                  gte: 1000000       # >= 1 USDC (6 decimals)

        # --- Log filter (single object or list, OR-ed) ---
        logEmitted:
          - startsWith:
              - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
            contract:
              address: 0x418ebb95eaa40c119408143056cad984c6129d45
            matchAny: false          # true = match any single topic
            not: false               # negate entire log match

        # --- Function filter (single object or list, OR-ed) ---
        function:
          - name: transfer           # match by name (verified contract)
            contract:
              address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6
              invocation: any        # any (default) | direct | internal
            not: false               # negate entire function + parameters match
            parameters:              # filter by decoded function arguments (AND-ed)
              - name: to
                string: "0x8F362C3dd5301Ce1b43ea3A278E3f12c1807C271"  # short form
              - name: from
                string:              # long form (with negation)
                  exact: "0xa59a97Ab934aE02A1E0561ea0f4F6C275Fc148B4"
                  not: true          # negate this string match
              - name: amount
                int:
                  gte: 1000000       # >= 1 USDC (6 decimals)
          # name and signature are mutually exclusive — each entry uses one or the other, not both
          - signature: "0xa9059cbb"  # match by 4-byte selector (0x + 8 hex chars)
            not: true                # negate this function match
            contract:
              address: 0xad881d3d06c7f168715b84b54f9d3e1ff27b80d6

        # --- ETH balance filter (single object or list, OR-ed) ---
        ethBalance:
          address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"  # vitalik.eth
          balanceCmp:
            gte: "1000000000000000000"  # >= 1 ETH in wei (decimal or 0x-prefixed hex)
          not: false                    # negate the balance match

        # --- State changed filter (single object or list, OR-ed) ---
        stateChanged:
          address: "0x6B175474E89094C44Da98b954EedeAC495271d0F"  # DAI on mainnet
          matchAny: false               # true = match any contract in the transaction
          not: false                    # negate the entire state change match
          params:                       # all entries AND-ed
            - name: totalSupply         # state variable name (verified contract)
              change: true              # matches when the value changed at all
            - name: totalSupply
              valueCmp:                 # BigIntComparison on the new value
                gte: "1000"
            - name: totalSupply
              percentageCmp:            # signed: (newVal-oldVal)*100/oldVal
                gte: "50"               # >= 50 means increased by >= 50%
                                        # use lte: "-50" to match a decrease of >= 50%
```

### Справочник схемы YAML-триггеров

Приведённая ниже схема описывает структуру и типы каждого поля, принимаемого конфигурацией триггера. Используйте её вместе с [аннотированным примером](#complete-transaction-trigger-reference) выше при построении вашего `tenderly.yaml`.

Нотация: `?` = опционально, `|` = одно из, `[]` = список. Поля, помеченные как «одиночный или список», принимают либо скалярное значение, либо YAML-список.

#### Все типы триггеров

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: periodic | webhook | block | transaction

  periodic:               # when type = periodic
    interval: string?     # "5m" | "10m" | "15m" | "30m" | "1h" | "3h" | "6h" | "12h" | "1d"
    cron: string?         # standard cron expression (mutually exclusive with interval)

  webhook:                # when type = webhook
    authenticated: bool?  # default: true

  block:                  # when type = block
    network: Network      # single chain ID or list of chain IDs
    blocks: int           # run every N blocks (must be > 0)

  transaction:            # when type = transaction
    status: TransactionStatus[]    # "mined" | "confirmed10"
    filters: TransactionFilter[]   # at least one filter required
```

#### TransactionFilter

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# All fields within a filter are AND-ed.
# Multiple filters in the list are OR-ed.

TransactionFilter:
  network: Network                # required. single chain ID or list (OR-ed)
  status: Status                  # optional. single or list: "success" | "fail" (OR-ed)
  from: Address                   # optional. single or list of addresses (OR-ed)
  to: Address                     # optional. single or list of addresses (OR-ed)
  value: IntComparison            # optional. single object or list (OR-ed)
  gasUsed: IntComparison          # optional. single object or list (OR-ed)
  gasLimit: IntComparison         # optional. single object or list (OR-ed)
  fee: IntComparison              # optional. single object or list (OR-ed)
  contract: Contract              # optional. shared default — applied to function/eventEmitted that omit their own contract
  function: FunctionFilter        # optional. single object or list (OR-ed)
  eventEmitted: EventFilter       # optional. single object or list (OR-ed)
  logEmitted: LogFilter           # optional. single object or list (OR-ed)
  ethBalance: EthBalanceFilter    # optional. single object or list (OR-ed)
  stateChanged: StateChangedFilter  # optional. single object or list (OR-ed)
  # constraint: at least one of from, to, function, eventEmitted, logEmitted, ethBalance, or stateChanged is required
```

<Warning>
  В каждом фильтре должен присутствовать хотя бы один из: `from`, `to`, `function`, `eventEmitted`, `logEmitted`, `ethBalance` или `stateChanged`.
</Warning>

<Note>
  Поле `contract` верхнего уровня действует как общее значение по умолчанию для фильтра. Оно автоматически применяется к любой записи `function` или `eventEmitted`, которая не указывает свой собственный контракт, что позволяет не повторять один и тот же адрес. Оно **не** применяется к `logEmitted`.
</Note>

#### Общие типы

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
Address: string                   # 0x-prefixed, 40 hex characters (case-insensitive)

Network: int | int[]              # chain ID(s)

Status: string | string[]        # "success" | "fail"

Contract:
  address: Address                # required
  invocation: string?             # "any" (default) | "direct" | "internal"

IntComparison:                    # single object or list of objects (OR-ed)
  eq: int?                        # equal to
  gt: int?                        # greater than
  gte: int?                       # greater than or equal
  lt: int?                        # less than
  lte: int?                       # less than or equal
  not: bool?                      # negate the combined condition

BigIntComparison:                 # used by ethBalance and stateChanged filters
  # values are decimal strings ("1000000000000000000") or 0x-prefixed hex ("0xde0b6b3a7640000")
  # for percentageCmp: signed value, (newVal-oldVal)*100/oldVal — positive=increase, negative=decrease
  eq: string?                     # equal to
  gt: string?                     # greater than
  gte: string?                    # greater than or equal
  lt: string?                     # less than
  lte: string?                    # less than or equal
  not: bool?                      # negate the combined condition
  # at least one of eq, gt, gte, lt, lte must be set

StringComparison:                 # accepts a plain string OR an object
  # Short form:  string: "0xdead..."        → exact match, not = false
  # Long form:   string: { exact: "0xdead...", not: true }
  exact: string?                  # exact match (case-insensitive)
  not: bool?                      # negate the match
```

#### FunctionFilter

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
FunctionFilter:                   # single object or list (OR-ed)
  contract: Contract              # required
  name: string?                   # function name (requires verified contract)
  signature: string?              # 4-byte selector, 0x-prefixed, 8 hex chars
  not: bool?                      # negate entire function + parameters match
  parameters: ParameterCondition[]?
  # note: name and signature are mutually exclusive (use one or the other)
  # note: parameters requires a verified contract (name must be set, not signature)

ParameterCondition:               # all conditions in the list are AND-ed
  name: string                    # required. function argument name
  string: StringComparison?       # string comparison (plain string or { exact, not })
  int: IntComparison?             # numeric comparison
```

#### EventFilter (eventEmitted)

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
EventFilter:                      # single object or list (OR-ed)
  contract: Contract              # required
  name: string?                   # event name (requires verified contract)
  id: string?                     # topic hash, 0x-prefixed, 64 hex chars
  not: bool?                      # negate entire event + parameters match
  parameters: ParameterCondition[]?
  # note: name and id are mutually exclusive (use one or the other)
  # note: see ParameterCondition definition under FunctionFilter above
```

#### LogFilter (logEmitted)

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
LogFilter:                        # single object or list (OR-ed)
  startsWith: string[]            # required. hex strings (typically 0x + 64 hex chars for full topic hashes)
  contract: Contract?             # optional. restrict to logs from this contract address
  # note: invocation is not supported for logEmitted; only contract.address is used
  matchAny: bool?                 # true = match any topic; false (default) = match all
  not: bool?                      # negate entire log match
```

#### EthBalanceFilter (ethBalance)

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
EthBalanceFilter:                 # single object or list (OR-ed)
  address: Address                # required. account or contract address to monitor
  balanceCmp: BigIntComparison    # required. condition on the ETH balance in wei
  not: bool?                      # negate the balance match
```

#### StateChangedFilter (stateChanged)

```yaml title="schema.yaml" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
StateChangedFilter:               # single object or list (OR-ed)
  address: Address?               # required unless matchAny = true
  matchAny: bool?                 # true = match state changes on any contract in the transaction
  params: StateChangedParamCondition[]?  # optional. when omitted, matches any state change on address
  not: bool?                      # negate the entire state change match

StateChangedParamCondition:       # all entries in the params list are AND-ed
  name: string                    # required. state variable name (verified contract)
  # at least one of the following must be set:
  change: bool?                   # true = matches when the variable changed at all
  valueCmp: BigIntComparison?     # condition on the new value
  percentageCmp: BigIntComparison?  # signed: (newVal-oldVal)*100/oldVal
                                  #   gte: "10"  → increased by >= 10%
                                  #   lte: "-10" → decreased by >= 10%
                                  #   returns 0 when oldVal is 0; use valueCmp or change: true instead
  storageSlotKey: string?         # raw storage slot key (useful for unverified contracts)
```
