Pwning Fomo3D Revealed: Iterative, Pre-Calculated Contract Creation For Airdrop Prizes!
Fomo3D  is an extreme popular, phenomenal and ponzi-like crypto-game in recent days. Justo, the developer of the game, made an astonishing announcement on twitter: “I have discovered an exploit that would be considered the equivalent of a nuclear bomb on the EVM.”
Unfortunately, Péter Szilágyi, the team lead of Ethereum foundation, argued that it was just a documented behavior, as shown in Figure 2.
In the meantime, Péter punched back with his findings, a bug in Fomo3D’s smart contract:
As a matter of fact, PeckShield researchers have observed attacks in the wild, and attackers had harvested many ETHs by exploiting the airdrop mechanism of Fomo3D. In this blog, we would like to reveal the attacks and financial damages we observed so far. In addition, we are going to go through the details of the particular security issue of Fomo3D and the corresponding the attack vectors.
Observed Attacks and Damages
We have observed multiple transactions launched by attackers, as follows:
However, the victim is not just Fomo3D merely. There exist several of pirated games with almost the same source code, therefore here comes the following victim list:
|Name||Address||Damage (in ETH)||Cost (in ETH)|
Bug in Fomo3D
The essence of the risk is caused by an improper check of access control. As already pointed out by Péter in Figure 3, Fomo3D relies on extcodesize to determine the type of a caller’s address: an account or a contract, as following:
You may wonder why a contract is required here, the reason behind is to control the opportunity to win the airdrop, as demonstrated in Figure 6:
Since the seed is computed by the information about the current block (e.g., timestamp in line 1416, difficulty in line 1417, etc.) plus the msg.sender, the attacker can pre-calculate the result in a contract before attacking the airdrop() function of Fomo3D. If a good seed against the current airDropTracker_, the attacker can always invest at the right time that the airdrop() returns true (line 1424). As shown in Figure 7, the airdrop() function in line 1051 is used as a switch to control the calculation of the airdrop prize:
Now, the exploitation steps could be summarized in the following:
- Pre-calculate the address X of the next contract that the attacker address is about to create ;
- If X can’t be used to generate a good seed with the current airDropTracker_, goto step 1;
- Create contract at address X;
- Invoke buyXid() function from X to win the airdrop prize;
- Invoke withdraw() function from X to get earnings calculated by the airdrop prize;
The airdrop prize relies on the value of airDropPot_ and the msg.value you just sent. airDropPot_ can be queried directly. Up to this writing, it was 0x840ca8cc325d303, which means you may get 0.1486744641827934 ETH back by sending 0.1 ETH and winning the airdrop. The above procedure can be launched repeatedly to make more profit, and you may refer to  for details.
PeckShield Inc. is a blockchain security company which aims to elevate the security, privacy, and usability of current blockchain ecosystem by offering top-notch, industry-leading services and products (e.g., smart contract auditing). Please contact us at Telegram, Twitter, or Email.
 StackExchange: How is the address of an Ethereum contract computed?, Jan 29, 2016
 Ethereum - Péter Szilágyi: How to pwn Fomo3D, July 23, 2018