Wait for onchain events and work with lists
Many times, we would want to be alerted whenever a specific thing happened onchain. Often, an EVM event would be emitted when an interested operation happens (ERC20 transfer, implementation change, etc).
In this example, we have a list of addresses, and we want to be notified if they are ever blacklisted by USDC.
use Events, Contains, Len from hexagate;
source usdc: address = 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48;
source myAddresses: list<address> = list(
0x10DF6B6fe66dd319B1f82BaB2d054cbb61cdAD2e,
0x95ba4cf87d6723ad9c0db21737d862be80e93911
);
source blacklistEvents: list<tuple<address>> = Events {
contract: usdc,
signature: "event Blacklisted(address)"
};
source blacklistedAddresses: list<address> = [
event[0] for event in blacklistEvents
];
source myBlacklisted: list<address> = [
address
for address in myAddresses
if Contains {
item: address,
sequence: blacklistedAddresses
}
];
rule {
description: "The following addresses were blacklisted: $myBlacklisted",
condition: Len { sequence: myBlacklisted } == 0
};A little bit more complex than previous examples, let's walk through it:
Here we're importing some data sources, saving the USDC contract address, as well as a list of addresses we are interested in monitoring for.
In the previous example, we've used Call to actively call a function on the blockchain. Here, Events is not doing anything actively. Instead, it looks for specific events (with this contract address and signature) that have happened in the current block.
Basically, this allows us to "wait" for events happening onchain, in order to perform some checks on them. If there were none, we would get an empty list. If there were 3 events that matched, they will all appear on this list.
Specifically here the Blacklisted event is emitted by the USDC contract whenever an account is blacklisted. The address parameter is the blacklisted account address.
The type of blacklistedEvents is list<tuple<address>>. This is because (similar to the function call parameters from the previous example) events can have multiple parameters.
For the next step, we need the actual list of addresses, so we can use a list comprehension to extract them.
This operation creates a new list: for each event in the blacklistEvents list (so event is a tuple<address>), we access the first element in the tuple (event[0]), so we end up with list<address>.
Here is another list comprehension. The first part is pretty simple - address for address in myAddresses.
The next part is a condition - only if the condition is true, we will include the address in the new list.
Here, we want to create a list that will only contain addresses from myAddresses if they were blacklisted on this block. So, we use the Contains datasource, to check if any of our addresses appear in the blacklistedAddresses list.
Our new list would contains these addresses which appear both in myAddresses and blacklistedAddresses, which means that if this list is not empty, one of our addresses has been blacklisted!
So, Finally, our rule will ensure every block that myBlacklisted is empty, by using the Len datasource.
Last updated