Logical Operators
Learning Objective
Master logical combinations and understand operator precedence and grouping
AND Operator (&&)
watchRule:
{
"expressions": [
"system.invoked(tx1.itx1.WETH.F.*) && system.emitted(tx1.itx1.WETH.E.*)"
]
}
Both conditions must be true - function invoked AND event emitted
OR Operator (||)
watchRule:
{
"expressions": [
"system.uintCompare(tx1.USDC.F.transfer.amount, >, 1000000000000000000000000) || system.uintCompare(tx1.USDC.riskscore, >, 75)"
]
}
Triggers on either large USDC transfers OR high-risk addresses - demonstrates logical OR for multiple alert conditions
Multiple AND Conditions (Comma-Separated)
watchRule:
{
"expressions": [
"system.reverted(tx1.AavePool.F.deposit)",
"system.reentrant(tx1.AavePool.F.deposit)"
]
}
Aave deposit must be both reverted AND reentrant - comma-separated expressions are equivalent to using && operator
Multiple AND Conditions with Literal Placeholders
watchRule:
{
"expressions": [
"system.uintCompare(tx1.USDC.F.transfer.amount, >, ${minAmount}) && system.addressCompare(tx1.USDC.F.transfer.to, !=, ${blacklistedAddress})"
]
}
options:
{
"literalDefs": {
"minAmount": 5e+23,
"blacklistedAddress": "0xBA12222222228d8Ba445958a75a0704d566BF2C8"
}
}
All conditions must be true - amount above threshold AND recipient not blacklisted
Complex OR with Nested AND
watchRule:
{
"expressions": [
"system.invoked(tx1.CompoundCToken.F.mint) && system.noMatches(system.invoked(tx2.CompoundCToken.F.redeem)) || system.uintCompare(tx1.CompoundCToken.F.mint.mintAmount, >, 50000000000000)"
]
}
Either (mint in tx1 without redeem in tx2) OR (mint with specific amount) - demonstrates operator precedence where AND binds tighter than OR
Multiple AND Conditions Across Transactions with Literal Placeholders
watchRule:
{
"expressions": [
"system.uintCompare(tx1.AavePool.E.Deposit.amount, >, ${suspiciousAmount1}) && system.uintCompare(tx2.AavePool.E.Withdraw.amount, >, ${suspiciousAmount2}) && system.addressCompare(tx2.AavePool.E.Withdraw.user, ==, ${targetAddress})"
]
}
options:
{
"literalDefs": {
"suspiciousAmount1": 98370000,
"suspiciousAmount2": 498500000,
"targetAddress": "0xBA12222222228d8Ba445958a75a0704d566BF2C8"
}
}
All three configurable conditions must be true across two Aave transactions - enables flexible threshold monitoring
Risk-Based Monitoring with Multiple Conditions (Comma-Separated)
watchRule:
{
"expressions": [
"system.uintCompare(tx1.LendingPool.F.flashLoan.amount, >, ${minAmount})",
"system.uintCompare(tx1.LendingPool.riskscore, >, ${riskThreshold})"
]
}
options:
{
"literalDefs": {
"minAmount": 1e+24,
"riskThreshold": 50
}
}
Triggers on large flash loans from high-risk addresses - comma-separated expressions are equivalent to && operator
Address List Filtering with Parameter Validation
watchRule:
{
"expressions": [
"system.uintCompare(tx1.AavePool.F.deposit.amount, >, ${largeDeposit})"
]
}
options:
{
"ruleScope": {
"contractName": "AavePool",
"groupId": "trusted_depositors",
"member": false
},
"literalDefs": {
"largeDeposit": 1e+24
}
}
Large Aave deposits from addresses not in the trusted list - parameter access implies function invocation, no need for redundant system.invoked()
Filtering Behavior: Rule fires for large deposits from untrusted addresses