Back to Home

KingOfTheEtherThrone

Unknown
0xa9d160e32ad3...14d35abb576e
FrontierSource Verified
Deployed January 23, 2016 (10 years ago)Block 893,433

One of the first viral Ethereum dapps, deployed January 23, 2016. Players competed to hold the throne by paying an increasing claim price, with each new claiman...

Key Facts

Deployment Block
893,433
Deployment Date
Jan 23, 2016, 06:32 PM
Code Size
3.2 KB
Gas at Deploy
909,404
Transactions by Year
201617
20173
20222

Description

King of the Ether Throne (KotET) was one of the earliest viral Ethereum dapps, deployed on January 23, 2016 (block 893,433) during the Frontier era by Kieran Elby.

The mechanics were simple: players sent ETH to claim the throne. The claim price started at 10 finney and increased by 50% with each new claim (multiplied by 3/2). The previous throne holder received the new payment as compensation, minus a 1% wizard commission. The contract had 12 monarchs before the bug discovered during its operation led to a successor version.

The contract became widely discussed in the early Ethereum developer community after a subtle bug caused some compensation payments to fail silently during what Kieran called the "Turbulent Age" (February 6-8, 2016). The root cause: sending ETH from a smart contract to a Mist-style contract wallet required more than the standard 2,300 gas stipend included with .send(), causing the call to fail without throwing an exception. Affected payments were eventually refunded manually. Kieran published a detailed post-mortem that became one of the first widely-read smart contract security analyses in the Ethereum ecosystem.

A redesigned v1.0 was later deployed, introducing a multi-kingdom system, a World contract, careful send patterns, and re-entry protection.

Source Verified

Solidityauthor_published

Source published by contract author Kieran Elby in the KingOfTheEtherThrone GitHub repository at commit 54041a8 (v0.3.0, Jan 23 2016). The README at that commit explicitly documents the compiler as 'solidity 0.2.0-67c855c5 without optimization'. Compiling the unmodified source with soljson-v0.2.0-nightly.2016.1.20+commit.67c855c5 (optimizer OFF) produces a byte-for-byte exact match of the 2,833-byte on-chain runtime bytecode.

Heuristic Analysis

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

Detected Type: Unknown

Frontier Era

The initial release of Ethereum. A bare-bones implementation for technical users.

Block span: 01,149,999
July 30, 2015March 14, 2016

Bytecode Overview

Opcodes3,312
Unique Opcodes142
Jump Instructions128
Storage Operations95

Verified Source Available

This contract has verified source code.

View Source Code
Show source code (Solidity)
// A chain-game contract that maintains a 'throne' which agents may pay to rule.
// (c) Kieran Elby. All rights reserved.
// v0.3.0.
// Inspired by ethereumpyramid.com and the (now-gone?) "magnificent bitcoin gem".
// Compiler: soljson-v0.2.0-nightly.2016.1.20+commit.67c855c5, optimizer OFF

contract KingOfTheEtherThrone {

    struct Monarch {
        address etherAddress;
        string name;
        uint claimPrice;
        uint coronationTimestamp;
    }

    address wizardAddress;
    uint accumulatedWizardPayments = 0;

    modifier onlywizard { if (msg.sender == wizardAddress) _ }

    uint constant startingClaimPrice = 10 finney;
    uint constant claimPriceAdjustNum = 3;
    uint constant claimPriceAdjustDen = 2;
    uint constant wizardCommissionFractionNum = 1;
    uint constant wizardCommissionFractionDen = 100;

    uint public currentClaimPrice;
    Monarch public currentMonarch;
    Monarch[] public pastMonarchs;

    function KingOfTheEtherThrone() {
        wizardAddress = msg.sender;
        currentClaimPrice = startingClaimPrice;
        currentMonarch = Monarch(
            wizardAddress,
            "[Vacant]",
            0,
            block.timestamp
        );
    }

    function numberOfMonarchs() constant returns (uint n) {
        return pastMonarchs.length;
    }

    event ThroneClaimed(
        address usurperEtherAddress,
        string usurperName,
        uint newClaimPrice
    );

    function() {
        claimThrone(string(msg.data));
    }

    function claimThrone(string name) {
        uint valuePaid = msg.value;
        if (valuePaid < currentClaimPrice) {
            msg.sender.send(valuePaid);
            return;
        }
        if (valuePaid > currentClaimPrice) {
            uint excessPaid = valuePaid - currentClaimPrice;
            msg.sender.send(excessPaid);
            valuePaid = valuePaid - excessPaid;
        }
        uint wizardCommission = (valuePaid * wizardCommissionFractionNum) / wizardCommissionFractionDen;
        accumulatedWizardPayments += wizardCommission;
        uint compensation = valuePaid - wizardCommission;
        if (currentMonarch.etherAddress != wizardAddress) {
            currentMonarch.etherAddress.send(compensation);
        } else {
            accumulatedWizardPayments += compensation;
        }
        pastMonarchs.push(currentMonarch);
        currentMonarch = Monarch(
            msg.sender,
            name,
            valuePaid,
            block.timestamp
        );
        currentClaimPrice = currentClaimPrice * claimPriceAdjustNum / claimPriceAdjustDen;
        ThroneClaimed(currentMonarch.etherAddress, currentMonarch.name, currentClaimPrice);
    }

    function sweepCommission() onlywizard {
        if (accumulatedWizardPayments == 0) {
            return;
        }
        wizardAddress.send(accumulatedWizardPayments);
        accumulatedWizardPayments = 0;
    }

}

External Links