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
andfinalized
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. |
Sentinels seamlessly supports notifications for events emitted by a smart contract on all networks, regardless of whether they are triggered directly or through internal calls from a third contract. However, the capability to track and provide notifications specifically for internal function calls within a contract is currently limited to the Ethereum mainnet. |
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.
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_id → alertId , scanner_count → scanNodeCount , type → findingType , tx_hash → transactionHash , chain_Id → chainId , Bot name removed, agent → bot . 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 Slack webhook documentation 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 Discord webhook documentation 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 Datadog metrics documentation
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 calleddefender.sentinel
.
PagerDuty Configuration
Please see PagerDuty integration documentation to configure an PagerDuty API v2 integration that can create change and alert events.
-
Event Type Event type for pager duty categorization (alert or change)
-
Routing Key Integration Key for an integration on a service or on a global ruleset (32 characters)
-
Event Action The action type of event (trigger, acknowledge or resolve)
-
Dedup Key Deduplication key for correlating triggers and resolves (255 max characters)
-
Severity The perceived severity of the status the event is describing with respect to the affected system (critical, error, warning or info)
-
Component Component of the source machine that is responsible for the event
-
Group Logical grouping of components of a service
-
Class The class/type of the event
-
Custom_detail Map of key-value pairs to provide additional details about the event and affected system
Telegram Configuration
Please see Telegram bot documentation 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.
Opsgenie Configuration
Please see Opsgenie integration documentation to configure an Opsgenie API integration that can create alerts.
-
API Key Integration API key that can be found in the integration settings
-
Instance Location Location where the Opsgenie instance server is located
-
Responders Teams, users, escalations and schedules that the alert will be routed to send notifications. type field is mandatory for each item, where possible values are team, user, escalation and schedule. If the API Key belongs to a team integration, this field will be overwritten with the owner team. Either id or name of each responder should be provided.You can refer below for example values (50 teams, users, escalations or schedules)
-
Visible To Teams and users that the alert will become visible to without sending any notification.type field is mandatory for each item, where possible values are team and user. In addition to the type field, either id or name should be given for teams and either id or username should be given for users. Please note: that alert will be visible to the teams that are specified within responders field by default, so there is no need to re-specify them within visibleTo field. You can refer below for example values (50 teams or users in total)
-
Alias Client-defined identifier of the alert, that is also the key element of Alert De-Duplication (512 max characters)
-
Priority Priority level of the alert. Possible values are P1, P2, P3, P4 and P5. Default value is P3
-
Entity Entity field of the alert that is generally used to specify which domain alert is related to (512 max characters)
-
Actions Custom actions that will be available for the alert (10 x 50 max characters)
-
Note Additional note that will be added while creating the alert (25000 max characters)
-
Details Map of key-value pairs to use as custom properties of the alert (8000 max characters)
-
Tags Tags of the alert (20 x 50 max characters)
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)
}
],
"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
"metadata": {...} // metadata injected by Autotask Condition (if applicable)
}
Forta Sentinel
We have updated the Forta Alert schema in correspondence with the new Forta API. The following changes were made: alert_id → alertId , scanner_count → scanNodeCount , type → findingType , tx_hash → transactionHash , chain_Id → chainId , Bot name removed, agent → bot . 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 subject (plain text only) and 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 message subjects (email and Opsgenie) support plain text only while custom message body content 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
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