Understanding the attack on Maxbet

PigFarm
4 min readAug 19, 2019

--

This article explains what we have discovered after careful investigation on the attack that won about 45k TOMO in MaxBet.

> The attack did not break the random algorithm, but it exploits a vulnerability in settleBet and refundBet contract function.

Bet lifecycle

To understand the attack, we will first explain the lifecycle of a bet:

1. Players send betting transactions to the contract, all bets that are in the same block are grouped in a round.
2. Once the bets are made, the bot from PigFarm team sends a transaction to settle those bets and start a new round for players to continue playing.
3. What the settling transaction does is that call function nextTick
— Compute lucky numbers for each player to determine whether a player wins or loses. The lucky numbers are computed in function reveal
— call settleBet function that loops over the list of the winning players in order to send funds back to the players that win the bet
4. If those bets are not settled within 150 blocks from the block that contains the bets, all players funds will be sent back to the players, which is done in refundBet function.

Vulnerabilities

AFAWK, the vulnerability is within the loop of the settleBet and refundBet function that the attacker took advantage:

1. for every winning player, settleBet calls transfer method to send funds to those winners
2. the transfer function should work properly for all users who use a normal account with a private key to bet.

The attack

The attacker was using 1 normal account and 15 contracts to attack the system

1. Normal account: `0xc001e936e922cf929f872eb9ae0b1a2da11f4a3b`
2. A master smart contract: `0xbe93bb3aa39dd24a56e374e323a53069567201ae`
3. 14 players contracts:

[https://scan.tomochain.com/address/0xbe7668a8c5ae9504a8d79fd7aff1d2ede4f53b4f](https://scan.tomochain.com/address/0xbe7668a8c5ae9504a8d79fd7aff1d2ede4f53b4f) — called `BetCheck` contract

all following contracts are called `Player Contract` or `BetHighAmountContract`

[https://scan.tomochain.com/address/0x18f64f65ceaf54db5c436a8fff075c17c0b16060](https://scan.tomochain.com/address/0x18f64f65ceaf54db5c436a8fff075c17c0b16060)

[https://scan.tomochain.com/address/0xde8f5de007d06aad84431126bcfdfe598d01b72a](https://scan.tomochain.com/address/0xde8f5de007d06aad84431126bcfdfe598d01b72a)[https://scan.tomochain.com/address/0x5b99417f694f01f534bdc2d27e9c449acd8d7bb2](https://scan.tomochain.com/address/0x5b99417f694f01f534bdc2d27e9c449acd8d7bb2)

[https://scan.tomochain.com/address/0x04869525b8d90904f55f4e3b54f01437eec83584](https://scan.tomochain.com/address/0x04869525b8d90904f55f4e3b54f01437eec83584)

[https://scan.tomochain.com/address/0x880ecb83d04fc60103315022f209b0f569ee61ac](https://scan.tomochain.com/address/0x880ecb83d04fc60103315022f209b0f569ee61ac)

[https://scan.tomochain.com/address/0xdd2f4784d3841d2b652d09cd6eb255da41ec2267](https://scan.tomochain.com/address/0xdd2f4784d3841d2b652d09cd6eb255da41ec2267)

[https://scan.tomochain.com/address/0xc878650bf45282ff7174c802615f822520b10111](https://scan.tomochain.com/address/0xc878650bf45282ff7174c802615f822520b10111)

[https://scan.tomochain.com/address/0xc8cf3b8e09dcc9ffb99b72902a8de885ef0c21f5](https://scan.tomochain.com/address/0xc8cf3b8e09dcc9ffb99b72902a8de885ef0c21f5)

[https://scan.tomochain.com/address/0x45a908e6a7d6123ba3c0a7b1247c248a2ff4a853](https://scan.tomochain.com/address/0x45a908e6a7d6123ba3c0a7b1247c248a2ff4a853)

[https://scan.tomochain.com/address/0xcff425baff3fedbf4d30efd05ad29a34680e365e](https://scan.tomochain.com/address/0xcff425baff3fedbf4d30efd05ad29a34680e365e)

[https://scan.tomochain.com/address/0xac22d0a2302ff4173f220bd4bb88e0eff22cbc68](https://scan.tomochain.com/address/0xac22d0a2302ff4173f220bd4bb88e0eff22cbc68)

[https://scan.tomochain.com/address/0x8d9e228ab0aeaefee889261527e7b76ec990db3f](https://scan.tomochain.com/address/0x8d9e228ab0aeaefee889261527e7b76ec990db3f)

[https://scan.tomochain.com/address/0x8f6749e757222fc77fe83590f536931ec24df0da](https://scan.tomochain.com/address/0x8f6749e757222fc77fe83590f536931ec24df0da)

Here’s how the attacker played:

1. Send about `1911` TOMO from the normal account to the master contract [here](https://scan.tomochain.com/txs/0x90f82cd3632d2d7a956245947fe1ffeb44e6b335712bc3f3c7a19b8a700d36c5)
2. The master contract:
— Send 0.1 TOMO to the first player contract BetCheck [0xbe7668a8c5ae9504a8d79fd7aff1d2ede4f53b4f](https://scan.tomochain.com/address/0xbe7668a8c5ae9504a8d79fd7aff1d2ede4f53b4f)
— Sends 147 TOMO to each of next 12 player contracts `BetHighAmountContract`
— Send 146.9 TOMO to the last player contract BetHighAmountContract [0x8f6749e757222fc77fe83590f536931ec24df0da](https://scan.tomochain.com/address/0x8f6749e757222fc77fe83590f536931ec24df0da)
— Note, all these bets happened within the same block and all of the last 13 contract players were betting on the same number, all are betting on over 50. if one of those 13 contracts win its bet, the other 12 contracts also win.
3. Each player contract calls `placeBet` function of MaxBet to make bets and all
— BetCheck bets under 95 with a bet amount of 0.1 to ensure that this bet will win with a very high probability

- All other player contracts bet 147 TOMO (and 146.9 TOMO) for over 50.

All is well until the bot calls nextTick function, which in turns call settleBet function to settle the bets.

Remember that settleBet loops all over winning players to call transfer function to send winning funds back to them. The best trick is that the first player contract has a fallback function that always reverts the settleBet function. Why?

1. When transfer funds to BetCheck contract, its fallback function is called
2. The fallback function is coded as follows:
— If one of the 13 player-contracts BetHighAmountContract lose, the fallback function reverts the whole settleBet transaction, which made the bot could not settle the pending bets, which prevents any player from betting, thus the game just suspended around 5 minutes which is actually 150 blocks, so that the attacker can get refunded from the losing bets
— If one of the 13 player contracts win, meaning that all 13 player contracts win (each win about 147 TOMO ⇒ a total of 1911 TOMO), the fallback function did not revert the settleBet transaction, which allows all players contracts to win, which in turn sent TOMO back to the master contract, and eventually to the attacker normal account [https://scan.tomochain.com/txs/0x73137d30ae6161652a5c8eb1b68b5700a347da0d07801926ab38c3a395e0908f](https://scan.tomochain.com/txs/0x73137d30ae6161652a5c8eb1b68b5700a347da0d07801926ab38c3a395e0908f).

Or in other words:

1. if all 13 player-contracts lost, the attack prevented the game from settling it in order to get `refunded` the lost funds.
2. if all 13 player-contracts won, the attacker won 1911 TOMO for each round!

We have to admit that this is a brilliant attack that exploited the vulnerability in function settleBet and refundBet.

Here is the full flow chart of how the attacker exploited the vulnerability.

How to mitigate the vulnerability?

We are developing a solution that rejects any bet from smart contract players, which in turn will make settleBet function always able to settle. Specifically, we will modify placeBet function to add more parameters including the signature of players to ensure that the betting transaction will be always made from an external account with an associated private key.

We have stopped Maxbet to proceed with the update and handle the issue. All of the stakers are recommended to withdraw your TOMO and wait for the next version. We will have an official announcement about compensation for the investors, thank you for your patience and support during the hardship. What doesn’t kill you makes you stronger!

PigFarm Team

Four kiddos having fun in the blockchain space.

For more support, reach us at:

Telegram

Twitter

--

--

PigFarm

MaxBet by PigFarm team aims to become a new standard dice game run on TomoChain. Join us on telegram: https://t.me/pigfarm