Back to Home

CKBirthBot

other
0x00000000a8f8...0a2594c9a126
ByzantiumExact Bytecode MatchEdit this contract
Deployed November 17, 2018 (7 years ago)Block 6,720,524

A CryptoKitties birth bot that earns midwife rewards while deploying self-destructing child contracts for gas refunds.

Key Facts

Deployment Block
6,720,524
Deployment Date
Nov 17, 2018, 09:35 AM
Code Size
1.6 KB
Gas at Deploy
477,077
Transactions by Year
201815,018
201913,026
20203,370
20214
20233

Description

CKBirthBot is a CryptoKitties birth bot deployed in November 2018 at an address starting with seven zero bytes (0x00000000). It calls the CryptoKitties core contract giveBirth() function to earn midwife rewards for birthing pregnant kitties. Simultaneously, it batch-deploys self-destructing child contracts via inline CREATE opcodes to harvest gas refunds, following a pattern similar to GST2 but with a custom, non-ERC20 implementation. The contract encodes its entire operational logic in a single fallback function that parses raw calldata to determine which action to take: birthing kitties, deploying gas token children, or managing storage slots. The contract includes owner-restricted withdraw and gas threshold functions protected by inline assembly origin checks.

Source Verified

SolidityExact bytecode match(1,683 bytes)
Compiler: v0.4.17

Compiled with solc v0.4.17+commit.bdeb9e52, optimizer disabled. Exact runtime bytecode match against on-chain code at block 6720524.

Heuristic Analysis

The following characteristics were detected through bytecode analysis and may not be accurate.

Detected Type: other

Byzantium Era

First Metropolis hard fork. Added zk-SNARK precompiles, REVERT opcode, and staticcall.

Block span: 4,370,0007,279,999
October 16, 2017February 28, 2019

Bytecode Overview

Opcodes1,683
Unique Opcodes173
Jump Instructions81
Storage Operations28

Verified Source Available

Source verified through compiler archaeology and exact bytecode matching.

View Verification Proof
Show source code (Solidity)
pragma solidity ^0.4.13;

contract CKBirthBot {
    uint256 counter;
    uint256 gasThreshold;

    function() payable {
        bytes32 data;
        bytes32 v1;
        uint256 v2;
        uint256 v3;
        uint256 v4;
        uint256 v5;
        uint256 v6;
        uint256 v7;
        uint256 v8;
        uint256 v9;

        if (msg.data.length > msg.value) {
            assembly { data := calldataload(callvalue()) }

            if (uint256(byte(data)) == msg.value) {
                data = bytes32(uint256(data) * 0x100);
                v1 = data;
                data = bytes32(uint256(data) * 0x100);
                v9 = gasThreshold;

                if (byte(v1) == 0x01 && tx.gasprice > v2) {
                    v3 = uint256(bytes2(data));
                    assembly { sstore(v3, callvalue()) }
                }

                data = bytes32(uint256(data) * 0x10000);
                v4 = uint256(bytes4(data));
                data = bytes32(uint256(data) * 0x100000000);

                if (block.blockhash(v4 - 1) != 0) {
                    v5 = uint256(bytes3(data));

                    while (v5 > msg.value) {
                        data = bytes32(uint256(data) * 0x1000000);

                        if (address(0x06012c8cf97BEaD5deAe237070F9587f8E7A266d).call(0x88c2a0bf, v5) && byte(v1) == 0x01) {
                            v3 = uint256(bytes3(data));
                            v7 = v3 + 6;

                            while (v3 < v7) {
                                if (v3 > 0xffff) {
                                    assembly {
                                        mstore(callvalue, add(v3, 0xd99400000000a8f806c754549943b6550a2594c9a12683000000))
                                        pop(call(gas, sha3(6, 0x1a), callvalue, callvalue, callvalue, callvalue, callvalue))
                                    }
                                } else if (v3 > 0xff) {
                                    assembly {
                                        mstore(callvalue, add(v3, 0xd89400000000a8f806c754549943b6550a2594c9a126820000))
                                        pop(call(gas, sha3(7, 0x19), callvalue, callvalue, callvalue, callvalue, callvalue))
                                    }
                                } else if (v3 > 0x7f) {
                                    assembly {
                                        mstore(callvalue, add(v3, 0xd79400000000a8f806c754549943b6550a2594c9a1268100))
                                        pop(call(gas, sha3(8, 0x18), callvalue, callvalue, callvalue, callvalue, callvalue))
                                    }
                                } else {
                                    assembly {
                                        mstore(callvalue, add(v3, 0xd69400000000a8f806c754549943b6550a2594c9a12600))
                                        pop(call(gas, sha3(9, 0x17), callvalue, callvalue, callvalue, callvalue, callvalue))
                                    }
                                }
                                v3++;
                            }
                        }

                        data = bytes32(uint256(data) * 0x1000000);
                        v6++;
                        if (v6 == 4) {
                            assembly { data := calldataload(0x20) }
                        } else if (v6 == 9) {
                            assembly { data := calldataload(0x3e) }
                        }
                        v5 = uint256(bytes3(data));
                    }
                }
            } else if (byte(data) == 0x01) {
                data = bytes32(uint256(data) * 0x100);
                v8 = uint256(bytes3(data));
                v9 = v8 + 0x64;
                if (v8 > 1) {
                    while (v8 < v9) {
                        assembly { sstore(v8, 1) }
                        v8++;
                    }
                }
            } else if (byte(data) == 0x02) {
                assembly {
                    mstore(0x64, 0x3318585733ff600052601b6005f3)
                    mstore(0x56, address)
                    mstore8(0x60, 0x7a)
                    mstore8(0x61, 0x73)
                    for { let i := 0 } lt(i, 0x3c) { i := add(i, 1) } {
                        pop(create(0, 0x60, 0x24))
                    }
                    sstore(0, add(0x3c, sload(0)))
                }
            }
        }
    }

    function withdraw(uint256 amount) public {
        checkOwner();
        checkGas();
        if (amount > 0) {
            tx.origin.transfer(amount);
        }
    }

    function setGasThreshold(uint256 val) public {
        checkOwner();
        checkGas();
        assembly { sstore(1, val) }
    }

    function checkOwner() internal {
        assembly {
            jumpi(ok, eq(origin(), 0x06aba80df0bb055e707a2c0337910c1438dc9d17))
            revert(0, 0)
            ok:
        }
    }

    function checkGas() internal {
        assembly {
            jumpi(ok, lt(gaslimit(), 0x01312d00))
            revert(0, 0)
            ok:
        }
    }
}

External Links