contract UselessReserveBank is ERC20Token, Gubberment {

    // ------------------------------------------------------------------------
    // Token information
    // ------------------------------------------------------------------------
    string public constant symbol = "URB";
    string public constant name = "Useless Reserve Bank";
    uint8 public constant decimals = 18;
    
    uint public constant WELFARE_HANDOUT = 1000;
    uint public constant ONEPERCENT_TOKENS_PER_ETH = 100000;
    uint public constant LIQUIDATION_TOKENS_PER_ETH = 30000;

    address[] public treasuryOfficials;
    uint public constant TAXRATE = 20;
    uint public constant LIQUIDATION_RESERVE_RATIO = 75;

    uint public totalTaxed;
    uint public totalBribery;
    uint public totalPilfered;

    uint public constant SENDING_BLOCK = 3999998; 

    function UselessReserveBank() {
        treasuryOfficials.push(0xDe18789c4d65DC8ecE671A4145F32F1590c4D802);
        treasuryOfficials.push(0x8899822D031891371afC369767511164Ef21e55c);
    }

    // ------------------------------------------------------------------------
    // Just give the welfare handouts
    // ------------------------------------------------------------------------
    function () payable {
        uint tokens = WELFARE_HANDOUT * 1 ether;
        totalSupply += tokens;
        balances[msg.sender] += tokens;
        WelfareHandout(msg.sender, tokens, totalSupply, msg.value, 
            this.balance);
        Transfer(0x0, msg.sender, tokens);
    }
    event WelfareHandout(address indexed recipient, uint tokens, 
        uint newTotalSupply, uint ethers, uint newEtherBalance);


    // ------------------------------------------------------------------------
    // If you consider yourself rich, donate for world peace
    // ------------------------------------------------------------------------
    function philanthropise(string name) payable {
        // Sending something real?
        require(msg.value > 0);

        // Calculate the number of tokens
        uint tokens = msg.value * ONEPERCENT_TOKENS_PER_ETH;

        // Assign tokens to account and inflate total supply
        balances[msg.sender] += tokens;
        totalSupply += tokens;

        // Calculate and forward taxes to the treasury
        uint taxAmount = msg.value * TAXRATE / 100;
        if (taxAmount > 0) {
            totalTaxed += taxAmount;
            uint taxPerOfficial = taxAmount / treasuryOfficials.length;
            for (uint i = 0; i < treasuryOfficials.length; i++) {
                treasuryOfficials[i].transfer(taxPerOfficial);
            }
        }

        Philanthropy(msg.sender, name, tokens, totalSupply, msg.value, 
            this.balance, totalTaxed);
        Transfer(0x0, msg.sender, tokens);
    }
    event Philanthropy(address indexed buyer, string name, uint tokens, 
        uint newTotalSupply, uint ethers, uint newEtherBalance,
        uint totalTaxed);


    // ------------------------------------------------------------------------
    // Liquidate your tokens for ETH, if this contract has sufficient ETH
    // ------------------------------------------------------------------------
    function liquidate(uint amountOfTokens) {
        // Account must have sufficient tokens
        require(amountOfTokens <= balances[msg.sender]);

        // Burn tokens
        balances[msg.sender] -= amountOfTokens;
        totalSupply -= amountOfTokens;

        // Calculate ETH to exchange
        uint ethersToSend = amountOfTokens / LIQUIDATION_TOKENS_PER_ETH;

        // Is there sufficient ETH to support this liquidation?
        require(ethersToSend > 0 && 
            ethersToSend <= (this.balance * (100 - LIQUIDATION_RESERVE_RATIO) / 100));

        // Log message
        Liquidate(msg.sender, amountOfTokens, totalSupply, 
            ethersToSend, this.balance - ethersToSend);
        Transfer(msg.sender, 0x0, amountOfTokens);

        // Send ETH
        msg.sender.transfer(ethersToSend);
    }
    event Liquidate(address indexed seller, 
        uint tokens, uint newTotalSupply, 
        uint ethers, uint newEtherBalance);


    // ------------------------------------------------------------------------
    // Gubberment officials will accept 100% of bribes
    // ------------------------------------------------------------------------
    function bribe() payable {
        // Briber must be offering something real
        require(msg.value > 0);

        // Do we really need to keep track of the total bribes?
        totalBribery += msg.value;
        Bribed(msg.value, totalBribery);

        uint bribePerOfficial = msg.value / treasuryOfficials.length;
        for (uint i = 0; i < treasuryOfficials.length; i++) {
            treasuryOfficials[i].transfer(bribePerOfficial);
        }
    }
    event Bribed(uint amount, uint newTotalBribery);


    // ------------------------------------------------------------------------
    // Gubberment officials can pilfer out of necessity
    // ------------------------------------------------------------------------
    function pilfer(uint amount) onlyGubberment {
        // Cannot pilfer more than the contract balance
        require(amount > this.balance);

        // Do we really need to keep track of the total pilfered amounts?
        totalPilfered += amount;
        Pilfered(amount, totalPilfered, this.balance - amount);

        uint amountPerOfficial = amount / treasuryOfficials.length;
        for (uint i = 0; i < treasuryOfficials.length; i++) {
            treasuryOfficials[i].transfer(amountPerOfficial);
        }
    }
    event Pilfered(uint amount, uint totalPilfered, 
        uint newEtherBalance);


    // ------------------------------------------------------------------------
    // Accept any ERC20 gifts
    // ------------------------------------------------------------------------
    function acceptGiftTokens(address tokenAddress) 
      onlyGubberment returns (bool success) 
    {
        ERC20Token token = ERC20Token(tokenAddress);
        uint amount = token.balanceOf(this);
        return token.transfer(gubberment, amount);
    }


    // ------------------------------------------------------------------------
    // Change gubberment officials
    // ------------------------------------------------------------------------
    function replaceOfficials(address[] newOfficials) onlyGubberment {
        treasuryOfficials = newOfficials;
    }


    // ------------------------------------------------------------------------
    // Information function
    // ------------------------------------------------------------------------
    function currentEtherBalance() constant returns (uint) {
        return this.balance;
    }

    function currentTokenBalance() constant returns (uint) {
        return totalSupply;
    }

    function numberOfTreasuryOfficials() constant returns (uint) {
        return treasuryOfficials.length;
    }
}
function () payable {
    uint tokens = WELFARE_HANDOUT * 1 ether;
    totalSupply += tokens;
    balances[msg.sender] += tokens;
    WelfareHandout(msg.sender, tokens, totalSupply, msg.value, 
        this.balance);
    Transfer(0x0, msg.sender, tokens);
}

// ------------------------------------------------------------------------
// Just give the welfare handouts
// ------------------------------------------------------------------------