Allow new claims if the star db gets updated with new stars

pragma solidity ^0.4.15;

import './zeppelin/ownership/Ownable.sol';

contract StarMarket is Ownable {

// You can use this hash to verify the csv file containing all the stars
    string public csvHash = "";

    address owner;

    string public standard = 'Stars';
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;
    uint256 public claimFee;

    uint public nextStarIndexToAssign = 0; // TODO: unused, remove?

    bool public allStarsAssigned = false;
    bool public canClaimStars = false;
    uint public starsRemainingToAssign = 0;

//mapping (address => uint) public addressToStarIndex;
    mapping (uint => address) public starIndexToAddress;

/* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;

    struct Offer {
    bool isForSale;
    uint starIndex;
    address seller;
    uint minValue;          // in ether
    address onlySellTo;     // specify to sell only to a specific person
    }

    struct Bid {
    bool hasBid;
    uint starIndex;
    address bidder;
    uint value;
    }

// A record of stars that are offered for sale at a specific minimum value, and perhaps to a specific person
    mapping (uint => Offer) public starsOfferedForSale;

// A record of the highest star bid
    mapping (uint => Bid) public starBids;

    mapping (address => uint) public pendingWithdrawals;

    event Assign(address indexed to, uint256 starIndex);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event StarTransfer(address indexed from, address indexed to, uint256 starIndex);
    event StarOffered(uint indexed starIndex, uint minValue, address indexed toAddress);
    event StarBidEntered(uint indexed starIndex, uint value, address indexed fromAddress);
    event StarBidWithdrawn(uint indexed starIndex, uint value, address indexed fromAddress);
    event StarBought(uint indexed starIndex, uint value, address indexed fromAddress, address indexed toAddress);
    event StarNoLongerForSale(uint indexed starIndex);
    event ClaimFeeUpdated(uint256 indexed claimFee);

/* Initializes contract with initial supply tokens to the creator of the contract */
    function StarMarket() payable {
    //        balanceOf[msg.sender] = initialSupply;        // Give the creator all initial tokens
        owner = msg.sender;
        totalSupply = 119615;                               // Update total supply
        starsRemainingToAssign = totalSupply;
        name = "STARS";                                     // Set the name for display purposes
        symbol = "★";                                       // Set the symbol for display purposes
        decimals = 0;                                       // Amount of decimals for display purposes
        claimFee = 15000000000000000;                       // Price of claiming a star
    }

    function setInitialOwner(address to, uint starIndex) onlyOwner {
        if (allStarsAssigned) revert();
        if (starIndex >= totalSupply) revert();
        if (starIndexToAddress[starIndex] != to) {
            if (starIndexToAddress[starIndex] != 0x0) {
                balanceOf[starIndexToAddress[starIndex]]--;
            } else {
                starsRemainingToAssign--;
            }
            starIndexToAddress[starIndex] = to;
            balanceOf[to]++;
            Assign(to, starIndex);
        }
    }

    function setInitialOwners(address[] addresses, uint[] indices) onlyOwner {
        uint n = addresses.length;
        for (uint i = 0; i < n; i++) {
            setInitialOwner(addresses[i], indices[i]);
        }
    }

    function allInitialOwnersAssigned() onlyOwner {
        allStarsAssigned = true;
        canClaimStars = true;
    }

    function updateCSV(string newHash, uint256 newTotalSupply) onlyOwner {
        if (newTotalSupply < totalSupply) revert();         // We should only be able to add stars to the db
        csvHash = newHash;
        if (totalSupply != newTotalSupply) {
            starsRemainingToAssign = newTotalSupply - totalSupply;
            canClaimStars = true;
            totalSupply = newTotalSupply;
        }
    }

    function updateClaimFee(uint256 newClaimFee) onlyOwner {
        claimFee = newClaimFee;
        ClaimFeeUpdated(newClaimFee);
    }

    function getStar(uint starIndex) {
        if (!allStarsAssigned && !canClaimStars) revert();
        if (starsRemainingToAssign == 0) revert();
        if (starIndexToAddress[starIndex] != 0x0) revert();
        if (starIndex >= totalSupply) revert();
        if (msg.value < claimFee) revert();
        pendingWithdrawals[owner] += msg.value;
        starIndexToAddress[starIndex] = msg.sender;
        balanceOf[msg.sender]++;
        starsRemainingToAssign--;
        if (starsRemainingToAssign == 0) {
            canClaimStars = false;
        }
        Assign(msg.sender, starIndex);
    }

// Transfer ownership of a star to another user without requiring payment
    function transferStar(address to, uint starIndex) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        if (starsOfferedForSale[starIndex].isForSale) {
            starNoLongerForSale(starIndex);
        }
        starIndexToAddress[starIndex] = to;
        balanceOf[msg.sender]--;
        balanceOf[to]++;
        Transfer(msg.sender, to, 1);
        StarTransfer(msg.sender, to, starIndex);
    // Check for the case where there is a bid from the new owner and refund it.
    // Any other bid can stay in place.
        Bid storage bid = starBids[starIndex];
        if (bid.bidder == to) {
        // Kill bid and refund value
            pendingWithdrawals[to] += bid.value;
            starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        }
    }

    function starNoLongerForSale(uint starIndex) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(false, starIndex, msg.sender, 0, 0x0);
        StarNoLongerForSale(starIndex);
    }

    function offerStarForSale(uint starIndex, uint minSalePriceInWei) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(true, starIndex, msg.sender, minSalePriceInWei, 0x0);
        StarOffered(starIndex, minSalePriceInWei, 0x0);
    }

    function offerStarForSaleToAddress(uint starIndex, uint minSalePriceInWei, address toAddress) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(true, starIndex, msg.sender, minSalePriceInWei, toAddress);
        StarOffered(starIndex, minSalePriceInWei, toAddress);
    }

    function buyStar(uint starIndex) payable {
        if (!allStarsAssigned) revert();
        Offer storage offer = starsOfferedForSale[starIndex];
        if (starIndex >= totalSupply) revert();
        if (!offer.isForSale) revert();                // star not actually for sale
        if (offer.onlySellTo != 0x0 && offer.onlySellTo != msg.sender) revert();  // star not supposed to be sold to this user
        if (msg.value < offer.minValue) revert();      // Didn't send enough ETH
        if (offer.seller != starIndexToAddress[starIndex]) revert(); // Seller no longer owner of star

        address seller = offer.seller;

        starIndexToAddress[starIndex] = msg.sender;
        balanceOf[seller]--;
        balanceOf[msg.sender]++;
        Transfer(seller, msg.sender, 1);

        starNoLongerForSale(starIndex);
        pendingWithdrawals[seller] += msg.value;
        StarBought(starIndex, msg.value, seller, msg.sender);

    // Check for the case where there is a bid from the new owner and refund it.
    // Any other bid can stay in place.
        Bid storage bid = starBids[starIndex];
        if (bid.bidder == msg.sender) {
        // Kill bid and refund value
            pendingWithdrawals[msg.sender] += bid.value;
            starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        }
    }

    function withdraw() {
        if (!allStarsAssigned) revert();
        uint amount = pendingWithdrawals[msg.sender];
    // Remember to zero the pending refund before
    // sending to prevent re-entrancy attacks
        pendingWithdrawals[msg.sender] = 0;
        msg.sender.transfer(amount);
    }

    function enterBidForStar(uint starIndex) payable {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] == 0x0) revert();
        if (starIndexToAddress[starIndex] == msg.sender) revert();
        if (msg.value == 0) revert();
        Bid storage existing = starBids[starIndex];
        if (msg.value <= existing.value) revert();
        if (existing.value > 0) {
        // Refund the failing bid
            pendingWithdrawals[existing.bidder] += existing.value;
        }
        starBids[starIndex] = Bid(true, starIndex, msg.sender, msg.value);
        StarBidEntered(starIndex, msg.value, msg.sender);
    }

    function acceptBidForStar(uint starIndex, uint minPrice) {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        address seller = msg.sender;
        Bid storage bid = starBids[starIndex];
        if (bid.value == 0) revert();
        if (bid.value < minPrice) revert();

        starIndexToAddress[starIndex] = bid.bidder;
        balanceOf[seller]--;
        balanceOf[bid.bidder]++;
        Transfer(seller, bid.bidder, 1);

        starsOfferedForSale[starIndex] = Offer(false, starIndex, bid.bidder, 0, 0x0);
        uint amount = bid.value;
        starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        pendingWithdrawals[seller] += amount;
        StarBought(starIndex, bid.value, seller, bid.bidder);
    }

    function withdrawBidForStar(uint starIndex) {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] == 0x0) revert();
        if (starIndexToAddress[starIndex] == msg.sender) revert();
        Bid storage bid = starBids[starIndex];
        if (bid.bidder != msg.sender) revert();
        StarBidWithdrawn(starIndex, bid.value, msg.sender);
        uint amount = bid.value;
        starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
    // Refund the bid money
        msg.sender.transfer(amount);
    }

}

pragma solidity ^0.4.15;

import './zeppelin/ownership/Ownable.sol';

contract StarMarket is Ownable {

// You can use this hash to verify the csv file containing all the stars
    string public csvHash = "";

    address owner;

    string public standard = 'Stars';
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;
    uint256 public claimFee;

    uint public nextStarIndexToAssign = 0; // TODO: unused, remove?

    bool public allStarsAssigned = false;
    uint public starsRemainingToAssign = 0;

//mapping (address => uint) public addressToStarIndex;
    mapping (uint => address) public starIndexToAddress;

/* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;

    struct Offer {
    bool isForSale;
    uint starIndex;
    address seller;
    uint minValue;          // in ether
    address onlySellTo;     // specify to sell only to a specific person
    }

    struct Bid {
    bool hasBid;
    uint starIndex;
    address bidder;
    uint value;
    }

// A record of stars that are offered for sale at a specific minimum value, and perhaps to a specific person
    mapping (uint => Offer) public starsOfferedForSale;

// A record of the highest star bid
    mapping (uint => Bid) public starBids;

    mapping (address => uint) public pendingWithdrawals;

    event Assign(address indexed to, uint256 starIndex);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event StarTransfer(address indexed from, address indexed to, uint256 starIndex);
    event StarOffered(uint indexed starIndex, uint minValue, address indexed toAddress);
    event StarBidEntered(uint indexed starIndex, uint value, address indexed fromAddress);
    event StarBidWithdrawn(uint indexed starIndex, uint value, address indexed fromAddress);
    event StarBought(uint indexed starIndex, uint value, address indexed fromAddress, address indexed toAddress);
    event StarNoLongerForSale(uint indexed starIndex);
    event ClaimFeeUpdated(uint256 indexed claimFee);

/* Initializes contract with initial supply tokens to the creator of the contract */
    function StarMarket() payable {
    //        balanceOf[msg.sender] = initialSupply;        // Give the creator all initial tokens
        owner = msg.sender;
        totalSupply = 119615;                               // Update total supply
        starsRemainingToAssign = totalSupply;
        name = "STARS";                                     // Set the name for display purposes
        symbol = "★";                                       // Set the symbol for display purposes
        decimals = 0;                                       // Amount of decimals for display purposes
        claimFee = 15000000000000000;                       // Price of claiming a star
    }

    function setInitialOwner(address to, uint starIndex) onlyOwner {
        if (allStarsAssigned) revert();
        if (starIndex >= totalSupply) revert();
        if (starIndexToAddress[starIndex] != to) {
            if (starIndexToAddress[starIndex] != 0x0) {
                balanceOf[starIndexToAddress[starIndex]]--;
            } else {
                starsRemainingToAssign--;
            }
            starIndexToAddress[starIndex] = to;
            balanceOf[to]++;
            Assign(to, starIndex);
        }
    }

    function setInitialOwners(address[] addresses, uint[] indices) onlyOwner {
        uint n = addresses.length;
        for (uint i = 0; i < n; i++) {
            setInitialOwner(addresses[i], indices[i]);
        }
    }

    function allInitialOwnersAssigned() onlyOwner {
        allStarsAssigned = true;
    }

    function updateCSV(string newHash, uint256 newTotalSupply) onlyOwner {
        csvHash = newHash;
        totalSupply = newTotalSupply;
    }

    function updateClaimFee(uint256 newClaimFee) onlyOwner {
        claimFee = newClaimFee;
        ClaimFeeUpdated(newClaimFee);
    }

    function getStar(uint starIndex) {
        if (!allStarsAssigned) revert();
        if (starsRemainingToAssign == 0) revert();
        if (starIndexToAddress[starIndex] != 0x0) revert();
        if (starIndex >= totalSupply) revert();
        if (msg.value < claimFee) revert();
        pendingWithdrawals[owner] += msg.value;
        starIndexToAddress[starIndex] = msg.sender;
        balanceOf[msg.sender]++;
        starsRemainingToAssign--;
        Assign(msg.sender, starIndex);
    }

// Transfer ownership of a star to another user without requiring payment
    function transferStar(address to, uint starIndex) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        if (starsOfferedForSale[starIndex].isForSale) {
            starNoLongerForSale(starIndex);
        }
        starIndexToAddress[starIndex] = to;
        balanceOf[msg.sender]--;
        balanceOf[to]++;
        Transfer(msg.sender, to, 1);
        StarTransfer(msg.sender, to, starIndex);
    // Check for the case where there is a bid from the new owner and refund it.
    // Any other bid can stay in place.
        Bid storage bid = starBids[starIndex];
        if (bid.bidder == to) {
        // Kill bid and refund value
            pendingWithdrawals[to] += bid.value;
            starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        }
    }

    function starNoLongerForSale(uint starIndex) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(false, starIndex, msg.sender, 0, 0x0);
        StarNoLongerForSale(starIndex);
    }

    function offerStarForSale(uint starIndex, uint minSalePriceInWei) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(true, starIndex, msg.sender, minSalePriceInWei, 0x0);
        StarOffered(starIndex, minSalePriceInWei, 0x0);
    }

    function offerStarForSaleToAddress(uint starIndex, uint minSalePriceInWei, address toAddress) {
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        if (starIndex >= totalSupply) revert();
        starsOfferedForSale[starIndex] = Offer(true, starIndex, msg.sender, minSalePriceInWei, toAddress);
        StarOffered(starIndex, minSalePriceInWei, toAddress);
    }

    function buyStar(uint starIndex) payable {
        if (!allStarsAssigned) revert();
        Offer storage offer = starsOfferedForSale[starIndex];
        if (starIndex >= totalSupply) revert();
        if (!offer.isForSale) revert();                // star not actually for sale
        if (offer.onlySellTo != 0x0 && offer.onlySellTo != msg.sender) revert();  // star not supposed to be sold to this user
        if (msg.value < offer.minValue) revert();      // Didn't send enough ETH
        if (offer.seller != starIndexToAddress[starIndex]) revert(); // Seller no longer owner of star

        address seller = offer.seller;

        starIndexToAddress[starIndex] = msg.sender;
        balanceOf[seller]--;
        balanceOf[msg.sender]++;
        Transfer(seller, msg.sender, 1);

        starNoLongerForSale(starIndex);
        pendingWithdrawals[seller] += msg.value;
        StarBought(starIndex, msg.value, seller, msg.sender);

    // Check for the case where there is a bid from the new owner and refund it.
    // Any other bid can stay in place.
        Bid storage bid = starBids[starIndex];
        if (bid.bidder == msg.sender) {
        // Kill bid and refund value
            pendingWithdrawals[msg.sender] += bid.value;
            starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        }
    }

    function withdraw() {
        if (!allStarsAssigned) revert();
        uint amount = pendingWithdrawals[msg.sender];
    // Remember to zero the pending refund before
    // sending to prevent re-entrancy attacks
        pendingWithdrawals[msg.sender] = 0;
        msg.sender.transfer(amount);
    }

    function enterBidForStar(uint starIndex) payable {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] == 0x0) revert();
        if (starIndexToAddress[starIndex] == msg.sender) revert();
        if (msg.value == 0) revert();
        Bid storage existing = starBids[starIndex];
        if (msg.value <= existing.value) revert();
        if (existing.value > 0) {
        // Refund the failing bid
            pendingWithdrawals[existing.bidder] += existing.value;
        }
        starBids[starIndex] = Bid(true, starIndex, msg.sender, msg.value);
        StarBidEntered(starIndex, msg.value, msg.sender);
    }

    function acceptBidForStar(uint starIndex, uint minPrice) {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] != msg.sender) revert();
        address seller = msg.sender;
        Bid storage bid = starBids[starIndex];
        if (bid.value == 0) revert();
        if (bid.value < minPrice) revert();

        starIndexToAddress[starIndex] = bid.bidder;
        balanceOf[seller]--;
        balanceOf[bid.bidder]++;
        Transfer(seller, bid.bidder, 1);

        starsOfferedForSale[starIndex] = Offer(false, starIndex, bid.bidder, 0, 0x0);
        uint amount = bid.value;
        starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
        pendingWithdrawals[seller] += amount;
        StarBought(starIndex, bid.value, seller, bid.bidder);
    }

    function withdrawBidForStar(uint starIndex) {
        if (starIndex >= totalSupply) revert();
        if (!allStarsAssigned) revert();
        if (starIndexToAddress[starIndex] == 0x0) revert();
        if (starIndexToAddress[starIndex] == msg.sender) revert();
        Bid storage bid = starBids[starIndex];
        if (bid.bidder != msg.sender) revert();
        StarBidWithdrawn(starIndex, bid.value, msg.sender);
        uint amount = bid.value;
        starBids[starIndex] = Bid(false, starIndex, 0x0, 0);
    // Refund the bid money
        msg.sender.transfer(amount);
    }

}


Add ListLib test for search hinting behavior

pragma solidity ^0.4.15;

import "truffle/Assert.sol";

import "../../contracts/intervals/ListLib.sol";

contract TestListLib {
  // TODO avoid redefinition here
  uint constant SEARCH_DONE = 0x00;
  uint constant SEARCH_EARLIER = 0x01;
  uint constant SEARCH_LATER = 0x10;

  using ListLib for ListLib.List;

  ListLib.List intervals;

  function test0_create() {
    intervals = ListLib.createNew();
    Assert.equal(intervals.length, 0, "Initial list should be empty");
  }

  function test1_addingFirst() {
    intervals.add(3, 7, 1);

    Assert.equal(intervals.length, 1, "Added intervals should be counted");
    Assert.equal(intervals.center, 5, "Center should update on first add");
  }

  function test2_addingSecond() {
    var oldCenter = intervals.center;
    var oldLowest = intervals.lowestBegin;
    var oldHighest = intervals.highestEnd;

    intervals.add(1, 6, 2);

    Assert.equal(intervals.length, 2, "Added intervals should be counted");
    Assert.equal(intervals.center, oldCenter, "List center should not change");
    Assert.notEqual(intervals.lowestBegin, oldLowest, "Lowest beginning interval should update");
    Assert.equal(intervals.highestEnd, oldHighest, "Highest ending interval should not update");
  }

  function test3_searchNext() {
    /*
     *   0   1   2   3   4   5   6   7   8   9
     *                     center
     *               *-------|-------o
     *       *---------------|---o
     *
     *    search hint behavior:
     *
     *                       *
     *                done with search
     *
     *   <:::::::::::::::::::o
     *       search earlier
     *                       o:::::::::::::::>
     *                          search later
     *
     *   0   1   2   3   4   5   6   7   8   9
     */

    uint[] memory matchingIDs;
    uint8 searchNext;

    /*
     * case: search done
     */
    (matchingIDs, searchNext) = intervals.matching(5);
    Assert.equal(uint(searchNext), SEARCH_DONE, "Searching overlaps at center finishes search");

    /*
     * case: search earlier
     */
    (matchingIDs, searchNext) = intervals.matching(4);
    assert(matchingIDs.length > 0);  // interval containing point exists
    Assert.equal(uint(searchNext), SEARCH_EARLIER, "less than center w/ matches yields SEARCH_EARLIER");

    (matchingIDs, searchNext) = intervals.matching(0);
    assert(matchingIDs.length == 0);  // no interval containing point
    Assert.equal(uint(searchNext), SEARCH_EARLIER, "less than center w/o matches yields SEARCH_EARLIER");

    /*
     * case: search later
     */
    (matchingIDs, searchNext) = intervals.matching(6);
    assert(matchingIDs.length > 0);  // interval containing point exists
    Assert.equal(uint(searchNext), SEARCH_LATER, "greater than center w/ matches yields SEARCH_LATER");

    (matchingIDs, searchNext) = intervals.matching(7);
    assert(matchingIDs.length == 0);  // no interval containing point
    Assert.equal(uint(searchNext), SEARCH_LATER, "greater than center w/o matches yields SEARCH_LATER");

  }
}

pragma solidity ^0.4.15;

import "truffle/Assert.sol";

import "../../contracts/intervals/ListLib.sol";

contract TestListLib {
  using ListLib for ListLib.List;

  ListLib.List intervals;

  function test0_create() {
    intervals = ListLib.createNew();
    Assert.equal(intervals.length, 0, "Initial list should be empty");
  }

  function test1_addingFirst() {
    intervals.add(3, 7, 1);

    Assert.equal(intervals.length, 1, "Added intervals should be counted");
    Assert.equal(intervals.center, 5, "Center should update on first add");
  }

  function test2_addingSecond() {
    var oldCenter = intervals.center;
    var oldLowest = intervals.lowestBegin;
    var oldHighest = intervals.highestEnd;

    intervals.add(1, 6, 2);

    Assert.equal(intervals.length, 2, "Added intervals should be counted");
    Assert.equal(intervals.center, oldCenter, "List center should not change");
    Assert.notEqual(intervals.lowestBegin, oldLowest, "Lowest beginning interval should update");
    Assert.equal(intervals.highestEnd, oldHighest, "Highest ending interval should not update");
  }
}


Pot vars in storage, solidity ^0.4.13

Pot vars in storage, solidity ^0.4.13

pragma solidity ^0.4.13;
contract PotOfEther {

    struct Pot {
        string storage name;
        uint buyIn;

        address[] storage players;

        uint lastPlayerBlockNumber;

        bool isOpen;
    }

    address public owner;

    mapping(string => Pot) nameToPot;
    mapping(address => uint) public refunds;
    uint public totalPendingRefunds;

    event LogPotCreated(string name, uint buyIn);
    event LogPotJoined(string name, address indexed newPlayer, uint buyIn);
    event LogPotFull(string name);
    event LogPotExpired(string name);
    event LogPotClosed(string name);
    event LogPotWinner(string name, address indexed winner, uint refundAmount);
    event LogPotLoser(string name, address indexed loser);
    event LogAccountRefund(address indexed account, uint refundAmount);

    function PotOfEther() {
        owner = msg.sender;
    }

    function availableOwnerWithdraw() constant returns (uint){
        return this.balance - totalPendingRefunds;
    }

    function ownerWithdraw(){
        owner.transfer(availableOwnerWithdraw());
    }

    function createPot(string name) payable {
        require(msg.value > 0); // must bet something
        require(bytes(name).length > 0); // name can't be empty
        require(nameToPot[name].buyIn == 0); // there isn't already a pot with this name

        Pot storage pot = nameToPot[name];
        pot.name = name;
        pot.buyIn = msg.value;
        pot.players.push(msg.sender);
        pot.isOpen = true;

        totalPendingRefunds += pot.buyIn; // owner can't withdraw this funds while pot is open

        LogPotCreated(name, msg.value);
        LogPotJoined(name, msg.sender, msg.value);
    }

    function joinPot(string name) payable {
        Pot storage pot = nameToPot[name];
        require(pot.isOpen); // pot exists and isn't over
        require(pot.players.length < 3); // pot isn't full
        require(msg.value == pot.buyIn); // must pay buyIn amount
        for(uint i = 0; i < pot.players.length; i++){
            require(pot.players[i] != msg.sender); //must be new to this pot
        }

        pot.players.push(msg.sender);
        LogPotJoined(name, msg.sender, msg.value);

        totalPendingRefunds += pot.buyIn; // owner can't withdraw this funds while pot is open

        if(pot.players.length == 3){
            pot.lastPlayerBlockNumber = block.number;
            LogPotFull(name);
        }
    }

    function canClosePot(string name) constant returns (bool){
        Pot storage pot = nameToPot[name];
        return pot.isOpen &&
                pot.players.length == 3 &&
                block.number > pot.lastPlayerBlockNumber + 1;
    }

    function closePot(string name){
        Pot storage pot = nameToPot[name];
        require(pot.isOpen); // pot isn't closed
        require(pot.players.length == 3); // pot full
        require(block.number > pot.lastPlayerBlockNumber + 1);

        pot.isOpen = false;
        LogPotClosed(name);
        totalPendingRefunds -= (pot.buyIn * 3);

        bytes32 blockHash = block.blockhash(pot.lastPlayerBlockNumber + 1);
        if(blockHash == 0) { // pot expired due to hash storage limits - nobody closed the pot
            LogPotExpired(name);

            // return money - no fee
            for(uint i = 0; i < pot.players.length; i++){
                refunds[pot.players[i]] += pot.buyIn;
                totalPendingRefunds += pot.buyIn;
            }

            return;
        }

        bytes32 potShaResult = sha3(name, blockHash);
        uint8 loserIndex = uint8(uint256(potShaResult) % 3);

        address loser = pot.players[loserIndex];
        address winner1 = pot.players[(loserIndex + 1) % 3];
        address winner2 = pot.players[(loserIndex + 2) % 3];

        uint fee = pot.buyIn / 100;
        uint playerWinAmount = (pot.buyIn - fee) / 2; // take 1% fee and split winnins
        uint winnerRefundAmount = pot.buyIn + playerWinAmount;

        refunds[winner1] += winnerRefundAmount;
        totalPendingRefunds += winnerRefundAmount;

        refunds[winner2] += winnerRefundAmount;
        totalPendingRefunds += winnerRefundAmount;

        LogPotWinner(name, winner1, winnerRefundAmount);
        LogPotWinner(name, winner2, winnerRefundAmount);
        LogPotLoser(name, loser);
    }

    function withdrawRefund(){
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        totalPendingRefunds -= refund;

        msg.sender.transfer(refund);
        LogAccountRefund(msg.sender, refund);
    }
}

pragma solidity ^0.4.14;
contract PotOfEther {

    struct Pot {
        string name;
        uint buyIn;

        address[] players;

        uint lastPlayerBlockNumber;

        bool isOpen;
    }

    address public owner;

    mapping(string => Pot) nameToPot;
    mapping(address => uint) public refunds;
    uint public totalPendingRefunds;

    event LogPotCreated(string name, uint buyIn);
    event LogPotJoined(string name, address indexed newPlayer, uint buyIn);
    event LogPotFull(string name);
    event LogPotExpired(string name);
    event LogPotClosed(string name);
    event LogPotWinner(string name, address indexed winner, uint refundAmount);
    event LogPotLoser(string name, address indexed loser);
    event LogAccountRefund(address indexed account, uint refundAmount);

    function PotOfEther() {
        owner = msg.sender;
    }

    function availableOwnerWithdraw() constant returns (uint){
        return this.balance - totalPendingRefunds;
    }

    function ownerWithdraw(){
        owner.transfer(availableOwnerWithdraw());
    }

    function createPot(string name) payable {
        require(msg.value > 0); // must bet something
        require(bytes(name).length > 0); // name can't be empty
        require(nameToPot[name].buyIn == 0); // there isn't already a pot with this name

        Pot storage pot = nameToPot[name];
        pot.name = name;
        pot.buyIn = msg.value;
        pot.players.push(msg.sender);
        pot.isOpen = true;

        totalPendingRefunds += pot.buyIn; // owner can't withdraw this funds while pot is open

        LogPotCreated(name, msg.value);
        LogPotJoined(name, msg.sender, msg.value);
    }

    function joinPot(string name) payable {
        Pot storage pot = nameToPot[name];
        require(pot.isOpen); // pot exists and isn't over
        require(pot.players.length < 3); // pot isn't full
        require(msg.value == pot.buyIn); // must pay buyIn amount
        for(uint i = 0; i < pot.players.length; i++){
            require(pot.players[i] != msg.sender); //must be new to this pot
        }

        pot.players.push(msg.sender);
        LogPotJoined(name, msg.sender, msg.value);

        totalPendingRefunds += pot.buyIn; // owner can't withdraw this funds while pot is open

        if(pot.players.length == 3){
            pot.lastPlayerBlockNumber = block.number;
            LogPotFull(name);
        }
    }

    function canClosePot(string name) constant returns (bool){
        Pot storage pot = nameToPot[name];
        return pot.isOpen &&
                pot.players.length == 3 &&
                block.number > pot.lastPlayerBlockNumber + 1;
    }

    function closePot(string name){
        Pot storage pot = nameToPot[name];
        require(pot.isOpen); // pot isn't closed
        require(pot.players.length == 3); // pot full
        require(block.number > pot.lastPlayerBlockNumber + 1);

        pot.isOpen = false;
        LogPotClosed(name);
        totalPendingRefunds -= (pot.buyIn * 3);

        bytes32 blockHash = block.blockhash(pot.lastPlayerBlockNumber + 1);
        if(blockHash == 0) { // pot expired due to hash storage limits - nobody closed the pot
            LogPotExpired(name);

            // return money - no fee
            for(uint i = 0; i < pot.players.length; i++){
                refunds[pot.players[i]] += pot.buyIn;
                totalPendingRefunds += pot.buyIn;
            }

            return;
        }

        bytes32 potShaResult = sha3(name, blockHash);
        uint8 loserIndex = uint8(uint256(potShaResult) % 3);

        address loser = pot.players[loserIndex];
        address winner1 = pot.players[(loserIndex + 1) % 3];
        address winner2 = pot.players[(loserIndex + 2) % 3];

        uint fee = pot.buyIn / 100;
        uint playerWinAmount = (pot.buyIn - fee) / 2; // take 1% fee and split winnins
        uint winnerRefundAmount = pot.buyIn + playerWinAmount;

        refunds[winner1] += winnerRefundAmount;
        totalPendingRefunds += winnerRefundAmount;

        refunds[winner2] += winnerRefundAmount;
        totalPendingRefunds += winnerRefundAmount;

        LogPotWinner(name, winner1, winnerRefundAmount);
        LogPotWinner(name, winner2, winnerRefundAmount);
        LogPotLoser(name, loser);
    }

    function withdrawRefund(){
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        totalPendingRefunds -= refund;

        msg.sender.transfer(refund);
        LogAccountRefund(msg.sender, refund);
    }
}


Update SafeERC20.sol (#2246)

Update SafeERC20.sol (#2246)

tweak intro dev comment to reflect more typical use case, wrapping an `IERC20` reference for a deposit contract using others' ERC-20 tokens. I might be mistaken ~ but typically SafeERC20 won't be used in conjunction with ERC20 for OZ token deployments?

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


Fix misspelling in comment (#3613)

Fix misspelling in comment (#3613)

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol)
pragma solidity ^0.8.0;

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
 * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 */
library BitMaps {
    struct BitMap {
        mapping(uint256 => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(
        BitMap storage bitmap,
        uint256 index,
        bool value
    ) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol)
pragma solidity ^0.8.0;

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
 * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 */
library BitMaps {
    struct BitMap {
        mapping(uint256 => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(
        BitMap storage bitmap,
        uint256 index,
        bool value
    ) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }
}


fix spelling error in comment

fix spelling error in comment

// Implements standard token interface
// From: https://github.com/slockit/DAO/blob/f640568e694a057aaeb64a0f1049fae27efe818b/Token.sol
// See also https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs

contract TokenInterface {
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /// Total amount of tokens
    uint256 public totalSupply;

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance);

    /// @notice Send `_amount` tokens to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _amount) returns (bool success);

    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
    /// is approved by `_from`
    /// @param _from The address of the origin of the transfer
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _amount) returns (bool success);

    /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
    /// its behalf
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _amount The amount of tokens to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _amount) returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens of _owner that _spender is allowed
    /// to spend
    function allowance(
        address _owner,
        address _spender
    ) constant returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _amount);
    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint256 _amount
    );
}

contract DynamicToken is TokenInterface {
  bool public isClosed;
  bool public isMaxSupplyLocked;
  bool public isLockedOpen;
  bool public isContractOwnerLocked;

  uint256 public maxSupply;

  address public upgradedContract;
  address public contractOwner;
  address[] public accounts;

  string[] public proofIds;

  mapping (address => bool) public accountExists;
  mapping (string => bool) proofIdExists;

  event TransferFrom(address indexed _from, address indexed _to,  address indexed _spender, uint256 _amount);
  event Issue(address indexed _from, address indexed _to, uint256 _amount, string _proofId);
  event Burn(address indexed _burnFrom, uint256 _amount);
  event Close(address indexed _closedBy);
  event Upgrade(address indexed _upgradedContract);
  event LockOpen(address indexed _by);
  event LockContractOwner(address indexed _by);
  event TransferContractOwnership(address indexed _by, address indexed _to);
  event MaxSupply(address indexed _by, uint256 _newMaxSupply, bool _isMaxSupplyLocked);

  function DynamicToken() {
    contractOwner = msg.sender;     // contract owner is contract creator
    maxSupply = 10**7;
    totalSupply = 0;

    isClosed = false;
    isMaxSupplyLocked = false;
    isLockedOpen = false;
    isContractOwnerLocked = false;
  }

  // restrict usage to only the owner
  modifier onlyContractOwner {
    if (msg.sender != contractOwner) throw;
    _
  }

  // check if the contract has been closed
  modifier notClosed {
    if (isClosed) throw;
    _
  }

  modifier notLockedOpen {
    if (isLockedOpen) throw;
    _
  }

  // no ether should be transferred to this contract
  modifier noEther() {if (msg.value > 0) throw; _}

  // accessors

  function getAccounts() noEther constant returns (address[] _accounts) {
    return accounts;
  }

  function balanceOf(address _owner) noEther constant returns(uint256 balance) {
    return balances[_owner];
  }

  function allowance(address _owner, address _spender) noEther constant returns (uint256 remaining) {
    return allowed[_owner][_spender];
  }

  // TOKEN MUTATORS

  // tokens are only issued in exchange for a unique proof of contribution
  function issue(address _to, uint256 _amount, string _proofId) notClosed onlyContractOwner noEther returns (bool success) {
    if (balances[_to] + _amount < balances[_to]) throw; // Guard against overflow
    if (totalSupply + _amount < totalSupply) throw;     // Guard against overflow  (this should never happen)

    if (proofIdExists[_proofId]) return false;
    if (totalSupply + _amount > maxSupply) return false;

    balances[_to] += _amount;
    totalSupply += _amount;
    _indexAccount(_to);
    _indexProofId(_proofId);
    Issue(msg.sender, _to, _amount, _proofId);
    return true;
  }

  function setMaxSupply(uint256 _maxSupply) notClosed onlyContractOwner noEther returns (bool success) {
    if (_maxSupply < totalSupply) throw;
    if (isMaxSupplyLocked) return false;

    maxSupply = _maxSupply;
    MaxSupply(msg.sender, _maxSupply, isMaxSupplyLocked);
    return true;
  }

  // lock the maxSupply to its current value forever
  function lockMaxSupply() notClosed onlyContractOwner noEther returns(bool success) {
    isMaxSupplyLocked = true;
    MaxSupply(msg.sender, maxSupply, isMaxSupplyLocked);
    return true;
  }

  function transfer(address _to, uint256 _amount) notClosed noEther returns (bool success) {
    return _transfer(msg.sender, _to, _amount);
  }

  function approve(address _spender, uint256 _amount) notClosed noEther returns (bool success) {
    allowed[msg.sender][_spender] = _amount;
    Approval(msg.sender, _spender, _amount);
    return true;
  }

  function transferFrom(address _from, address _to, uint256 _amount) notClosed noEther returns (bool success) {
    if (_amount > allowed[_from][msg.sender]) return false;

    if (allowed[_from][msg.sender] - _amount > allowed[_from][msg.sender]) throw;  // Guard against underflow

    if (_transfer(_from, _to, _amount)) {
      allowed[_from][msg.sender] -= _amount;
      TransferFrom(_from, _to, msg.sender, _amount);
      return true;
    } else {
      return false;
    }
  }

  function burn(uint256 _amount) notClosed noEther returns (bool success) {
    if (_amount > balances[msg.sender]) return false;

    if (_amount > totalSupply) throw;
    if (balances[msg.sender] - _amount > balances[msg.sender]) throw;     // Guard against underflow
    if (totalSupply - _amount > totalSupply) throw;                     // Guard against underflow

    balances[msg.sender] -= _amount;
    totalSupply -= _amount;
    Burn(msg.sender, _amount);
    return true;
  }

  // CONTRACT MUTATORS

  // Lock the contract owner forever
  function lockContractOwner() notClosed onlyContractOwner noEther returns(bool success) {
    isContractOwnerLocked = true;
    LockContractOwner(msg.sender);
    return true;
  }

  function transferContractOwnership(address _newOwner) notClosed onlyContractOwner noEther returns (bool success) {
    if(isContractOwnerLocked) throw;

    contractOwner = _newOwner;
    TransferContractOwnership(msg.sender, _newOwner);
    return true;
  }

  // Block the contract from ever being upgraded, closed, or destroyed
  function lockOpen() notClosed onlyContractOwner noEther returns (bool success) {
    isLockedOpen = true;
    LockOpen(msg.sender);
    return true;
  }

  function upgrade(address _upgradedContract) notLockedOpen notClosed onlyContractOwner noEther returns (bool success) {
    upgradedContract = _upgradedContract;
    close();
    Upgrade(_upgradedContract);
    return true;
  }

  function close() notLockedOpen notClosed onlyContractOwner noEther returns (bool success) {
    isClosed = true;
    Close(msg.sender);
    return true;
  }

  function destroyContract() notLockedOpen onlyContractOwner noEther {
    selfdestruct(contractOwner);
  }

  // PRIVATE MUTATORS

  function _transfer(address _from, address _to, uint256 _amount) notClosed private returns (bool success) {
    if (_amount > balances[_from]) return false;

    if (balances[_to] + _amount < balances[_to]) throw;      // Guard against overflow
    if (balances[_from] - _amount > balances[_from]) throw;  // Guard against underflow

    balances[_to] += _amount;
    balances[_from] -= _amount;
    _indexAccount(_to);
    Transfer(_from, _to, _amount);
    return true;
  }

  function _indexAccount(address _account) notClosed private returns (bool success) {
    if (accountExists[_account]) return;
    accountExists[_account] = true;
    accounts.push(_account);
    return true;
  }

  function _indexProofId(string _proofId) notClosed private returns (bool success) {
    if (proofIdExists[_proofId]) return;
    proofIdExists[_proofId] = true;
    proofIds.push(_proofId);
    return true;
  }

  // throw on malformed calls
  function () {
    throw;
  }
}

// Implements standard token interface
// From: https://github.com/slockit/DAO/blob/f640568e694a057aaeb64a0f1049fae27efe818b/Token.sol
// See also https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs

contract TokenInterface {
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /// Total amount of tokens
    uint256 public totalSupply;

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance);

    /// @notice Send `_amount` tokens to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _amount) returns (bool success);

    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
    /// is approved by `_from`
    /// @param _from The address of the origin of the transfer
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _amount) returns (bool success);

    /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
    /// its behalf
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _amount The amount of tokens to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _amount) returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens of _owner that _spender is allowed
    /// to spend
    function allowance(
        address _owner,
        address _spender
    ) constant returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _amount);
    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint256 _amount
    );
}

contract DynamicToken is TokenInterface {
  bool public isClosed;
  bool public isMaxSupplyLocked;
  bool public isLockedOpen;
  bool public isContractOwnerLocked;

  uint256 public maxSupply;

  address public upgradedContract;
  address public contractOwner;
  address[] public accounts;

  string[] public proofIds;

  mapping (address => bool) public accountExists;
  mapping (string => bool) proofIdExists;

  event TransferFrom(address indexed _from, address indexed _to,  address indexed _spender, uint256 _amount);
  event Issue(address indexed _from, address indexed _to, uint256 _amount, string _proofId);
  event Burn(address indexed _burnFrom, uint256 _amount);
  event Close(address indexed _closedBy);
  event Upgrade(address indexed _upgradedContract);
  event LockOpen(address indexed _by);
  event LockContractOwner(address indexed _by);
  event TransferContractOwnership(address indexed _by, address indexed _to);
  event MaxSupply(address indexed _by, uint256 _newMaxSupply, bool _isMaxSupplyLocked);

  function DynamicToken() {
    contractOwner = msg.sender;     // contract owner is contract creator
    maxSupply = 10**7;
    totalSupply = 0;

    isClosed = false;
    isMaxSupplyLocked = false;
    isLockedOpen = false;
    isContractOwnerLocked = false;
  }

  // restrict usage to only the owner
  modifier onlyContractOwner {
    if (msg.sender != contractOwner) throw;
    _
  }

  // check if the contract has been closed
  modifier notClosed {
    if (isClosed) throw;
    _
  }

  modifier notLockedOpen {
    if (isLockedOpen) throw;
    _
  }

  // no ether should be transfered to this contract
  modifier noEther() {if (msg.value > 0) throw; _}

  // accessors

  function getAccounts() noEther constant returns (address[] _accounts) {
    return accounts;
  }

  function balanceOf(address _owner) noEther constant returns(uint256 balance) {
    return balances[_owner];
  }

  function allowance(address _owner, address _spender) noEther constant returns (uint256 remaining) {
    return allowed[_owner][_spender];
  }

  // TOKEN MUTATORS

  // tokens are only issued in exchange for a unique proof of contribution
  function issue(address _to, uint256 _amount, string _proofId) notClosed onlyContractOwner noEther returns (bool success) {
    if (balances[_to] + _amount < balances[_to]) throw; // Guard against overflow
    if (totalSupply + _amount < totalSupply) throw;     // Guard against overflow  (this should never happen)

    if (proofIdExists[_proofId]) return false;
    if (totalSupply + _amount > maxSupply) return false;

    balances[_to] += _amount;
    totalSupply += _amount;
    _indexAccount(_to);
    _indexProofId(_proofId);
    Issue(msg.sender, _to, _amount, _proofId);
    return true;
  }

  function setMaxSupply(uint256 _maxSupply) notClosed onlyContractOwner noEther returns (bool success) {
    if (_maxSupply < totalSupply) throw;
    if (isMaxSupplyLocked) return false;

    maxSupply = _maxSupply;
    MaxSupply(msg.sender, _maxSupply, isMaxSupplyLocked);
    return true;
  }

  // lock the maxSupply to its current value forever
  function lockMaxSupply() notClosed onlyContractOwner noEther returns(bool success) {
    isMaxSupplyLocked = true;
    MaxSupply(msg.sender, maxSupply, isMaxSupplyLocked);
    return true;
  }

  function transfer(address _to, uint256 _amount) notClosed noEther returns (bool success) {
    return _transfer(msg.sender, _to, _amount);
  }

  function approve(address _spender, uint256 _amount) notClosed noEther returns (bool success) {
    allowed[msg.sender][_spender] = _amount;
    Approval(msg.sender, _spender, _amount);
    return true;
  }

  function transferFrom(address _from, address _to, uint256 _amount) notClosed noEther returns (bool success) {
    if (_amount > allowed[_from][msg.sender]) return false;

    if (allowed[_from][msg.sender] - _amount > allowed[_from][msg.sender]) throw;  // Guard against underflow

    if (_transfer(_from, _to, _amount)) {
      allowed[_from][msg.sender] -= _amount;
      TransferFrom(_from, _to, msg.sender, _amount);
      return true;
    } else {
      return false;
    }
  }

  function burn(uint256 _amount) notClosed noEther returns (bool success) {
    if (_amount > balances[msg.sender]) return false;

    if (_amount > totalSupply) throw;
    if (balances[msg.sender] - _amount > balances[msg.sender]) throw;     // Guard against underflow
    if (totalSupply - _amount > totalSupply) throw;                     // Guard against underflow

    balances[msg.sender] -= _amount;
    totalSupply -= _amount;
    Burn(msg.sender, _amount);
    return true;
  }

  // CONTRACT MUTATORS

  // Lock the contract owner forever
  function lockContractOwner() notClosed onlyContractOwner noEther returns(bool success) {
    isContractOwnerLocked = true;
    LockContractOwner(msg.sender);
    return true;
  }

  function transferContractOwnership(address _newOwner) notClosed onlyContractOwner noEther returns (bool success) {
    if(isContractOwnerLocked) throw;

    contractOwner = _newOwner;
    TransferContractOwnership(msg.sender, _newOwner);
    return true;
  }

  // Block the contract from ever being upgraded, closed, or destroyed
  function lockOpen() notClosed onlyContractOwner noEther returns (bool success) {
    isLockedOpen = true;
    LockOpen(msg.sender);
    return true;
  }

  function upgrade(address _upgradedContract) notLockedOpen notClosed onlyContractOwner noEther returns (bool success) {
    upgradedContract = _upgradedContract;
    close();
    Upgrade(_upgradedContract);
    return true;
  }

  function close() notLockedOpen notClosed onlyContractOwner noEther returns (bool success) {
    isClosed = true;
    Close(msg.sender);
    return true;
  }

  function destroyContract() notLockedOpen onlyContractOwner noEther {
    selfdestruct(contractOwner);
  }

  // PRIVATE MUTATORS

  function _transfer(address _from, address _to, uint256 _amount) notClosed private returns (bool success) {
    if (_amount > balances[_from]) return false;

    if (balances[_to] + _amount < balances[_to]) throw;      // Guard against overflow
    if (balances[_from] - _amount > balances[_from]) throw;  // Guard against underflow

    balances[_to] += _amount;
    balances[_from] -= _amount;
    _indexAccount(_to);
    Transfer(_from, _to, _amount);
    return true;
  }

  function _indexAccount(address _account) notClosed private returns (bool success) {
    if (accountExists[_account]) return;
    accountExists[_account] = true;
    accounts.push(_account);
    return true;
  }

  function _indexProofId(string _proofId) notClosed private returns (bool success) {
    if (proofIdExists[_proofId]) return;
    proofIdExists[_proofId] = true;
    proofIds.push(_proofId);
    return true;
  }

  // throw on malformed calls
  function () {
    throw;
  }
}


Add counterfactual calling in CallLib

Add counterfactual calling in CallLib

import "./BulletinBoard.sol";

/**
 * This library contains functions which support calling of arbitrary functions
 * with variable arguments.
 */
library CallLib {

	/**
	 * Executes a call to a function in a contract.
	 *
	 * _target: The target contract to call
	 * _value: The amount of Ether to send
	 * _methodSignature: The signature of the method being called
	 * _calldata: The arguments passed to the function
	 */
	function doCall(address _target, uint _value, bytes4 _methodSignature, bytes32[] _calldata) {
		if (!_target.call.value(_value)(_methodSignature, _calldata)) {
			throw;
		}
	}

	/**
	 * Finds a contract from a BulletinBoard and calls it.
	 *
	 * _bulletinBoard: The BulletinBoard where the contract can be foundg
	 * _contractID: The ID of the contract that is being foundg
	 * _value: The amount of Ether to send
	 * _methodSignature: The signature of the method being called
	 * _calldata: The arguments passed to the function
	 */
	function callFromBulletinBoard(
		BulletinBoard _bulletinBoard,
		bytes32 _contractID,
		uint _value,
		bytes4 _methodSignature,
		bytes32[] _calldata
	) {
		address target = _bulletinBoard.registry(_contractID);
		if (target == 0 || !target.call.value(_value)(_methodSignature, _calldata)) {
			throw;
		}
	}
}

/**
 * This library contains functions which support calling of arbitrary functions
 * with variable arguments.
 */
library CallLib {

	/**
	 * Executes a call to a function in a contract.
	 *
	 * _target: The target contract to call
	 * _value: The amount of Ether to send
	 * _methodSignature: The signature of the method being called
	 * _calldata: The arguments passed to the function
	 */
	function doCall(address _target, uint _value, bytes4 _methodSignature, bytes32[] _calldata) {
		if (!_target.call.value(_value)(_methodSignature, _calldata)) {
			throw;
		}
	}
	// TODO: Make a counterfactually addressing version of the function above!
}


update constructor parameters

update constructor parameters

import "HumanStandardToken.sol";

// Creates 20,000,000.00000000 Pluton (PLU) Tokens
contract Plutons is HumanStandardToken(2000000000000000, "Pluton", 8, "PLU") {
}

import "HumanStandardToken.sol";

contract Plutons is HumanStandardToken(20000000, "Pluton", 8, "PLU") {
}