Monitor: do events from a monitored contract match when another contract made the call?
Written 5 October 2026
Yes for events, no for functions. Verified in the OpenZeppelin Monitor 1.6.0 source, src/. Upstream question: openzeppelin-monitor #406.
Situation
You monitor contract A. A user calls contract B, and B calls A internally. The transaction's to is B. Does your monitor on A fire?
Events: yes
filter_block fetches all logs for the block with no address filter, groups them by transaction hash, and evaluates every transaction in the block against every monitor. find_ walks the transaction's logs, keeps the ones whose log.address equals a monitored address, and adds that emitting address to the transaction's involved addresses. It never looks at transaction.to. A transaction counts as involving a monitored address if that address is the sender, the recipient, or the emitter of a matched log.
So if A emits an event during the internal call, a monitor on A with an event condition for that event matches, provided A's contract_spec (the ABI array in the monitor's addresses entry) contains the event so the log can be decoded.
Functions: no
find_ decodes transaction.input against the ABI of the address in transaction.to. An internal call from B into A is not in the transaction input, so a function condition on A does not see it. A fallback call has no selector to decode either. Monitor 1.6.0 does no call tracing.
Workaround
For cross-contract calls, emit an event from the monitored contract and match the event. Use function conditions only for direct calls to the monitored address.
A matching monitor fragment:
"addresses": [{"address": "0xA...", "contract_spec": [ ...ABI including the event... ]}],
"match_conditions": {
"events": [{"signature": "Rebalanced(address,uint256)", "expression": "amount > 0"}]
}
Signatures use exact Solidity types with no parameter names or spaces.