Fomo3D developers would prefer if you never heard about this vulnerability, as this smart contract exploit turns the popular cryptocurrency game into a rat race that can’t be won without cheating. And since smart contracts of other DApps are also susceptible to this weakness, you need to be aware of it when working on your own blockchain solution.
In one of our previous posts, we already went over one of the Fomo3D exploits, but this one seems to be much more significant. This article will be helpful for distributed application developers who build smart contracts for the Ethereum platform.
Fomo3D is an extremely popular game on the Ethereum network that’s developed by Team Just. The rules of Fomo3D are deceptively simple. Players can purchase one or more keys, which adds time to a timer and marks them as the current leader. With each key purchase during the round, the price of keys increases slightly. The last person to buy a key when the time runs out is the winner, and receives half of the pot. The other half is distributed among all the other players.
There are more details to the contract such as teams, pot distributions, and “Divies.” But the most important rule is that you have to be the last one to play in order to win. A normal winning scenario should occur when the price of a key becomes so high that nobody would want to buy a key. However, there’s a simple way to cheat the game. In a nutshell, if no one else could send transactions while you were in the lead, then you could win easily.
This approach has been known for a while now, and many people have theorized about ways it could be achieved. One of them is a mining attack. A miner can pick transactions, which they include within a block, and manipulate things like timestamps to some degree. This would give the miner the power to prevent anyone else from accessing the smart contract. However, a single miner wouldn’t be able to do much damage. Other miners might allow transactions, so the attack wouldn’t be successful. In order for it to succeed, the miner would have to pull off a 51% attack. A 51% attack means that a single miner (or a mining pool) acquires more than half of the network’s hash rate. In this case, this miner would have the monopoly on block creation and would be able to block transactions from other users.
Fortunately, a 51% attack is extremely difficult to perform, as it would probably require cooperation from multiple large mining pools. And in case such an attack did occur, Fomo3D would be the least of everyone’s worries.
The Fomo3D exploit can be explained by looking closely at how transactions are structured. Let’s consider a Fomo3D exploit scenario. In addition to hundreds of players, at the end of the game there are many bots constantly monitoring the state of the game. These bots would keep buying keys once the timer reached a certain threshold. With all of these bots pointed at the smart contract, the attacker would definitely have to prevent other transactions from reaching it.
This could be achieved not by acquiring a large amount of hashing power but by abusing the network itself and buying out whole blocks. To understand how it’s possible to “buy a block” on the Ethereum blockchain, we have to understand how the blockchain operates in the first place. Specifically, we need to look at the concept of GAS limits.
GAS is a secondary currency on the Ethereum network that’s used to pay for transactions. If the transactions were free, malicious users could spam useless transactions in order to waste miners’ resources and block the whole network. In order to prevent such denial of service attacks, Ethereum introduced a fee for each transaction that has to be paid up-front. This fee limits the number of computations that may be executed during a transaction (like transferring tokens, updating balances, calculating dividends, etc.). If a computation exceeds the GAS limit, the transaction fails and all of the GAS is consumed. The GAS fee is paid directly to the miner, so miners usually select transactions with the maximum GAS fees for processing.
This provides greater flexibility for users. If you want your transaction to be executed sooner, you can set a higher GAS price and miners will be more likely to include your transaction in a block. Unfortunately, this also means that if there are many transactions with expensive GAS, cheaper transactions may not be included. Such transactions will have to wait for a few minutes or up to an hour. Apart from the GAS limit set by the fee, there’s a global GAS limit for each block. This limit is set by miners and might change somewhat, but usually it’s around 8 million GAS. If the cumulative GAS used by all transactions within a block exceeds this limit, then no more transactions may be added to that block.
These GAS usage mechanisms open an interesting possibility. It’s possible to send several transactions with high GAS prices and arrange for them to use more than 8 million GAS in total. These transactions would be selected first by miners for their high fees. And since they use up so much GAS, no other transactions would be able to fit into the same block. Effectively, this allows a single person to buy full blocks.
To gauge the efficiency of such an attack, we have to estimate the cost of a full block on Ethereum. GAS prices in Ethereum are measured in gwei, which is a billionth of an Ether. The average GAS price on the Ethereum network right now is around 12 to 15 gwei. To ensure that a transaction is included in the next block, the price should be about 10 times larger than average, so 120 to 150 gwei. And since a block consists of 8 million GAS, the total price for a block comes to 1.2 Ether (~300 USD at the time of writing). Since we know the average block time on Ethereum to be 15 seconds, we can calculate how much it would cost per minute for the exclusive right to send transactions.
1 Ether = 1,000,000,000 gwei
1 GAS = 150 gwei
1 block = 8,000,000 GAS
1 block = 15 seconds
We can calculate:
1 minute = 4 blocks = 4 × 8,000,000 GAS × 150 gwei = 4 × 1,200,000,000 gwei = 4 × 1.2 Ether = 4.8 Ether
Despite the high cost of such an attack, the payoff might be worth it. Just like it was with the 10,000 Ether in Fomo3D.
So the strategy is simple: send a lot of transactions that waste a lot of GAS while setting a high GAS price. At the calculated price of 4.8 Ether/minute, the last winnings from Fomo3D would cover stalling the network for about 34 hours. That should be more than enough to win, given that the maximum time limit in Fomo3D is 24 hours. But you would need to have 10,000 Ether to pay for GAS in the first place, and in the end you would receive nothing but disapproval from the Ethereum community. The real-life attacker decided on a different approach.
The basic strategy can be deduced from the last few blocks before the win. This block is a great example of how the attack proceeded. It contains only three transactions, all to the same smart contract. The contract’s source code isn’t publicly available, however from decompiling the Solidity bytecode we can tell a few things about what the contract does. First, it checks the state of the Fomo3D contract. If the timer is beyond a certain threshold and the attacker is in the lead, it fails an assertion to consume all of the GAS. Otherwise it reverts, consuming very little GAS.
A contract like this can be called by a bot, similar to other Fomo3D bots. Except the bot can first become the leader and then start blocking other people’s transactions. And that’s exactly how the attacker was able to snatch first place in Fomo3D. To hide some of its tracks, the bot also used different addresses and different smart contracts to perform the attack, but all of the smart contracts point back to the winner of Fomo3D as the culprit.
The victory, however, is considered legitimate. The smart contract of the game worked as intended. Team Just, the development team behind Fomo3D, had no issues with the victory:
The game itself is a parody of the greedy pump and dump ICOs, and the way it ended with a hack seems somehow appropriate. The next round is already underway, with more than 8,000 Ether in the pot at this point. And players will probably be even more creative in cheating the system the second time.
Unfortunately, this attack displays a larger issue with Ethereum itself. While the attack targeted only the Fomo3D smart contract, it has affected the whole network. This method makes it possible to manipulate the outcome of any smart contract. Every time-constrained DApp is vulnerable to this attack. Smart contracts can be manipulated during:
- Some ICOs
- Votes and governance
Each of these types of contracts can be exploited by preventing any further transactions (at any point) once the attacker’s preferred outcome has been reached. The only way to avoid being vulnerable to such attacks is to avoid using timestamps for regulating time limits.
This can be achieved by using Oracle contracts that notify the target smart contract about an external event. However, this adds a lot of complexity to the smart contract while making the system less decentralized. Other that that, there’s no easy way for smart contracts to avoid this vulnerability because the contracts themselves aren’t the problem. The issue here is an inherent flaw of the network, and that could only be fixed by changing how miners accept transactions. This shouldn’t lead to a fork, but it will require a lot of cooperation from miners and the community.
However, the cost of the attack limits the number of vulnerable contracts. Only large lotteries with immediate payoffs (similar to Fomo3D) would make viable targets. So it’s unlikely that any action will be taken, keeping the network vulnerable until major changes are introduced like the planned introduction of Proof of Stake.
In this article, we’ve looked at Ethereum smart contract vulnerabilities, focusing on particular weakness with round conclusion and establishing block ownership that came to light because of the exploit in Fomo3D, an Ethereum-based game. Even though only Fomo3D was affected, the attack has large consequences for Ethereum and particularly for its core element — smart contracts — demonstrating that the outcome of any smart contract can be manipulated.
At Apriorit, we have a team of blockchain professionals with a high level of expertise in developing and pen-testing different kinds of smart contracts and other blockchain-based applications. If you’re working on a new blockchain solution, our experts would be glad to assist.