Factory that deploys a short-lived bot to buy into FoMo3D repeatedly and chase the airdrop pot, then self-destructs it.
Historical Significance
FoMo3D paid an airdrop to buyers probabilistically, with the odds rising with purchase size, so the game rewarded whoever could fire the most qualifying buys in one transaction. Deploying a fresh contract per attempt and destroying it at the end was how bots recovered gas and kept each attempt isolated. Contracts like this are the visible residue of an on chain race that ran for weeks in mid 2018.
Key Facts
Description
execute is owner gated through an assembly label jump rather than a require, which is why the compiled check carries no address masking. It creates a child contract, forwarding the incoming ether as the child's endowment and passing the game address, an affiliate code, an iteration count and a floor for the airdrop pot.
The child's constructor is the whole program. It loops up to the requested number of times, reading airDropPot_ from the game each pass and stopping early once the pot falls below the floor. Each iteration calls buyXid with value and then withdraw to pull winnings back. When the loop ends the child self-destructs to the transaction origin, returning both the remaining balance and part of the deployment gas.
Source Verified
Byzantium Era
First Metropolis hard fork. Added zk-SNARK precompiles, REVERT opcode, and staticcall.
Bytecode Overview
Verified Source Available
This contract has verified source code.
View Verification ProofShow source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
pragma solidity ^0.4.24;
contract FoMo3D {
function airDropPot_() public view returns (uint256);
}
contract Bot {
constructor(address _game, uint256 _affCode, uint256 _times, uint256 _minPot) public payable {
for (uint256 i = 0; i < _times + 1; i++) {
if (FoMo3D(_game).airDropPot_() < _minPot) {
break;
}
_game.call.value(msg.value)(0x8f38f309, _affCode, uint256(1));
_game.call(0x3ccfd60b);
}
selfdestruct(tx.origin);
}
}
contract Executor {
address owner;
function () public payable {
}
function execute(address _game, uint256 _affCode, uint256 _times, uint256 _minPot) public payable {
address o = owner;
assembly {
jumpi(ok, eq(caller, o))
revert(0, 0)
ok:
}
(new Bot).value(msg.value)(_game, _affCode, _times, _minPot);
}
}