Security
Fomo3D airdrop bug
Its isHuman
function can not prohibit other contract to invoke it. Hacker can create an attack contract, and call Fomo3D's function in its constructor.
/**
* @dev prevents contracts from interacting with fomo3d
*/
modifier isHuman() {
address _addr = msg.sender;
uint256 _codeLength;
assembly {_codeLength := extcodesize(_addr)}
require(_codeLength == 0, "sorry humans only");
_;
}
Its airdrop
function has non really random seed. It depends on timestamp
, difficulty
and msg.sender
. Hacker can pre-calculate the seed by attack contract. Coin Flip of Ethernaut
is the tutorial for this.
/**
* @dev generates a random number between 0-99 and checks to see if thats
* resulted in an airdrop win
* @return do we have a winner?
*/
function airdrop()
private
view
returns(bool)
{
uint256 seed = uint256(keccak256(abi.encodePacked(
(block.timestamp).add
(block.difficulty).add
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
(block.gaslimit).add
((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
(block.number)
)));
if((seed - ((seed / 1000) * 1000)) < airDropTracker_)
return(true);
else
return(false);
}
The transaction hash of successful attack is 0x86c3ff158b7e372e3e2aa964b2c3f0ca25c59f7bcc95a13fd72b139c0ab6f7ad
.
Tricky way to win Fomo3D
The hacker confirms that being the latest player. Then hacker makes many transaction with high gas price and limit to block the blockchain, so that other players can not buy the key to be the latest one. Finally, the hacker win. King of Ethernaut
is tutorial of blocking the contract to prohibit other player to be a king.