Sentinel

The Defender Sentinel service offers 3 types of Sentinels, Contract Sentinels, Forta Sentinels and Forta Local Mode Sentinels. Contract Sentinels allow you to monitor transactions to a contract by defining conditions on events, functions, transaction parameters. Forta Sentinels allow you to monitor Forta Alerts by defining conditions on Forta Bots, contract addresses, alert IDs and severity. If a Sentinel matches a transaction or a Forta Alert based on your defined conditions it will notify you via email, slack, telegram, discord, Autotasks, and more.

Use cases

Use a Sentinel when you need to know about or respond to transactions and Forta Alerts involving your smart contracts, other smart contracts you need to monitor or Forta Bots. Your Sentinel will watch every transaction and Forta Alert and send the ones you care about to your notification methods of choice.

  • Monitor your sensitive functions like transferOwnership, pause, or upgrade

  • Alert on potentially dangerous transactions on your contracts

  • Respond by executing logic when key events happen

  • Integrate with your existing tools through slack, telegram, discord, email or custom Autotask integration

  • Know when an unexpected volume of transactions or alerts occur

When to use a Contract vs a Forta Sentinel

Contract Sentinels are particularly useful for monitoring transactions to a single contract. With the Contract Conditions you can filter transactions by various transaction attributes i.e events, functions, params, gasPrice, value, etc.

Forta Sentinels are useful for monitoring one or more of your smart contracts using a more complex criteria, by hooking into the events and conditions defined by Forta Bot Developers. Forta Bots have greater flexibility for defining transaction conditions than a Contract Sentinel.

What’s in a Contract Sentinel?

A Contract Sentinel watches for transactions related your chosen addresses, filters those transactions by any conditions that you specify, then notifies you when those transactions occur.

At this time, Sentinels are supported across all networks except Fantom. Furthermore, Sentinels can only monitor internal function calls on Mainnet, Ropsten, and Kovan. If the internal call emits an event, consider monitoring for that event instead, as events emitted from internal calls are detected on all supported networks.

Specifying Addresses

  • Addresses: Choose either smart contracts or externally owned accounts to monitor. You may only have 1 ABI per sentinel, if you choose multiple smart contracts they must adhere to the same ABI/Interface.

  • ABI: Specify the ABI for the contract. Defender will automatically load the ABI if the source code is verified.

  • Confirmation Blocks: If you want to be notified only after a certain level of confidence that the transaction is accepted, choose a higher confirmation block level, but, if you want to be notified as soon as possible and are tolerant to re-orgs, then choose lower confirmation block level. In chains where safe and finalized block tags are accepted, you can also select them as confirmation block level.

Matching Rules

For a Transaction to trigger a notification, it must satisfy ALL of the following:

  • Transaction MUST have a To, From, or Address (from log) that matches the configured address

  • If a Transaction Condition is specified

    • The Transaction MUST match the Transaction Condition.

  • If Events are selected

    • The Transaction MUST emit any of the selected Events and match the Event Condition (if any)

  • If Functions are selected

    • The Transaction MUST directly invoke any of the selected Functions (contract calls are not detected at the moment) and match the Function Condition (if any)

Events and Functions

Select any Events and Function calls that you wish to monitor. Selecting Events and Functions acts as an OR clause, in that if a transaction matches ANY of the selected Events or Functions, it will trigger notification.

An ABI is required to configure Events and Function detection
If no Events or Functions are specified, then the Sentinel will monitor ALL transactions to or from your monitored addresses.
At this time, Sentinels can only monitor internal function calls on Mainnet, Ropsten, and Kovan. If the internal call emits an event, consider monitoring for that event instead. Events emitted from internal calls are detected on all networks.

Hedera Support

Hedera mainnet and testnet are supported in Defender Sentinels. There exist some considerations unique to this network when configuring a sentinel:

  • The sentinel monitors a contract’s EVM address (starts with "0x") not the Hedera contract ID. The EVM address can be found on a Hedera Explorer such as HashScan.

  • There is no remote resource to obtain contract ABIs as of now, so they must be generated from the solidity code using a solidity compiler.

  • For ERC20 token transfers, only those invoked via the smart contract can be monitored using Sentinels, not those using a Hedera Token Service (HTS).

  • Only Event conditions can be monitored for Hedera internal transactions (contract calling contract). Other conditions will not trigger Sentinels.

What’s in a Forta Sentinel?

A Forta Sentinel watches Forta Alerts that come from a given Forta Bot or affect a given address, and filters those alerts by any conditions that you specify, then notifies you when those alerts occur.

Forta Local Mode Sentinels

Forta offers the ability to run scanner nodes locally, this can be useful for running only specific detection bots and handling alerts internally instead of publishing to the network. You can monitor scanner nodes running in Local Mode with Defender by creating a new Forta Local Mode Sentinel and specifying the address of your scanner node. After creation your new sentinel will have a Webhook URI, you can add this to your scanner node config file to forward alerts to defender. You can find more information on Local Mode scanner nodes in the Forta Docs.

Specifying Forta Detection Bots and Addresses

Forta Local Mode Sentinels do not have the option to specify Bot IDs as scanner nodes running in local mode don’t support Bot IDs

A Forta Sentinel filters on Bot IDs or Addresses and requires that at least one of these filters are set. It is possible to sepcify multiple Bot IDs and Addresses to filter on.

  • Bot IDs: Specify the Bot IDs to filter on. These can be comma separated to specify multiple.

  • Address: Choose either smart contracts or externally owned accounts to filter on.

Forta Matching Rules

For a Forta Alert to trigger a notification, it must satisfy ALL of the following:

  • Forta Alert MUST come from one of the Bot IDs specified and/or one of the Addresses specified

  • If the Alert ID Condition is specified

    • The Alert ID from the alert MUST match one of the Alert IDs specified

  • If the Severity Condition is specified

    • The Alert Severity MUST match or be of greater severity than the one specified

Severity and Alert IDs

You can specify Alert Severity and Alert IDs to monitor. Specifying both Severity and Alert IDs acts as an OR clause, in that if a alert matches ANY of the selected Alert IDs or matches the selected Severity, it will trigger notification.

If no Severity or Alert IDs are specified, then the Sentinel will monitor ALL alerts matching your specified Bot IDs and/or Adresses.

What are Contract Conditions?

Conditions act as filters that allow you to narrow the transactions even further. These are entered as expressions and offer a great deal of flexibility. Conditions are very much like Javascript expressions. To accomodate comparisons for checksum and non-checksum addresses, comparisons are case-insensitive.

If you want to receive ALL transactions that involve your selected events/functions, then do not specify any conditions.
  • Conditions can use AND, OR, NOT and ()

  • Conditions can use ==, <, >, >=, <= to compare

  • Number values can be referred to by Hex (0xabc123) or Decimal (10000000000)

  • String values can only be compared via ==

  • Includes basic math operators: +, -, *, /, ^

Transaction Conditions

If a transaction condition is specified, then a transaction MUST meet this condition in order to trigger a notification.

Transaction Conditions can refer to the following properties

  • to is the to address for the transaction

  • from is the from address for the transaction

  • gasPrice is the price of gas sent in the transaction. In EIP1559 transactions, it’s equal to or below the maxFeePerGas.

  • maxFeePerGas is the maximum price the transaction was willing to pay for the transaction. Only existent in EIP1559 transactions.

  • maxPriorityFeePerGas is the maximum amount of wei over the BASE_FEE the transaction is willing to pay to the miner for inclusion. Only existent in EIP1559 transactions.

  • gasLimit is the gas limit sent in the transaction

  • gasUsed is the amount of gas used in the transaction

  • value is the value sent in the transaction

  • nonce is the nonce for the specific transaction

  • status is a derived value and can be compared with "success" or "failed"

Example Conditions

Transactions that are reverted

status == "failed"

Transactions excluding those from 0xd5180d374b6d1961ba24d0a4dbf26d696fda4cad

from != "0xd5180d374b6d1961ba24d0a4dbf26d696fda4cad"

Transactions that have BOTH a gasPrice higher than 50 gwei AND a gasUsed higher than 20000

gasPrice > 50000000000 and gasUsed > 20000

Event and Function Conditions

Event and Function conditions further narrow the set of transactions that trigger notification. These can refer to arguments in the signature either by name (if the argument is named) or by index (e.g. $0, $1…​). The variables that are available to you are indicated in the user interface as you specify these functions.

Example Conditions

Transactions that emit a Transfer(…​) event with a value between 1 and 100 ETH (in hex)

// Event Signature: Transfer(address to, address from, uint256 value)
value > 0xde0b6b3a7640000 and value < 0x56bc75e2d63100000

Transactions that emit a ValsEvent(…​) event with an array with a first element equal to 5

// Event Signature: ValsEvent(uint256[3] vals)
vals[0] == 5

Transactions that invoke a greet(…​) function with an unnamed string of "hello"

// Function Signature: greet(address, string)
$1 == "hello"

Autotask Conditions

If an autotask condition is specified, then it will be called with a list of matches found for a given block. This allows the sentinel to use other datasources and custom logic to evaluate whether a transaction is a match.

Only transactions that match other conditions (event, function, transaction) will invoke the autotask condition.
Each invocation can contain up to 25 transactions.

Request Schema

The request body will contain the following structure. You can use the SentinelConditionRequest type from the defender-autotask-utils package if you are coding your Autotasks in Typescript.

{
  "events": [
  {
    "transaction": {                     // eth_getTransactionReceipt response body
      ...                                // see https://eips.ethereum.org/EIPS/eip-1474
    },
    "blockHash": "0xab..123",            // block hash from where this transaction was seen
    "matchReasons": [                    // the reasons why sentinel triggered
      {
        "type": "event",                 // event, function, or transaction
        "address": "0x123..abc",         // address of the event emitting contract
        "signature": "...",              // signature of your event/function
        "condition": "value > 5",        // condition expression (if any)
        "args": ["5"],                   // parameters by index (unnamed are present)
        "params": { "value": "5" }       // parameters by name (unnamed are not present)
      }
    ],
    "matchedAddresses": ["0x000..000"],  // the addresses from this transaction your are monitoring
    "sentinel": {
      "id": "44a7d5...31df5",            // internal ID of your sentinel
      "name": "Sentinel Name",           // name of your sentinel
      "abi": [...],                      // abi of your addresses (or undefined)
      "addresses": ["0x000..000"],       // addresses your sentinel is watching
      "confirmBlocks": 0,                // number of blocks sentinel waits (can be 'safe' or 'finalized' on PoS clients)
      "network": "rinkeby"               // network of your addresses
      "chainId": 4                       // chain Id of the network
    }
  }
  ]
}

Response Schema

The autotask must return a structure containing all matches. Returning an empty object indicates no match occurred. The type for this object is SentinelConditionResponse.

Errors will be treated as a non-match. All executions can be found on the Autotask’s run page.
{
  "matches": [
    {
      "hash": "0xabc...123",   // transaction hash
      "metadata": {
        "foo": true            // any object to be shared with notifications
      }
    },
    {
      "hash": "0xabc...123"    // example with no metadata specified
    }
  ]
}

Example Autotask Condition

exports.handler = async function(payload) {
  const conditionRequest = payload.request.body;
  const matches = [];
  const events = conditionRequest.events;
  for(const evt of events) {

    // add custom logic for matching here

    // metadata can be any JSON-marshalable object (or undefined)
    matches.push({
       hash: evt.hash,
       metadata: {
        "id": "customId",
        "timestamp": new Date().getTime(),
        "numberVal": 5,
        "nested": { "example": { "here": true } }
       }
    });
  }
  return { matches }
}

Testing Conditions

On the right side of the conditions form, there is a "Test Sentinel conditions" tool. This tool searches for transactions that match the Sentinel’s conditions across a range of blocks. Testing also invokes an autotask condition if one is specified

Options

  • Recent Blocks searches a range of blocks prior to the network’s latest block

  • Specific Block will search the specified block

  • Specific Transaction will attempt to match a transaction hash (0xabc…​def)

The search uses the conditions that are in the form at the current moment.

Note: Running a Test will not trigger a notification.

What are Forta Conditions?

Forta Conditions act as filters that allow you to narrow Forta Alerts down even further.

Severity Condition

The Severity Condition allows you to only get notified about alerts which are greater than a certain impact level. You will be notified of any alerts which match or have a greater impact level than your chosen severity value.

Forta Alerts may have 1 of the following 5 severity values which indicate different impact levels:

  • Critical - Exploitable vulnerabilities, massive impact on users/funds

  • High - Exploitable under more specific conditions, significant impact on users/funds

  • Medium - Notable unexpected behaviours, moderate to low impact on users/funds

  • Low - Minor oversights, negligible impact on users/funds

  • Info - Miscellaneous behaviours worth describing

Alert IDs Condition

The Alert IDs Condition allows you to filter alerts and only get notified about a specific class of finding. One or more Alert IDs may be specified.

Example Conditions

FORTA-1, NETHFORTA-1

Autotask Conditions

If an autotask condition is specified, then it will be called with a list of matches. This allows the sentinel to use other datasources and custom logic to evaluate whether a transaction is a match.

Only alerts that match other conditions (Severity, Alert IDs) will invoke the autotask condition.

Request Schema

The request body will contain the following structure.

We have updated the Forta Alert schema in correspondence with the new Forta API. The following changes were made: alert_idalertId, scanner_countscanNodeCount, typefindingType, tx_hashtransactionHash, chain_IdchainId, Bot name removed, agentbot. Old properties are now deprecated but we will continue to send both to remain backwards compatible.
Forta have changed the terminology for 'Agent' to 'Detection Bot'. We will continue to refer to them as 'agents' for now. sentinel.agents will be a list of your Bot IDs
{
  "events": [
    {
      "alert": {                            // Forta Alert
        "addresses": [ "0xab..123" ],       // map of addresses involved in the transaction
        "alertId": "NETHFORTA-1",           // unique string to identify this class of finding
        "name": "High Gas Used",            // human-readable name of finding
        "description": "Gas Used: 999999",  // brief description
        "hash": "0xab..123",                // Forta Alert transaction hash
        "protocol": "ethereum",             // specifies which network the transaction was mined
        "scanNodeCount": 1,
        "severity": "MEDIUM",               // indicates impact level of finding
        "findingType": "SUSPICIOUS",        // indicates type of finding: Exploit, Suspicious, Degraded, Info
        "metadata": { "gas": "999999" },    // metadata for the alert
        "source": {
          "transactionHash": "0xab..123",   // network transaction hash  e.g ethereum transaction hash
          "bot": {
            "id": "0xab..123",              // Bot ID
          },
          "block": {
            "chainId": 1,                   // Chain ID of the originating network
            "hash": "0xab..123",            // network block hash  e.g ethereum block hash
          }
        }
      },
      "matchReasons": [                     // the reasons why sentinel triggered
        {
          "type": "alert-id",               // Alert ID or Severity
          "value": "NETHFORTA-1"            // Condition Value
        }
      ],
      "sentinel": {
        "id": "forta_id",                   // internal ID of your sentinel
        "name": "forta sentinel",           // name of your sentinel
        "addresses": [ "0xab..123" ],       // addresses your sentinel is monitoring
        "agents": [ "0xab..123" ]           // Bot IDs your sentinel is monitoring
        "network": "mainnet"                // network your sentinel is monitoring
        "chainId": 1                        // chain Id of the network
      }
    }
  ]
}

Response Schema

The autotask must return a structure containing all matches. Returning an empty object indicates no match occurred. The type for this object is SentinelConditionResponse.

Errors will be treated as a non-match. All executions can be found on the Autotask’s run page.
{
  "matches": [
    {
      "hash": "0xabc...123",   // Forta Alert hash i.e events[0].alert.hash
      "metadata": {
        "foo": true            // any object to be shared with notifications
      }
    },
    {
      "hash": "0xabc...123"    // example with no metadata specified
    }
  ]
}

Example Autotask Condition

exports.handler = async function(payload) {
  const conditionRequest = payload.request.body;
  const matches = [];
  const events = conditionRequest.events;
  for(const evt of events) {

    // add custom logic for matching here
    // metadata can be any JSON-marshalable object (or undefined)
    matches.push({
       hash: evt.hash,
       metadata: {
        "id": "customId",
        "timestamp": new Date().getTime(),
        "numberVal": 5,
        "nested": { "example": { "here": true } }
       }
    });
  }
  return { matches }
}

Notifications

When triggered, a Sentinel can notify one or more slack webhooks, telegram bots, discord webhooks, email lists, datadog metrics, custom webhooks, or execute an autotask.

Slack Configuration

Please see https://api.slack.com/messaging/webhooks to configure a Slack webhook. Once Slack is configured, enter the webhook URL in Defender.

  • Alias is the name for this slack configuration. For instance, you might name it after the name of the channel.

  • Webhook URL is the URL from your slack management console to use for notification.

Email Configuration

  • Alias is the name for this email list. (e.g., Developers)

  • Emails is the list of emails you wish to notify. These can be comma or semicolon-delimited.

Discord Configuration

Please see https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks to configure a webhook for your Discord channel.

  • Alias is the name for this discord configuration.

  • Webhook URL is the URL from your discord channel to use for notification.

Datadog Configuration

Datadog configurations let Defender forward custom metrics to your Datadog account. For more information about custom metrics, please see https://docs.datadoghq.com/developers/metrics/

The metric we send is a COUNT metric, which represents the number of transactions that triggered the sentinel. We do not send zeros, so a lack of data should be expected if the sentinel does not trigger. With each metric, we send two tags: network (rinkeby, mainnet,…​) & sentinel (name of sentinel)

It can take several minutes for a new custom metric to show up in the Datadog console
  • Alias is the name for this Datadog configuration.

  • Api Key is the API key from your Datadog management.

  • Metric Prefix will precede all metric names. For instance, with a prefix of defender., sentinels will send a metric called defender.sentinel.

Telegram Configuration

Please see https://core.telegram.org/bots#6-botfather to configure a Telegram Bot using the BotFather

The Telegram Bot must be added to your channel and have the rights to post messages.

To find the Chat ID of the channel, execute the following curl (with your bot token value) and extract the id value of the chat. If you do not receive any entries in the response, send a test message to your chat first.

$ curl https://api.telegram.org/bot$BOT_TOKEN/getUpdates
{
  "ok": true,
  "result": [
    {
      "update_id": 98xxxx98,
      "channel_post": {
        "message_id": 26,
        "sender_chat": {
          "id": -100xxxxxx5976,
          "title": "Defender Sentinel Test",
          "type": "channel"
        },
        "chat": {
          "id": -100xxxxxx5976, // <--- This is your chat ID
          "title": "Defender Sentinel Test",
          "type": "channel"
        },
        "date": 1612809138,
        "text": "test"
      }
    }
  ]
}
  • Alias is the name for this Telegram configuration.

  • Chat ID is the ID of the Telegram Chat.

  • Bot Token is the token you receive from the BotFather when creating the Telegram Bot.

Custom webhook Configuration

To configure a custom webhook notification channel, you just need to provide the webhook endpoint URL and an alias for display purposes.

  • Alias is the name for this webhook endpoint.

  • Webhook URL is the URL where Sentinel will send matching events.

To avoid overwhelming the receiving webhook with many concurrent requests under a high number of matches, Sentinel sends a JSON object with an events containing an array with all the matching events found in a block.

{
  events: [...] // See Event Schema for details on the contents of this array
}

The event schema is exactly the same as the one laid out in Event Schema. You can also use the test notification feature to send a test notification to your webhook.

Autotask

If an autotask is selected, then the autotask will receive a body property containing the details for the triggering event, either the transaction details for the triggering transaction or Forta Alert details from the triggerting alert. The autotask can then perform custom logic and reach out to external APIs as needed.

Autotask executions are subject to quotas. After a quota is exhausted, the autotask will no longer execute. If you need to raise your Autotask execution quotas, please let us know at defender@openzeppelin.com with a description of your use case.

Autotask Events

The sentinel will pass information about the transaction to your autotask. If you are writing your Autotasks in typescript you can use the BlockTriggerEvent type for contract sentinels and the FortaTriggerEvent type for Forta sentinels, from the defender-autotask-utils package.

Example Autotask

exports.handler = async function(params) {
  const payload = params.request.body;
  const matchReasons = payload.matchReasons;
  const sentinel = payload.sentinel;

  // if contract sentinel
  const transaction  = payload.transaction;
  const abi = sentinel.abi;

  // if Forta sentinel
  const alert  = payload.alert;



  // custom logic...
}

Event Schema

Contract Sentinel

{
  "transaction": {                     // eth_getTransactionReceipt response body
    ...                                // see https://eips.ethereum.org/EIPS/eip-1474
  },
  "blockHash": "0xab..123",            // block hash from where this transaction was seen
  "matchReasons": [                    // the reasons why sentinel triggered
    {
      "type": "event",                 // event, function, or transaction
      "address": "0x123..abc",         // address of the event emitting contract
      "signature": "...",              // signature of your event/function
      "condition": "value > 5",        // condition expression (if any)
      "args": ["5"],                   // parameters by index (unnamed are present)
      "params": { "value": "5" }       // parameters by name (unnamed are not present)
      "metadata": {...}                // metadata injected by Autotask Condition (if applicable)
    }
  ],
  "matchedAddresses":["0x000..000"]    // the addresses from this transaction your are monitoring
  "sentinel": {
    "id": "44a7d5...31df5",            // internal ID of your sentinel
    "name": "Sentinel Name",           // name of your sentinel
    "abi": [...],                      // abi of your address (or undefined)
    "addresses": ["0x000..000"],       // addresses your sentinel is watching
    "confirmBlocks": 0,                // number of blocks sentinel waits (can be 'safe' or 'finalized' on PoS clients)
    "network": "rinkeby"               // network of your address
    "chainId": 4                       // chain Id of the network
  },
  "value": "0x16345785D8A0000"         // value of the transaction
}

Forta Sentinel

We have updated the Forta Alert schema in correspondence with the new Forta API. The following changes were made: alert_idalertId, scanner_countscanNodeCount, typefindingType, tx_hashtransactionHash, chain_IdchainId, Bot name removed, agentbot. Old properties are now deprecated but we will continue to send both to remain backwards compatible.
Forta have changed the terminology for 'Agent' to 'Detection Bot'. We will continue to refer to them as 'agents' for now. sentinel.agents will be a list of your Bot IDs
{
  "alert": {                            // Forta Alert
    "addresses": [ "0xab..123" ],       // map of addresses involved in the transaction
    "alertId": "NETHFORTA-1",           // unique string to identify this class of finding
    "name": "High Gas Used",            // human-readable name of finding
    "description": "Gas Used: 999999",  // brief description
    "hash": "0xab..123",                // Forta Alert transaction hash
    "protocol": "ethereum",             // specifies which network the transaction was mined
    "scanNodeCount": 1,
    "severity": "MEDIUM",               // indicates impact level of finding
    "findingType": "SUSPICIOUS",        // indicates type of finding: Exploit, Suspicious, Degraded, Info
    "metadata": { "gas": "999999" },    // metadata for the alert
    "source": {
      "transactionHash": "0xab..123",   // network transaction hash  e.g ethereum transaction hash
      "bot": {
        "id": "0xab..123",              // Bot ID
      },
      "block": {
        "chainId": 1,                   // Chain ID of the originating network
        "hash": "0xab..123",            // network block hash  e.g ethereum block hash
      }
    }
  },
  "matchReasons": [                     // the reasons why sentinel triggered
    {
      "type": "alert-id",               // Alert ID or Severity
      "value": "NETHFORTA-1"            // Condition Value
    }
  ],
  "sentinel": {
    "id": "forta_id",                   // internal ID of your sentinel
    "name": "forta sentinel",           // name of your sentinel
    "addresses": [ "0xab..123" ],       // addresses your sentinel is monitoring
    "agents": [ "0xab..123" ]           // Bot IDs your sentinel is monitoring
    "network": "mainnet"                // network your sentinel is monitoring
    "chainId": 1                        // chain Id of the network
  },
  "value": undefined                    // value will always be undefined for FORTA sentinels
}

Customizing Notification Messages

You can optionally modify the message body content and formatting using the checkbox below the notification channel selector.

Example

Template

**Sentinel Name**

{{ sentinel.name }}

**Network**

{{ sentinel.network }}

**Block Hash**

{{ blockHash }}

**Transaction Hash**

{{ transaction.transactionHash }}

**Transaction Link**

[Block Explorer]({{ transaction.link }})

{{ matchReasonsFormatted }}

**value**

{{ value }}

Preview

Sentinel Name

Sentinel

Network

rinkeby

Block Hash

0x22407d00e953e5f8dabea57673b9109dad31acfc15d07126b9dc22c33521af52

Transaction Hash

0x1dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50

Match Reason 1

Type: Function

Matched Address:_ 0x1bb1b73c4f0bda4f67dca266ce6ef42f520fbb98

Signature: greet(name)

Condition: name == 'test'

Params:

name: test

Match Reason 2

Type: Transaction

Condition: gasPrice > 10

Value

0x16345785D8A0000

Message Syntax

Custom notifications support a limited set of markdown syntax:

  • Bold (**this text is bold**)

  • Italic (*this text* and _this text_ are italic)

  • Links (this is a [link](http://example.com))

There is partial support for additional markdown syntax, but rendering behavior varies by platform. Email supports full HTML and has the richest feature set, but other messaging platforms have limitations including support for standard markdown features such as headings, block quotes, and tables. Combinations of the supported features (e.g. both bold and italicized text) also has mixed support. If your markdown contains any syntax with mixed platform support, a warning message will appear directly below the editor.

Dynamic Content

Custom notification templates render dynamic content using inline templating. Any string surrounded by double curly braces will be resolved against the Event Schema. Deeply nested items (including those in arrays) can be accessed using dot notation.

In addition to the standard event schema, the following parameters are injected for usage in custom notification messages:

  • transaction.link

  • matchReasonsFormatted

Character Limit

Messages will be truncated if they exceed a platform’s character limit. The best practice is to limit messages to 1900 characters.

Controlling the Notify Rate

Once you have specified your conditions as desired, there are two ways to limit the number of notifications: Alert and Timeout. These are meant to be used together to achieve a wide range of alerting behaviors.

Alert Threshold

To be alerted when matching transactions exceed a threshold, use an alert threshold.

This threshold is evaluated for each transaction. Once a threshold is exceeded then notifications will continue to fire until the amount falls below the threshold in the time window immediately prior to the current transaction. Consider using a Timeout value to prevent subsequent notifications.
  • Amount is the number of times this sentinel must trigger before firing a notification.

  • Window is the number of seconds that is considered

Example:

At least 5 times within an hour should specify an Amount of 5 and a Window of 3600 seconds.

Timeout

If you do not wish to receive a notification more than a certain rate, consider using a Timeout. This will effectively prevent notifications for a certain duration after a notification is sent.

  • Timeout is the number of seconds to wait between notifications

Example:

Avoid notifying more than once per hour should specify a Timeout of 3600

Pausing

Pausing a Sentinel will pause the monitoring of your addresses.