In this blog, Soptq and Kovart describe their bots developed as part of a recent Forta contest aimed at identifying attacks with high precision before digital assets are stolen from a protocol. The intent of this blog is to expand the bot developer’s community toolbox to create more valuable Forta detection bots that help to secure Web3.
Forta detection bots usually analyze transactions through some type of heuristic or machine learning model. For example, a detection bot can assess whether a transaction utilized a flash loan. However, detection bots can do a lot more. They can reach out to the web to fetch additional information or execute arbitrary code to analyze a transaction in different ways, which opens the door to identify more sophisticated attacks earlier.
Early detection with high precision is needed in order to secure protocols. As previously discussed, attacks usually go through four distinct stages. As the attack moves towards the right side of these stages, the confidence that an attack occurred increases. Ideally, attacks ought to be identified with high confidence in the first two stages prior to funds being lost.
In the preparation stage, attackers may deploy an attacker smart contract, which then later gets invoked by the attacker in the exploitation stage to steal the funds. However, as soon as the smart contract is deployed, a defender can fork the chain at that point, invoke the smart contract, and observe the attacker contract drain the funds from the victim contract.
Forta’s detection bot development contest #3 was aimed at leveraging simulation methods to successfully identify hacks in the first two stages. Detection bots are able to simulate attacks utilizing a locally forked version of the blockchain using Ganache. Specifically, the purpose of this contest was to identify the Saddle Finance attack using simulation and discover new methods that security researchers can use to flag similar attacks in the future. In the following sections, Soptq and Kovart describe their bots and methods that were submitted as part of this contest.
This bot detects suspicious contract functions by simulating invoking them in a forked environment. The bot will observe defined suspicious state changes after invocation and raise alerts. This bot does not use any external APIs, so it will support all chains supported by Forta.
Specifically, this bot will first detect the creation of any contract, pulling its byte code from the blockchain for analysis. Next, the bot will decode the byte-code to op-code using an implemented byte2op decoder, and then it will go through the decoded op-code to determine the entry point of every function implemented in the contract by using matching patterns like PUSH4 -> EQ -> PUSH -> JUMPI. Finally, it will hard fork the blockchain at the contract creation time and simulate the invoking of the function to see if there are suspicious state changes.
But, while some functions are parameterless, many functions need arguments to proceed normally or they will plainly revert. Consequently, a big challenge here is how to correctly provide arguments for the invoked function. This bot will automatically determine the arguments of the function by brute force attack. In other words, it will firstly try to feed the function with no argument, checking if it reverts. If yes, then the bot will try to feed the function with one argument, checking if it reverts, and so on.
A special feature of this bot is a unique system for finding the signature of a function. First the bot tries to find the number of parameters of the function. This is done by looking at the value of programCounter, which is returned with the error and indicates where the error occurred. If the function signature is not valid, it will return a revert that always has the same programCounter. If the signature is valid, but the passed values are wrong, revert will happen inside the function and the programCounter will be changed. Once inside the function, it proceeds to fuzz its parameters. To do this, the combinatorial function “combinations with repetition” is used with the following potential values: deployer/sender address, 0, 1, 1e18, 1e22, MaxUint256.
To increase the success of a function call, all transactions are called on behalf of the account that deployed the smart contract. It is also worth noting that all function calls, even if they are reverted, waste gas. Therefore, a virtual 99,999 ether is sent to the sender before the fuzzing begins.
This bot uses the approach of tracking balance changes based on ERC20, ERC721, ERC1155 token events. In contrast to simply checking the attacker’s balance, this approach allows detection of absolutely all token movements, including outgoing ones. Balances after an attack are performed and written to the balanceChanges metadata field, which contains information about addresses and their affected tokens. This approach allows the attack to be detected even if the attacker uses secondary accounts to which the stolen money will be sent. In addition to knowing negative balance changes, this allows the easy detection of the addresses of victims to include them in the alert. Forta allows the subscription to alerts in which your addresses are involved. So if your address or contract is involved in such an attack, you will be notified immediately before the attack even begins.
Detection bots allow for a broad range of developer freedom. In this blog post, is is illustrated how a challenging data problem can be solved with attack simulation to identify attacks early with high precision. If you are developing detection bots on Forta and have a need to interact with the blockchain, consider the forking technique described in this post. It will help to identify attacks early with high precision. If you have ideas on how to improve the fuzzing component, consider joining the Forta Discord to discuss detection bot development and detection bot development ideas. Forta’s bot development contest #5 is currently live, offering up to $5,000 in FORT to identify new methods of on-chain money laundering.