adding order filled event

adding order filled event

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.4.18;

import "./Creatable.sol";
import "./oraclize/oraclizeAPI.sol";
import "./libraries/MathLib.sol";
import "./libraries/HashLib.sol";
import "zeppelin-solidity/contracts/token/ERC20.sol";
import "zeppelin-solidity/contracts/token/SafeERC20.sol";

// TODO:
//      add failsafe for pool distribution.
//      push as much into library as possible
//      think about circuit breaker in case of issues
//      discuss build out ability to use ETH vs only ERC20? - WETH?
//      add open interest to allow users to see outstanding open positions
//      add function to allow user to pay for an extra query right now that could trigger settlement.
//      require creator to own arbitrary amount of MEM
//      add in fee functionality needed for nodes and the reduced fees for holders of mem.

/// @title MarketContract first example of a MarketProtocol contract using Oraclize services
/// @author Phil Elsasser <phil@marketprotcol.io>
contract MarketContract is Creatable, usingOraclize  {
    using MathLib for uint256;
    using MathLib for int;
    using HashLib for address;
    using SafeERC20 for ERC20;

    struct UserNetPosition {
        address userAddress;
        Position[] positions;   // all open positions (lifo upon exit - allows us to not reindex array!)
        int netPosition;        // net position across all prices / executions
    }

    struct Position {
        uint price;
        int qty;
    }

    struct Order {
        address maker;
        address taker;
        address feeRecipient;
        uint makerFee;
        uint takerFee;
        uint qty;
        uint price;
        uint expirationTimeStamp;
        bytes32 orderHash;
    }

    enum ErrorCodes {
        ORDER_EXPIRED,              // past designated timestamp
        ORDER_DEAD                  // order if fully filled or fully cancelled
    }

    // constants
    string public CONTRACT_NAME;
    address public BASE_TOKEN_ADDRESS;
    ERC20 public BASE_TOKEN;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public QTY_DECIMAL_PLACES;     // how many tradeable units make up a whole pricing increment
    uint public EXPIRATION;
    string public ORACLE_DATA_SOURCE;
    string public ORACLE_QUERY;
    uint public ORACLE_QUERY_REPEAT;
    uint8 constant public BUY_SIDE = 0;
    uint8 constant public SELL_SIDE = 1;
    uint constant public COST_PER_QUERY = 2 finney;    // leave static for now, price of first query from oraclize is 0
    uint constant public QUERY_CALLBACK_GAS = 300000;

    // state variables
    string public lastPriceQueryResult;
    uint public lastPrice;
    uint public settlementPrice;
    bool public isSettled;
    mapping(bytes32 => bool) validQueryIDs;

    // accounting
    mapping(address => UserNetPosition) addressToUserPosition;
    mapping(address => uint) userAddressToAccountBalance;   // stores account balances allowed to be allocated to orders
    mapping (bytes32 => int) public filledOrderQty;
    mapping (bytes32 => int) public cancelledOrderQty;
    uint collateralPoolBalance = 0;                         // current balance of all collateral committed

    // events
    event OracleQuerySuccess();
    event OracleQueryFailed();
    event UpdatedLastPrice(string price);
    event ContractSettled(uint settlePrice);
    event UpdatedUserBalance(address indexed user, uint balance);
    event UpdatedPoolBalance(uint balance);
    event Error(ErrorCodes indexed errorCode, bytes32 indexed orderHash);

    // order events
    event OrderFilled(
        address indexed maker,
        address indexed taker,
        address indexed feeRecipient,
        int filledQty,
        uint paidMakerFee,
        uint paidTakerFee,
        bytes32 indexed orderHash
    );
    event OrderCancelled(
        address indexed maker,
        address indexed feeRecipient,
        int cancelledQty,
        bytes32 indexed orderHash
    );

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param baseTokenAddress address of the ERC20 token that will be used for collateral and pricing
    /// @param oracleDataSource a data-source such as "URL", "WolframAlpha", "IPFS"
    /// see http://docs.oraclize.it/#ethereum-quick-start-simple-query
    /// @param oracleQuery see http://docs.oraclize.it/#ethereum-quick-start-simple-query for examples
    /// @param oracleQueryRepeatSeconds how often to repeat this callback to check for settlement, more frequent
    /// queries require more gas and may not be needed.
    /// @param floorPrice minimum tradeable price of this contract, contract enters settlement if breached
    /// @param capPrice maximum tradeable price of this contract, contract enters settlement if breached
    /// @param priceDecimalPlaces number of decimal places to convert our queried price from a floating point to
    /// an integer
    /// @param qtyDecimalPlaces decimal places to multiply traded qty by.
    /// @param secondsToExpiration - second from now that this contract expires and enters settlement
    function MarketContract(
        string contractName,
        address baseTokenAddress,
        string oracleDataSource,
        string oracleQuery,
        uint oracleQueryRepeatSeconds,
        uint floorPrice,
        uint capPrice,
        uint priceDecimalPlaces,
        uint qtyDecimalPlaces,
        uint secondsToExpiration
    ) public payable {

        require(capPrice > floorPrice);
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        CONTRACT_NAME = contractName;
        BASE_TOKEN_ADDRESS = baseTokenAddress;
        BASE_TOKEN = ERC20(baseTokenAddress);
        PRICE_CAP = capPrice;
        PRICE_FLOOR = floorPrice;
        EXPIRATION = now + secondsToExpiration;
        ORACLE_DATA_SOURCE = oracleDataSource;
        ORACLE_QUERY = oracleQuery;
        ORACLE_QUERY_REPEAT = oracleQueryRepeatSeconds;
        PRICE_DECIMAL_PLACES = priceDecimalPlaces;
        QTY_DECIMAL_PLACES = qtyDecimalPlaces;
        require(checkSufficientStartingBalance(secondsToExpiration));
        queryOracle();  // schedules recursive calls to oracle
    }

    /*
    // EXTERNAL METHODS
    */

    // @param userAddress address to return position for
    // @return the users current open position.
    function getUserPosition(address userAddress) external view returns (int)  {
        return addressToUserPosition[userAddress].netPosition;
    }

    /// @notice deposits tokens to the smart contract to fund the user account and provide needed tokens for collateral
    /// pool upon trade matching.
    /// @param depositAmount qty of ERC20 tokens to deposit to the smart contract to cover open orders and collateral
    function depositTokensForTrading(uint256 depositAmount) external {
        // user must call approve!
        BASE_TOKEN.safeTransferFrom(msg.sender, this, depositAmount);
        uint256 balanceAfterDeposit = userAddressToAccountBalance[msg.sender].add(depositAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterDeposit;
        UpdatedUserBalance(msg.sender, balanceAfterDeposit);
    }

    // @notice called by a participant wanting to trade a specific order
    /// @param maker address of the maker of this order
    /// @param taker address of the designated taker or address(0) if publicly available to be traded
    /// @param feeRecipient address of a fee recipient, optional
    /// @param makerFee amount of MKT token for maker fee
    /// @param takerFee amount of MKT token for taker fee
    /// @param price of the order
    /// @param orderQty quantity of the order
    /// @param qtyToFill quantity taker is willing to fill (max)
    /// @param expirationTimeStamp last valid timestamp of the order (seconds since epoch)
    /// @param v order signature
    /// @param r order signature
    /// @param s order signature
    function tradeOrder(
        address maker,
        address taker,
        address feeRecipient,
        uint makerFee,
        uint takerFee,
        uint price,
        int orderQty,
        int qtyToFill,
        uint expirationTimeStamp,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (int filledQty) {
        require(!isSettled);                                // no trading past settlement
        require(taker == address(0) || taker == msg.sender);// taker can be anyone, or specifically the caller!
        require(maker != address(0) && maker != taker);     // do not allow self trade
        require(orderQty != 0 && qtyToFill != 0);           // no zero trades

        bytes32 orderHash = address(this).createOrderHash(maker, feeRecipient,
                                makerFee, takerFee, orderQty, price, expirationTimeStamp);

        require(maker.isValidSignature(orderHash, v, r, s));

        if(now >= expirationTimeStamp) {
            Error(ErrorCodes.ORDER_EXPIRED, orderHash);
            return 0;
        }

        int remainingQty = orderQty.subtract(getQtyFilledOrCancelledFromOrder(orderHash));
        if(remainingQty == 0) { // there is no qty remaining  - cannot fill!
            Error(ErrorCodes.ORDER_DEAD, orderHash);
            return 0;
        }

        filledQty = MathLib.absMin(remainingQty, qtyToFill);
        //TODO: finish build out and allocation of positions.

        uint paidMakerFee = 0;
        uint paidTakerFee = 0;
        OrderFilled(maker, taker, feeRecipient, filledQty, paidMakerFee, paidTakerFee, orderHash);
        return filledQty;
    }

    // @notice called by the maker of an order to attempt to cancel the order before its expiration time stamp
    /// @param maker address of the maker of this order
    /// @param taker address of the designated taker or address(0) if publicly available to be traded
    /// @param feeRecipient address of a fee recipient, optional
    /// @param makerFee amount of MKT token for maker fee
    /// @param takerFee amount of MKT token for taker fee
    /// @param price of the order
    /// @param orderQty quantity of the order
    /// @param qtyToCancel quantity maker is attempting to cancel
    /// @param expirationTimeStamp last valid timestamp of the order (seconds since epoch)
    /// @return qty that was successfully cancelled of order.
    function cancelOrder(
        address maker,
        address taker,
        address feeRecipient,
        uint makerFee,
        uint takerFee,
        uint price,
        int orderQty,
        int qtyToCancel,
        uint expirationTimeStamp
    ) external returns (int qtyCancelled){
        require(maker == msg.sender);                                       // only maker can cancel standing order
        require(qtyToCancel != 0 && qtyToCancel.isSameSign(orderQty));      // cannot cancel 0 and signs must match
        require(!isSettled);

        bytes32 orderHash = address(this).createOrderHash(maker, feeRecipient,
            makerFee, takerFee, orderQty, price, expirationTimeStamp);

        if(now >= expirationTimeStamp) {
            Error(ErrorCodes.ORDER_EXPIRED, orderHash);
            return 0;
        }

        int remainingQty = orderQty.subtract(getQtyFilledOrCancelledFromOrder(orderHash));
        if(remainingQty == 0) { // there is no qty remaining to cancel order is dead
            Error(ErrorCodes.ORDER_DEAD, orderHash);
            return 0;
        }

        qtyCancelled = MathLib.absMin(qtyToCancel, remainingQty);   // we can only cancel what remains
        cancelledOrderQty[orderHash] = cancelledOrderQty[orderHash].add(qtyCancelled);
        OrderCancelled(maker, feeRecipient, cancelledQty, orderHash);
        return qtyCancelled;
    }

    // @notice called by a user after settlement has occurred.  This function will finalize all accounting around any
    // outstanding positions and return all remaining collateral to the caller. This should only be called after
    // settlement has occurred.
    function settleAndClose() external {
        require(isSettled);
        UserNetPosition storage userNetPos = addressToUserPosition[msg.sender];
        if(userNetPos.netPosition != 0) {
            // this user has a position that we need to settle based upon the settlement price of the contract
            reduceUserNetPosition(msg.sender, userNetPos.netPosition * - 1, settlementPrice);
        }
        withdrawTokens(userAddressToAccountBalance[msg.sender]);   // transfer all balances back to user.
    }

    /*
    // PUBLIC METHODS
    */

    /// @param queryID of the returning query, this should match our own internal mapping
    /// @param result query to be processed
    /// @param proof result proof
    function __callback(bytes32 queryID, string result, bytes proof) public {
        require(validQueryIDs[queryID]);
        require(msg.sender == oraclize_cbAddress());
        lastPriceQueryResult = result;
        lastPrice = parseInt(result, PRICE_DECIMAL_PLACES);
        UpdatedLastPrice(result);
        delete validQueryIDs[queryID];
        checkSettlement();
        if (!isSettled) {
            queryOracle();  // set up our next query
        }
    }

    /// @notice returns the qty that is no longer available to trade for a given order
    /// @param orderHash hash of order to find filled and cancelled qty
    /// @return int quantity that is no longer able to filled from the supplied order hash
    function getQtyFilledOrCancelledFromOrder(bytes32 orderHash) public view returns (int) {
        return filledOrderQty[orderHash].add(cancelledOrderQty[orderHash]);
    }

    /// @notice removes token from users trading account
    /// @param withdrawAmount qty of token to attempt to withdraw
    function withdrawTokens(uint256 withdrawAmount) public {
        require(userAddressToAccountBalance[msg.sender] >= withdrawAmount);   // ensure sufficient balance
        uint256 balanceAfterWithdrawal = userAddressToAccountBalance[msg.sender].subtract(withdrawAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterWithdrawal;   // update balance before external call!
        BASE_TOKEN.safeTransfer(msg.sender, withdrawAmount);
        UpdatedUserBalance(msg.sender, balanceAfterWithdrawal);
    }

    /*
    // PRIVATE METHODS
    */

    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(address maker, address taker, int qty, uint price) private {
        updatePosition(maker, qty, price);
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(taker, qty * -1, price);

    }

    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(address userAddress, int qty, uint price) private {
        UserNetPosition storage userNetPosition = addressToUserPosition[userAddress];
        if(userNetPosition.netPosition == 0 ||  userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos, no collateral returned
            userNetPosition.positions.push(Position(price, qty)); //append array with new position
        }
        else {
            // opposite side from open position, reduce, flattened, or flipped.
            if(userNetPosition.netPosition >= qty * -1) { // pos is reduced of flattened
                reduceUserNetPosition(userNetPosition, qty, price);
            } else {    // pos is flipped, reduce and then create new open pos!
                reduceUserNetPosition(userNetPosition, userNetPosition.netPosition * -1, price); // flatten completely
                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                userNetPosition.positions.push(Position(price, newNetPos));   // append array with new position
            }
        }
        userNetPosition.netPosition.add(qty);
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(address userAddress, int qty, uint price) private {
        uint neededCollateral = MathLib.calculateNeededCollateral(this, qty, price);
        commitCollateralToPool(userAddress, neededCollateral);
    }

    /// @param userAddress address of user who is reducing their pos
    /// @param userNetPos storage struct for this users position
    /// @param qty signed quantity of the qty to reduce this users position by
    /// @param price transacted price
    function reduceUserNetPosition(
        address userAddress,
        UserNetPosition storage userNetPos,
        int qty,
        uint price
    ) private {
        uint collateralToReturnToUserAccount = 0;
        int qtyToReduce = qty;                      // note: this sign is opposite of our users position
        assert(userNetPos.positions.length != 0);   // sanity check
        while(qtyToReduce != 0) {   //TODO: ensure we dont run out of gas here!
            Position storage position = userNetPos.positions[userNetPos.positions.length - 1];  // get the last pos (LIFO)
            if(position.qty.abs() <= qtyToReduce.abs()) {   // this position is completely consumed!
                collateralToReturnToUserAccount.add(MathLib.calculateNeededCollateral(this, position.qty, price));
                qtyToReduce = qtyToReduce.add(position.qty);
                userNetPos.positions.length--;  // remove this position from our array.
            }
            else {  // this position stays, just reduce the qty.
                position.qty = position.qty.add(qtyToReduce);
                // pos is opp sign of qty we are reducing here!
                collateralToReturnToUserAccount.add(MathLib.calculateNeededCollateral(this, qtyToReduce * -1, price));
                //qtyToReduce = 0; // completely reduced now!
                break;
            }
        }

        if(collateralToReturnToUserAccount != 0) {  // allocate funds back to user acct.
            withdrawCollateralFromPool(userAddress, collateralToReturnToUserAccount);
        }
    }

    /// @notice moves collateral from a user's account to the pool upon trade execution.
    /// @param fromAddress address of user entering trade
    /// @param collateralAmount amount of collateral to transfer from user account to collateral pool
    function commitCollateralToPool(address fromAddress, uint collateralAmount) private {
        require(userAddressToAccountBalance[fromAddress] >= collateralAmount);   // ensure sufficient balance
        uint newBalance = userAddressToAccountBalance[fromAddress].subtract(collateralAmount);
        userAddressToAccountBalance[fromAddress] = newBalance;
        collateralPoolBalance = collateralPoolBalance.add(collateralAmount);
        UpdatedUserBalance(fromAddress, newBalance);
        UpdatedPoolBalance(collateralPoolBalance);
    }

    /// @notice withdraws collateral from pool to a user account upon exit or trade settlement
    /// @param toAddress address of user
    /// @param collateralAmount amount to transfer from pool to user.
    function withdrawCollateralFromPool(address toAddress, uint collateralAmount) private {
        require(collateralPoolBalance >= collateralAmount); // ensure sufficient balance
        uint newBalance = userAddressToAccountBalance[toAddress].add(collateralAmount);
        userAddressToAccountBalance[toAddress] = newBalance;
        collateralPoolBalance = collateralPoolBalance.subtract(collateralAmount);
        UpdatedUserBalance(toAddress, newBalance);
        UpdatedPoolBalance(collateralPoolBalance);
    }

    /// @dev call to oraclize to set up our query and record its hash.
    function queryOracle() private {
        if (oraclize_getPrice(ORACLE_DATA_SOURCE) > this.balance) {
            OracleQueryFailed();
            lastPriceQueryResult = "FAILED"; //TODO: failsafe
        } else {
            OracleQuerySuccess();
            bytes32 queryId = oraclize_query(ORACLE_QUERY_REPEAT, ORACLE_DATA_SOURCE, ORACLE_QUERY, QUERY_CALLBACK_GAS);
            validQueryIDs[queryId] = true;
        }
    }

    /// @dev checks our last query price to see if our contract should enter settlement due to it being past our
    //  expiration date or outside of our tradeable ranges.
    function checkSettlement() private {
        if(isSettled)   // already settled.
            return;

        if(now > EXPIRATION) {  // note: miners can cheat this by small increments of time (minutes, not hours)
            isSettled = true;   // time based expiration has occurred.
        } else if(lastPrice >= PRICE_CAP || lastPrice <= PRICE_FLOOR) {
            isSettled = true;   // we have breached/touched our pricing bands
        }

        if(isSettled) {
            settleContract();
        }
    }

    /// @dev records our final settlement price and fires needed events.
    /// @param finalSettlementPrice final query price at time of settlement
    function settleContract(uint finalSettlementPrice) private {
        settlementPrice = finalSettlementPrice;
        ContractSettled(finalSettlementPrice);
        // TODO: return any remaining ether balance to creator of this contract (no longer needs gas for queries)
    }

    /// @dev over estimates needed gas to power queries until expiration and determines if provided contract
    /// contains enough.
    /// @param secondsToExpiration seconds from now that expiration is scheduled.
    /// @returns true if sufficient gas is present to create queries at the designated
    /// frequency from now until expiration
    function checkSufficientStartingBalance(uint secondsToExpiration) private view returns (bool isSufficient) {
        //uint costPerQuery = oraclize_getPrice(ORACLE_DATA_SOURCE); this doesn't work prior to first query(its free)
        uint expectedNoOfQueries = secondsToExpiration / ORACLE_QUERY_REPEAT;
        uint approxGasRequired = COST_PER_QUERY * expectedNoOfQueries;
        return this.balance > (approxGasRequired * 2);
    }
}

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.4.18;

import "./Creatable.sol";
import "./oraclize/oraclizeAPI.sol";
import "./libraries/MathLib.sol";
import "./libraries/HashLib.sol";
import "zeppelin-solidity/contracts/token/ERC20.sol";
import "zeppelin-solidity/contracts/token/SafeERC20.sol";

// TODO:
//      add failsafe for pool distribution.
//      push as much into library as possible
//      think about circuit breaker in case of issues
//      discuss build out ability to use ETH vs only ERC20? - WETH?
//      add open interest to allow users to see outstanding open positions
//      add function to allow user to pay for an extra query right now that could trigger settlement.

/// @title MarketContract first example of a MarketProtocol contract using Oraclize services
/// @author Phil Elsasser <phil@marketprotcol.io>
contract MarketContract is Creatable, usingOraclize  {
    using MathLib for uint256;
    using MathLib for int;
    using HashLib for address;
    using SafeERC20 for ERC20;

    struct UserNetPosition {
        address userAddress;
        Position[] positions;   // all open positions (lifo upon exit - allows us to not reindex array!)
        int netPosition;        // net position across all prices / executions
    }

    struct Position {
        uint price;
        int qty;
    }

    struct Order {
        address maker;
        address taker;
        address feeRecipient;
        uint makerFee;
        uint takerFee;
        uint qty;
        uint price;
        uint8 makerSide;            // 0=Buy 1=Sell
        uint expirationTimeStamp;
        bytes32 orderHash;
    }

    enum ErrorCodes {
        ORDER_EXPIRED,              // past designated timestamp
        ORDER_DEAD                  // order if fully filled or fully cancelled
    }

    // constants
    string public CONTRACT_NAME;
    address public BASE_TOKEN_ADDRESS;
    ERC20 public BASE_TOKEN;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public QTY_DECIMAL_PLACES;     // how many tradeable units make up a whole pricing increment
    uint public EXPIRATION;
    string public ORACLE_DATA_SOURCE;
    string public ORACLE_QUERY;
    uint public ORACLE_QUERY_REPEAT;
    uint8 constant public BUY_SIDE = 0;
    uint8 constant public SELL_SIDE = 1;
    uint constant public COST_PER_QUERY = 2 finney;    // leave static for now, price of first query from oraclize is 0
    uint constant public QUERY_CALLBACK_GAS = 300000;

    // state variables
    string public lastPriceQueryResult;
    uint public lastPrice;
    uint public settlementPrice;
    bool public isSettled;
    mapping(bytes32 => bool) validQueryIDs;

    // accounting
    mapping(address => UserNetPosition) addressToUserPosition;
    mapping(address => uint) userAddressToAccountBalance;   // stores account balances allowed to be allocated to orders
    mapping (bytes32 => int) public filledOrderQty;
    mapping (bytes32 => int) public cancelledOrderQty;
    uint collateralPoolBalance = 0;                         // current balance of all collateral committed

    // events
    event OracleQuerySuccess();
    event OracleQueryFailed();
    event UpdatedLastPrice(string price);
    event ContractSettled(uint settlePrice);
    event UpdatedUserBalance(address indexed user, uint balance);
    event UpdatedPoolBalance(uint balance);
    event Error(ErrorCodes indexed errorCode, bytes32 indexed orderHash);
    event OrderCancelled(
        address indexed maker,
        address indexed feeRecipient,
        int cancelledQty,
        bytes32 indexed orderHash
    );

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param baseTokenAddress address of the ERC20 token that will be used for collateral and pricing
    /// @param oracleDataSource a data-source such as "URL", "WolframAlpha", "IPFS"
    /// see http://docs.oraclize.it/#ethereum-quick-start-simple-query
    /// @param oracleQuery see http://docs.oraclize.it/#ethereum-quick-start-simple-query for examples
    /// @param oracleQueryRepeatSeconds how often to repeat this callback to check for settlement, more frequent
    /// queries require more gas and may not be needed.
    /// @param floorPrice minimum tradeable price of this contract, contract enters settlement if breached
    /// @param capPrice maximum tradeable price of this contract, contract enters settlement if breached
    /// @param priceDecimalPlaces number of decimal places to convert our queried price from a floating point to
    /// an integer
    /// @param qtyDecimalPlaces decimal places to multiply traded qty by.
    /// @param secondsToExpiration - second from now that this contract expires and enters settlement
    function MarketContract(
        string contractName,
        address baseTokenAddress,
        string oracleDataSource,
        string oracleQuery,
        uint oracleQueryRepeatSeconds,
        uint floorPrice,
        uint capPrice,
        uint priceDecimalPlaces,
        uint qtyDecimalPlaces,
        uint secondsToExpiration
    ) public payable {

        require(capPrice > floorPrice);
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        CONTRACT_NAME = contractName;
        BASE_TOKEN_ADDRESS = baseTokenAddress;
        BASE_TOKEN = ERC20(baseTokenAddress);
        PRICE_CAP = capPrice;
        PRICE_FLOOR = floorPrice;
        EXPIRATION = now + secondsToExpiration;
        ORACLE_DATA_SOURCE = oracleDataSource;
        ORACLE_QUERY = oracleQuery;
        ORACLE_QUERY_REPEAT = oracleQueryRepeatSeconds;
        PRICE_DECIMAL_PLACES = priceDecimalPlaces;
        QTY_DECIMAL_PLACES = qtyDecimalPlaces;
        require(checkSufficientStartingBalance(secondsToExpiration));
        queryOracle();  // schedules recursive calls to oracle
    }

    /*
    // EXTERNAL METHODS
    */

    // @param userAddress address to return position for
    // @return the users current open position.
    function getUserPosition(address userAddress) external view returns (int)  {
        return addressToUserPosition[userAddress].netPosition;
    }

    /// @notice deposits tokens to the smart contract to fund the user account and provide needed tokens for collateral
    /// pool upon trade matching.
    /// @param depositAmount qty of ERC20 tokens to deposit to the smart contract to cover open orders and collateral
    function depositTokensForTrading(uint256 depositAmount) external {
        // user must call approve!
        BASE_TOKEN.safeTransferFrom(msg.sender, this, depositAmount);
        uint256 balanceAfterDeposit = userAddressToAccountBalance[msg.sender].add(depositAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterDeposit;
        UpdatedUserBalance(msg.sender, balanceAfterDeposit);
    }

    // @notice called by a participant wanting to trade a specific order
    /// @param maker address of the maker of this order
    /// @param taker address of the designated taker or address(0) if publicly available to be traded
    /// @param feeRecipient address of a fee recipient, optional
    /// @param makerFee amount of MKT token for maker fee
    /// @param takerFee amount of MKT token for taker fee
    /// @param price of the order
    /// @param orderQty quantity of the order
    /// @param qtyToFill quantity taker is willing to fill (max)
    /// @param expirationTimeStamp last valid timestamp of the order (seconds since epoch)
    /// @param v order signature
    /// @param r order signature
    /// @param s order signature
    function tradeOrder(
        address maker,
        address taker,
        address feeRecipient,
        uint makerFee,
        uint takerFee,
        uint price,
        int orderQty,
        int qtyToFill,
        uint expirationTimeStamp,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(!isSettled);                                // no trading past settlement
        require(taker == address(0) || taker == msg.sender);// taker can be anyone, or specifically the caller!
        require(maker != address(0) && maker != taker);     // do not allow self trade
        require(orderQty != 0 && qtyToFill != 0);           // no zero trades

        bytes32 orderHash = address(this).createOrderHash(maker, feeRecipient,
                                makerFee, takerFee, orderQty, price, expirationTimeStamp);

        require(maker.isValidSignature(orderHash, v, r, s));

        if(now >= expirationTimeStamp) {
            Error(ErrorCodes.ORDER_EXPIRED, orderHash);
            return;
        }
        // TODO finish build out

    }

    // @notice called by the maker of an order to attempt to cancel the order before its expiration time stamp
    /// @param maker address of the maker of this order
    /// @param taker address of the designated taker or address(0) if publicly available to be traded
    /// @param feeRecipient address of a fee recipient, optional
    /// @param makerFee amount of MKT token for maker fee
    /// @param takerFee amount of MKT token for taker fee
    /// @param price of the order
    /// @param orderQty quantity of the order
    /// @param qtyToCancel quantity maker is attempting to cancel
    /// @param expirationTimeStamp last valid timestamp of the order (seconds since epoch)
    /// @return qty that was successfully cancelled of order.
    function cancelOrder(
        address maker,
        address taker,
        address feeRecipient,
        uint makerFee,
        uint takerFee,
        uint price,
        int orderQty,
        int qtyToCancel,
        uint expirationTimeStamp
    ) external returns (int){
        require(maker == msg.sender);                                       // only maker can cancel standing order
        require(qtyToCancel != 0 && qtyToCancel.isSameSign(orderQty));      // cannot cancel 0 and signs must match
        require(!isSettled);

        bytes32 orderHash = address(this).createOrderHash(maker, feeRecipient,
            makerFee, takerFee, orderQty, price, expirationTimeStamp);

        if(now >= expirationTimeStamp) {
            Error(ErrorCodes.ORDER_EXPIRED, orderHash);
            return 0;
        }

        int remainingQty = orderQty.subtract(getQtyFilledOrCancelledFromOrder(orderHash));
        if(remainingQty == 0) { // there is no qty remaining to cancel order is dead
            Error(ErrorCodes.ORDER_DEAD, orderHash);
            return 0;
        }

        int qtyCancelled = MathLib.absMin(qtyToCancel, remainingQty);   // we can only cancel what remains
        cancelledOrderQty[orderHash] = cancelledOrderQty[orderHash].add(qtyCancelled);
        OrderCancelled(maker, feeRecipient, cancelledQty, orderHash);
        return qtyCancelled;
    }

    // @notice called by a user after settlement has occurred.  This function will finalize all accounting around any
    // outstanding positions and return all remaining collateral to the caller. This should only be called after
    // settlement has occurred.
    function settleAndClose() external {
        require(isSettled);
        UserNetPosition storage userNetPos = addressToUserPosition[msg.sender];
        if(userNetPos.netPosition != 0) {
            // this user has a position that we need to settle based upon the settlement price of the contract
            reduceUserNetPosition(msg.sender, userNetPos.netPosition * - 1, settlementPrice);
        }
        withdrawTokens(userAddressToAccountBalance[msg.sender]);   // transfer all balances back to user.
    }

    /*
    // PUBLIC METHODS
    */

    /// @param queryID of the returning query, this should match our own internal mapping
    /// @param result query to be processed
    /// @param proof result proof
    function __callback(bytes32 queryID, string result, bytes proof) public {
        require(validQueryIDs[queryID]);
        require(msg.sender == oraclize_cbAddress());
        lastPriceQueryResult = result;
        lastPrice = parseInt(result, PRICE_DECIMAL_PLACES);
        UpdatedLastPrice(result);
        delete validQueryIDs[queryID];
        checkSettlement();
        if (!isSettled) {
            queryOracle();  // set up our next query
        }
    }

    /// @notice returns the qty that is no longer available to trade for a given order
    /// @param orderHash hash of order to find filled and cancelled qty
    /// @return int quantity that is no longer able to filled from the supplied order hash
    function getQtyFilledOrCancelledFromOrder(bytes32 orderHash) public view returns (int) {
        return filledOrderQty[orderHash].add(cancelledOrderQty[orderHash]);
    }

    /// @notice removes token from users trading account
    /// @param withdrawAmount qty of token to attempt to withdraw
    function withdrawTokens(uint256 withdrawAmount) public {
        require(userAddressToAccountBalance[msg.sender] >= withdrawAmount);   // ensure sufficient balance
        uint256 balanceAfterWithdrawal = userAddressToAccountBalance[msg.sender].subtract(withdrawAmount);
        userAddressToAccountBalance[msg.sender] = balanceAfterWithdrawal;   // update balance before external call!
        BASE_TOKEN.safeTransfer(msg.sender, withdrawAmount);
        UpdatedUserBalance(msg.sender, balanceAfterWithdrawal);
    }

    /*
    // PRIVATE METHODS
    */

    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(address maker, address taker, int qty, uint price) private {
        updatePosition(maker, qty, price);
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(taker, qty * -1, price);

    }

    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(address userAddress, int qty, uint price) private {
        UserNetPosition storage userNetPosition = addressToUserPosition[userAddress];
        if(userNetPosition.netPosition == 0 ||  userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos, no collateral returned
            userNetPosition.positions.push(Position(price, qty)); //append array with new position
        }
        else {
            // opposite side from open position, reduce, flattened, or flipped.
            if(userNetPosition.netPosition >= qty * -1) { // pos is reduced of flattened
                reduceUserNetPosition(userNetPosition, qty, price);
            } else {    // pos is flipped, reduce and then create new open pos!
                reduceUserNetPosition(userNetPosition, userNetPosition.netPosition * -1, price); // flatten completely
                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                userNetPosition.positions.push(Position(price, newNetPos));   // append array with new position
            }
        }
        userNetPosition.netPosition.add(qty);
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(address userAddress, int qty, uint price) private {
        uint neededCollateral = MathLib.calculateNeededCollateral(this, qty, price);
        commitCollateralToPool(userAddress, neededCollateral);
    }

    /// @param userAddress address of user who is reducing their pos
    /// @param userNetPos storage struct for this users position
    /// @param qty signed quantity of the qty to reduce this users position by
    /// @param price transacted price
    function reduceUserNetPosition(
        address userAddress,
        UserNetPosition storage userNetPos,
        int qty,
        uint price
    ) private {
        uint collateralToReturnToUserAccount = 0;
        int qtyToReduce = qty;                      // note: this sign is opposite of our users position
        assert(userNetPos.positions.length != 0);   // sanity check
        while(qtyToReduce != 0) {   //TODO: ensure we dont run out of gas here!
            Position storage position = userNetPos.positions[userNetPos.positions.length - 1];  // get the last pos (LIFO)
            if(position.qty.abs() <= qtyToReduce.abs()) {   // this position is completely consumed!
                collateralToReturnToUserAccount.add(MathLib.calculateNeededCollateral(this, position.qty, price));
                qtyToReduce = qtyToReduce.add(position.qty);
                userNetPos.positions.length--;  // remove this position from our array.
            }
            else {  // this position stays, just reduce the qty.
                position.qty = position.qty.add(qtyToReduce);
                // pos is opp sign of qty we are reducing here!
                collateralToReturnToUserAccount.add(MathLib.calculateNeededCollateral(this, qtyToReduce * -1, price));
                //qtyToReduce = 0; // completely reduced now!
                break;
            }
        }

        if(collateralToReturnToUserAccount != 0) {  // allocate funds back to user acct.
            withdrawCollateralFromPool(userAddress, collateralToReturnToUserAccount);
        }
    }

    /// @notice moves collateral from a user's account to the pool upon trade execution.
    /// @param fromAddress address of user entering trade
    /// @param collateralAmount amount of collateral to transfer from user account to collateral pool
    function commitCollateralToPool(address fromAddress, uint collateralAmount) private {
        require(userAddressToAccountBalance[fromAddress] >= collateralAmount);   // ensure sufficient balance
        uint newBalance = userAddressToAccountBalance[fromAddress].subtract(collateralAmount);
        userAddressToAccountBalance[fromAddress] = newBalance;
        collateralPoolBalance = collateralPoolBalance.add(collateralAmount);
        UpdatedUserBalance(fromAddress, newBalance);
        UpdatedPoolBalance(collateralPoolBalance);
    }

    /// @notice withdraws collateral from pool to a user account upon exit or trade settlement
    /// @param toAddress address of user
    /// @param collateralAmount amount to transfer from pool to user.
    function withdrawCollateralFromPool(address toAddress, uint collateralAmount) private {
        require(collateralPoolBalance >= collateralAmount); // ensure sufficient balance
        uint newBalance = userAddressToAccountBalance[toAddress].add(collateralAmount);
        userAddressToAccountBalance[toAddress] = newBalance;
        collateralPoolBalance = collateralPoolBalance.subtract(collateralAmount);
        UpdatedUserBalance(toAddress, newBalance);
        UpdatedPoolBalance(collateralPoolBalance);
    }

    /// @dev call to oraclize to set up our query and record its hash.
    function queryOracle() private {
        if (oraclize_getPrice(ORACLE_DATA_SOURCE) > this.balance) {
            OracleQueryFailed();
            lastPriceQueryResult = "FAILED"; //TODO: failsafe
        } else {
            OracleQuerySuccess();
            bytes32 queryId = oraclize_query(ORACLE_QUERY_REPEAT, ORACLE_DATA_SOURCE, ORACLE_QUERY, QUERY_CALLBACK_GAS);
            validQueryIDs[queryId] = true;
        }
    }

    /// @dev checks our last query price to see if our contract should enter settlement due to it being past our
    //  expiration date or outside of our tradeable ranges.
    function checkSettlement() private {
        if(isSettled)   // already settled.
            return;

        if(now > EXPIRATION) {  // note: miners can cheat this by small increments of time (minutes, not hours)
            isSettled = true;   // time based expiration has occurred.
        } else if(lastPrice >= PRICE_CAP || lastPrice <= PRICE_FLOOR) {
            isSettled = true;   // we have breached/touched our pricing bands
        }

        if(isSettled) {
            settleContract();
        }
    }

    /// @dev records our final settlement price and fires needed events.
    /// @param finalSettlementPrice final query price at time of settlement
    function settleContract(uint finalSettlementPrice) private {
        settlementPrice = finalSettlementPrice;
        ContractSettled(finalSettlementPrice);
        // TODO: return any remaining ether balance to creator of this contract (no longer needs gas for queries)
    }

    /// @dev over estimates needed gas to power queries until expiration and determines if provided contract
    /// contains enough.
    /// @param secondsToExpiration seconds from now that expiration is scheduled.
    /// @returns true if sufficient gas is present to create queries at the designated
    /// frequency from now until expiration
    function checkSufficientStartingBalance(uint secondsToExpiration) private view returns (bool isSufficient) {
        //uint costPerQuery = oraclize_getPrice(ORACLE_DATA_SOURCE); this doesn't work prior to first query(its free)
        uint expectedNoOfQueries = secondsToExpiration / ORACLE_QUERY_REPEAT;
        uint approxGasRequired = COST_PER_QUERY * expectedNoOfQueries;
        return this.balance > (approxGasRequired * 2);
    }
}


Update TokenSellerFactory.sol

Update TokenSellerFactory.sol

pragma solidity ^0.4.4;

// ------------------------------------------------------------------------
// TokenSellerFactory
//
// Decentralised trustless ERC20-partially-compliant token to ETH exchange
// contract on the Ethereum blockchain.
//
// This caters for the Golem Network Token which does not implement the
// transferFrom(...), approve(...) and allowance(...) methods
//
// Enjoy. (c) JonnyLatte, Cintix & BokkyPooBah 2016. The MIT licence.
// ------------------------------------------------------------------------

// https://github.com/ethereum/EIPs/issues/20
contract ERC20Partial {
    function totalSupply() constant returns (uint totalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    // function transferFrom(address _from, address _to, uint _value) returns (bool success);
    // function approve(address _spender, uint _value) returns (bool success);
    // function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    // event Approval(address indexed _owner, address indexed _spender, uint _value);
}

contract Owned {
    address public owner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

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

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

    function transferOwnership(address newOwner) onlyOwner {
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// contract can sell tokens for ETH
// prices are in amount of wei per batch of token units

contract TokenSeller is Owned {

    address public asset;       // address of token
    uint256 public sellPrice;   // contract sells lots of tokens at this price
    uint256 public units;       // lot size (token-wei)

    bool public sellsTokens;    // is contract selling

    event ActivatedEvent(bool sells);
    event AssetWithdrawn(uint256 value);
    event TokenWithdrawn(address token, uint256 value);
    event EtherWithdrawn(uint256 value);
    event AssetBought(address indexed buyer, uint256 amount, uint256 value, uint256 change);

    // Constructor
    function TokenSeller (
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) {
        asset       = _asset;
        sellPrice   = _sellPrice;
        units       = _units;
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // modify trading behavior
    function activate (
        bool _sellsTokens
    ) onlyOwner {
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // allow owner to remove trade token
    function withdrawAsset(uint256 _value) onlyOwner returns (bool ok) {
        AssetWithdrawn(_value);
        return ERC20Partial(asset).transfer(owner, _value);
    }

    // allow owner to remove arbitrary tokens
    // included just in case contract receives wrong token
    function withdrawToken(address _token, uint256 _value) onlyOwner returns (bool ok) {
        TokenWithdrawn(_token, _value);
        return ERC20Partial(_token).transfer(owner, _value);
    }

    // allow owner to remove ETH
    function withdraw(uint256 _value) onlyOwner returns (bool ok) {
        if (this.balance >= _value) {
            EtherWithdrawn(_value);
            return owner.send(_value);
        }
    }

    // user buys token with ETH
    function buy() payable {
        if (sellsTokens || msg.sender == owner) {
            uint order    = msg.value / sellPrice;
            uint can_sell = ERC20Partial(asset).balanceOf(address(this)) / units;
            uint256 change = 0;
            if (order > can_sell) {
                change = msg.value - (can_sell * sellPrice);
                order = can_sell;
                if (!msg.sender.send(change)) throw;
            }
            if (order > 0) {
                if(!ERC20Partial(asset).transfer(msg.sender, order * units)) throw;
            }
            AssetBought(msg.sender, msg.value, order * units, change);
        }
        else if (!msg.sender.send(msg.value)) throw;  // return user funds if the contract is not selling
    }

    // sending ETH to contract sells tokens to user
    function () payable {
        buy();
    }
}

// This contract deploys TokenSeller contracts and logs the event
contract TokenSellerFactory is Owned {

    event TradeListing(address owner, address addr);
    event TokenWithdrawn(address token, uint256 value);

    mapping(address => bool) _verify;

    function verify(address tradeContract) constant returns (
        bool valid,
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) {
        valid = _verify[tradeContract];
        if (valid) {
            TokenSeller t = TokenSeller(tradeContract);
            asset       = t.asset();
            sellPrice   = t.sellPrice();
            units       = t.units();
            sellsTokens = t.sellsTokens();
        }
    }

    function createTradeContract(
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) returns (address) {
        if (_units == 0) throw;            // can't sell zero units
        address trader = new TokenSeller(
            _asset,
            _sellPrice,
            _units,
            _sellsTokens);
        _verify[trader] = true; // record that this factory created the trader
        TokenSeller(trader).transferOwnership(msg.sender); // set the owner to whoever called the function
        TradeListing(msg.sender, trader);
    }

    // allow owner to remove arbitrary tokens
    // included just in case contract receives some tokens
    function withdrawToken(address _token, uint256 _value) onlyOwner returns (bool ok) {
        TokenWithdrawn(_token, _value);
        return ERC20Partial(_token).transfer(owner, _value);
    }

    function () {
        throw;     // Prevents accidental sending of ether to the factory
    }
}

pragma solidity ^0.4.4;

// ------------------------------------------------------------------------
// TokenSellerFactory
//
// Decentralised trustless ERC20-partially-compliant token to ETH exchange
// contract on the Ethereum blockchain.
//
// This caters for the Golem Network Token which does not implement the
// transferFrom(...), approve(...) and allowance(...) methods
//
// Enjoy. (c) JonnyLatte, Cintix & BokkyPooBah 2016. The MIT licence.
// ------------------------------------------------------------------------

// https://github.com/ethereum/EIPs/issues/20
contract ERC20Partial {
    function totalSupply() constant returns (uint totalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    // function transferFrom(address _from, address _to, uint _value) returns (bool success);
    // function approve(address _spender, uint _value) returns (bool success);
    // function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    // event Approval(address indexed _owner, address indexed _spender, uint _value);
}

contract Owned {
    address public owner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

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

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

    function transferOwnership(address newOwner) onlyOwner {
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// contract can sell tokens for ETH
// prices are in amount of wei per batch of token units

contract TokenSeller is Owned {

    address public asset;       // address of token
    uint256 public sellPrice;   // contract sells lots of tokens at this price
    uint256 public units;       // lot size (token-wei)

    bool public sellsTokens;    // is contract selling

    event ActivatedEvent(bool sells);
    event AssetWithdrawn(uint256 value);
    event TokenWithdrawn(address token, uint256 value);
    event EtherWithdrawn(uint256 value);
    event AssetBought(address indexed buyer, uint256 amount, uint256 value, uint256 change);
    event AssetSold(address indexed seller, uint256 amount, uint256 value);

    // Constructor
    function TokenSeller (
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens,
        bool    _buysTokens
    ) {
        asset       = _asset;
        buyPrice    = _buyPrice;
        sellPrice   = _sellPrice;
        units       = _units;
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // modify trading behavior
    function activate (
        bool _sellsTokens
    ) onlyOwner {
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // allow owner to remove trade token
    function withdrawAsset(uint256 _value) onlyOwner returns (bool ok) {
        AssetWithdrawn(_value);
        return ERC20Partial(asset).transfer(owner, _value);
    }

    // allow owner to remove arbitrary tokens
    // included just in case contract receives wrong token
    function withdrawToken(address _token, uint256 _value) onlyOwner returns (bool ok) {
        TokenWithdrawn(_token, _value);
        return ERC20Partial(_token).transfer(owner, _value);
    }

    // allow owner to remove ETH
    function withdraw(uint256 _value) onlyOwner returns (bool ok) {
        if (this.balance >= _value) {
            EtherWithdrawn(_value);
            return owner.send(_value);
        }
    }

    // user buys token with ETH
    function buy() payable {
        if (sellsTokens || msg.sender == owner) {
            uint order    = msg.value / sellPrice;
            uint can_sell = ERC20Partial(asset).balanceOf(address(this)) / units;
            uint256 change = 0;
            if (order > can_sell) {
                change = msg.value - (can_sell * sellPrice);
                order = can_sell;
                if (!msg.sender.send(change)) throw;
            }
            if (order > 0) {
                if(!ERC20Partial(asset).transfer(msg.sender, order * units)) throw;
            }
            AssetBought(msg.sender, msg.value, order * units, change);
        }
        else if (!msg.sender.send(msg.value)) throw;  // return user funds if the contract is not selling
    }

    // sending ETH to contract sells tokens to user
    function () payable {
        buy();
    }
}

// This contract deploys TokenSeller contracts and logs the event
contract TokenSellerFactory is Owned {

    event TradeListing(address owner, address addr);
    event TokenWithdrawn(address token, uint256 value);

    mapping(address => bool) _verify;

    function verify(address tradeContract) constant returns (
        bool valid,
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) {
        valid = _verify[tradeContract];
        if (valid) {
            TokenSeller t = TokenSeller(tradeContract);
            asset       = t.asset();
            sellPrice   = t.sellPrice();
            units       = t.units();
            sellsTokens = t.sellsTokens();
        }
    }

    function createTradeContract(
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) returns (address) {
        if (_units == 0) throw;            // can't sell zero units
        address trader = new TokenSeller(
            _asset,
            _sellPrice,
            _units,
            _sellsTokens);
        _verify[trader] = true; // record that this factory created the trader
        TokenSeller(trader).transferOwnership(msg.sender); // set the owner to whoever called the function
        TradeListing(msg.sender, trader);
    }

    // allow owner to remove arbitrary tokens
    // included just in case contract receives some tokens
    function withdrawToken(address _token, uint256 _value) onlyOwner returns (bool ok) {
        TokenWithdrawn(_token, _value);
        return ERC20Partial(_token).transfer(owner, _value);
    }

    function () {
        throw;     // Prevents accidental sending of ether to the factory
    }
}


Remove all traces of nonce

Remove all traces of nonce

import "CompareOp.sol";

contract Adjudicator {

	bool public frozen = false;
	uint lastTimestamp = 0;
	CompareOp compareOp;
	address owner;
	uint timeout;
	bytes state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(CompareOp _compareOp, address _owner, uint _timeout) {
		compareOp = _compareOp;
		owner = _owner;
		timeout = _timeout;
	}

	function submit(bytes _state)
		external
		onlyOwner
		notFrozen
		returns (bool)
	{
		if (compareOp.isSuperior(state, _state) {
			state = _state;
			return true;
		} else {
			return false;
		}
	}

	function unfreeze() external onlyOwner returns (bool) {
		if (frozen && !CompareOp.isFinal(state)) {
			lastTimestamp = 0;
			frozen = false;
			return true;
		} else {
			return false;
		}
	}

	function finalize() external notFrozen returns (bool) {
		if (CompareOp.isFinal(state) || (lastTimestamp != 0 && now > lastTimestamp + timeout)) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}

contract Adjudicator {

	uint public constant UINT_MAX = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function submit(uint _newNonce, bytes _state)
		external
		onlyOwner
		notFrozen
		returns (bool)
	{
		if (_newNonce > nonce) {
			nonce = _newNonce;
			state = _state;
			return true;
		} else {
			return false;
		}
	}

	function unfreeze() external onlyOwner returns (bool) {
		if (frozen && nonce != UINT_MAX) {
			lastTimestamp = 0;
			frozen = false;
			return true;
		} else {
			return false;
		}
	}

	function finalize() external notFrozen returns (bool) {
		if (nonce == UINT_MAX || (lastTimestamp != 0 && now > lastTimestamp + timeout)) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}


Fix resetSpent.

Fix resetSpent.

// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
// single, or, crucially, each of a number of, designated owners.
// usage:
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
contract multiowned {
	// struct for the status of a pending operation.
	struct PendingState {
		uint yetNeeded;
		uint ownersDone;
	}

	// this contract only has two types of events: it can accept a confirmation, in which case
	// we record owner and operation (hash) alongside it.
	event Confirmation(address owner, hash operation);
	// the other is in the case of an owner changing. here we record the old and new owners.
	event OwnerChanged(address oldOwner, address newOwner);

	// constructor is given number of sigs required to do protected "onlyowners" transactions
	// as well as the selection of addresses capable of confirming them.
	function multiowned(uint _required, address[] _owners) {
		m_required = _required;
		m_owners = _owners;
	}

	// simple single-sig function modifier.
	modifier onlyowner {
		if (m_owners.find(msg.sender) != notfound)
			_
	}

	// multi-sig function modifier: the operation must have an intrinsic hash in order
	// that later attempts can be realised as the same underlying operation and
	// thus count as confirmations.
	modifier onlymanyowners(hash _operation) {
		if (confirm(_operation))
			_
	}

	function confirm(hash _operation) protected returns (bool _r) {
		// determine what index the present sender is:
		uint ownerIndex = m_owners.find(msg.sender);

		// make sure they're an owner
		if (ownerIndex != notfound) {
			// if we're not yet working on this operation, switch over and reset the confirmation status.
			if (!m_pending[_operation].yetNeeded) {
				// reset count of confirmations needed.
				m_pending[_operation].yetNeeded = _sigs.size();
				// reset which owners have confirmed (none) - set our bitmap to 0.
				m_pending[_operation].ownersDone = 0;
			}
			// determine the bit to set for this owner.
			uint ownerIndexBit = 1 << ownerIndex;

			// make sure we (the message sender) haven't confirmed this operation previously.
			assert(m_pending[_operation].yetNeeded > 0);
			if (!(m_pending[_operation].ownersDone & ownerIndexBit)) {
				Confirmation(msg.sender, _operation);
				// ok - check if count is enough to go ahead.
				if (m_pending[_operation].yetNeeded == 1) {
					// enough confirmations: reset and run interior.
					delete m_pending[_operation];
					_r = true;
				}
				else
				{
					// not enough: record that this owner in particular confirmed.
					m_pending[_operation].yetNeeded--;
					m_pending[_operation].ownersDone |= ownerIndexBit;
				}
			}
		}
	}

	// replaces an owner `_from` with another `_to`.
	function changeOwner(address _from, address _to) external multiowned(sha3(msg.sig, _from, _to)) {
		uint ownerIndex = m_owners.find(_from);
		if (ownerIndex != notfound)
		{
			m_owners[ownerIndex] = _to;
			OwnerChanged(_from, _to);
		}
	}

	// the number of owners that must confirm the same operation before it is run.
	uint constant m_required;

	//stateset owners {
	set address[] m_owners;
	// set meaning you can do a fast look up into it to get the index.
	// suggested impl as combination of count-prefixed contiguous series and normal mapping for the reverse lookup:
	// sha3(BASE + 0) => N,
	// sha3(BASE + 1) => address[0],
	// ...
	// sha3(BASE + N) => address[N-1],
	// sha3(BASE ++ address[0]) => 1,
	// ...
	// sha3(BASE ++ address[N-1]) -> N
	//
	// provides:
	// size: m_owners.size()
	// dereference: m_owners[0], ..., m_owners[m_owners.size() - 1]
	// alteration: m_owners[2] = newValue; (original m_owners[2] is removed)
	// find: m_owners.find(m_owners[0]) == 0, ..., m_owners.find(m_owners[m_owners.size() - 1]) == m_owners.size() - 1,  m_owners.find(...) == (uint)-1 == notfound
	// append: m_owners.insert(n): m_owners[m_owners.size() - 1] == n, m_owners.lookup(n) == m_owners.size() - 1
	// delete: delete m_owners[n]
	// clear: m_owners.clear(): m_owners.size() == 0 (or just delete m_owners)
	//}

	/*
	// for now could just be:
	uint m_ownersCount;
	mapping (uint => address) m_owners;
	mapping (address => uint) m_ownersFind;
	*/

	// the ongoing operations.
	mapping { hash => PendingState } m_pending;
}

// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
// uses is specified in the modifier.
contract daylimit is multiowned {
	// constructor - just records the present day's index.
	function daylimit() {
		m_lastDay = today();
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function setDailyLimit(uint _newLimit) external onlyowners(sha3(msg.sig, _newLimit)) {
		m_dailyLimit = _newLimit;
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function resetSpentToday() external onlyowners(sha3(msg.sig)) {
		m_spentToday = 0;
	}

	// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
	// returns true. otherwise just returns false.
	function underLimit(uint _value) protected onlyowner {
		// reset the spend limit if we're on a different day to last time.
		if (today() > m_lastDay) {
			m_spentToday = 0;
			m_lastDay = today();
		}
		// check to see if there's enough left - if so, subtract and return true.
		if (m_spentToday + _value <= m_dailyLimit) {
			m_spendToday += _value;
			return true;
		}
		return false;
	}

	// simple modifier for daily limit.
	modifier limitedDaily(uint _value) {
		if (underLimit(_value))
			_
	}

	// determines today's index.
	function today() private constant returns (uint r) { r = block.timestamp / (60 * 60 * 24); }

	uint m_spentToday;
	uint m_dailyLimit;
	uint m_lastDay;
}

// interface contract for multisig proxy contracts.
contract multisig {
	function changeOwner(address _from, address _to);
	function transact(address _to, uint _value) returns (hash _r);
	function confirm(hash _h);
}

// usage:
// hash h = Wallet(w).from(oneOwner).transact(to, value, data);
// Wallet(w).from(anotherOwner).confirm(h);
contract Wallet is multisig multiowned daylimit {
	// Transaction structure to remember details of transaction lest it need be saved for a later call.
	structure Transaction {
		address to;
		uint value;
		byte[] data;
	}

	// logged events:
	// Funds has arrived into the wallet (record how much).
	event CashIn(uint value);
	// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
	event SingleTransact(indexed string32 = "out", address owner, uint value, address to);
	// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
	event MultiTransact(indexed string32 = "out", address owner, hash operation, uint value, address to);

	// constructor - just pass on the owner arra to the multiowned.
	function Wallet(address[] _owners) multiowned(2, _owners) {}

	// kills the contract sending everything to `_to`.
	function kill(address _to) external onlyowners(sha3("kill", _to)) {
		this.suicide(_to);
	}

	// gets called when no other function matches
	function() {
		// just being sent some cash?
		if (msg.value) {
			CashIn(msg.value);
		}
	}

	// Outside-visible transact entry point. Executes transacion immediately if below daily spend limit.
	// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
	// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
	// and _data arguments). They still get the option of using them if they want, anyways.
	function transact(address _to, uint _value, bytes[] _data) external returns (hash _r) {
		// first, take the opportunity to check that we're under the daily limit.
		if (underLimit(_value)) {
			log SingleTransact(_value, _to);
			// yes - just execute the call.
			_to.call(_value, _data);
			return 0;
		}

		// determine our operation hash.
		_r = sha3("transact", _to, _value, _data);
		if (!confirm(_r) && m_txs[_r].to == 0) {
			m_txs[_r].to = _to;
			m_txs[_r].value = _value;
			m_txs[_r].data = _data;
		}
	}

	// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
	// to determine the body of the transaction from the hash provided.
	function confirm(hash _h) external onlyowners(_h) {
		if (m_txs[_h].to != 0) {
			m_txs[_h].to.call(m_txs[_h].value, m_txs[_h].data);
			MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to);
			delete m_txs[_h];
		}
	}

	// internally confirm transaction with all of the info. returns true iff confirmed good and executed.
	function confirm(hash _h, address _to, uint _value, bytes[] _data) private onlyowners(_h) returns (bool _r) {
		_to.call(_value, _data);
		MultiTransact(msg.sender, _h, _value, _to);
		_r = true;
	}

	// pending transactions we have at present.
	mapping (hash => Transaction) m_txs;
}

// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
// single, or, crucially, each of a number of, designated owners.
// usage:
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
contract multiowned {
	// struct for the status of a pending operation.
	struct PendingState {
		uint yetNeeded;
		uint ownersDone;
	}

	// this contract only has two types of events: it can accept a confirmation, in which case
	// we record owner and operation (hash) alongside it.
	event Confirmation(address owner, hash operation);
	// the other is in the case of an owner changing. here we record the old and new owners.
	event OwnerChanged(address oldOwner, address newOwner);

	// constructor is given number of sigs required to do protected "onlyowners" transactions
	// as well as the selection of addresses capable of confirming them.
	function multiowned(uint _required, address[] _owners) {
		m_required = _required;
		m_owners = _owners;
	}

	// simple single-sig function modifier.
	modifier onlyowner {
		if (m_owners.find(msg.sender) != notfound)
			_
	}

	// multi-sig function modifier: the operation must have an intrinsic hash in order
	// that later attempts can be realised as the same underlying operation and
	// thus count as confirmations.
	modifier onlymanyowners(hash _operation) {
		if (confirm(_operation))
			_
	}

	function confirm(hash _operation) protected returns (bool _r) {
		// determine what index the present sender is:
		uint ownerIndex = m_owners.find(msg.sender);

		// make sure they're an owner
		if (ownerIndex != notfound) {
			// if we're not yet working on this operation, switch over and reset the confirmation status.
			if (!m_pending[_operation].yetNeeded) {
				// reset count of confirmations needed.
				m_pending[_operation].yetNeeded = _sigs.size();
				// reset which owners have confirmed (none) - set our bitmap to 0.
				m_pending[_operation].ownersDone = 0;
			}
			// determine the bit to set for this owner.
			uint ownerIndexBit = 1 << ownerIndex;

			// make sure we (the message sender) haven't confirmed this operation previously.
			assert(m_pending[_operation].yetNeeded > 0);
			if (!(m_pending[_operation].ownersDone & ownerIndexBit)) {
				Confirmation(msg.sender, _operation);
				// ok - check if count is enough to go ahead.
				if (m_pending[_operation].yetNeeded == 1) {
					// enough confirmations: reset and run interior.
					delete m_pending[_operation];
					_r = true;
				}
				else
				{
					// not enough: record that this owner in particular confirmed.
					m_pending[_operation].yetNeeded--;
					m_pending[_operation].ownersDone |= ownerIndexBit;
				}
			}
		}
	}

	// replaces an owner `_from` with another `_to`.
	function changeOwner(address _from, address _to) external multiowned(sha3(msg.sig, _from, _to)) {
		uint ownerIndex = m_owners.find(_from);
		if (ownerIndex != notfound)
		{
			m_owners[ownerIndex] = _to;
			OwnerChanged(_from, _to);
		}
	}

	// the number of owners that must confirm the same operation before it is run.
	uint constant m_required;

	//stateset owners {
	set address[] m_owners;
	// set meaning you can do a fast look up into it to get the index.
	// suggested impl as combination of count-prefixed contiguous series and normal mapping for the reverse lookup:
	// sha3(BASE + 0) => N,
	// sha3(BASE + 1) => address[0],
	// ...
	// sha3(BASE + N) => address[N-1],
	// sha3(BASE ++ address[0]) => 1,
	// ...
	// sha3(BASE ++ address[N-1]) -> N
	//
	// provides:
	// size: m_owners.size()
	// dereference: m_owners[0], ..., m_owners[m_owners.size() - 1]
	// alteration: m_owners[2] = newValue; (original m_owners[2] is removed)
	// find: m_owners.find(m_owners[0]) == 0, ..., m_owners.find(m_owners[m_owners.size() - 1]) == m_owners.size() - 1,  m_owners.find(...) == (uint)-1 == notfound
	// append: m_owners.insert(n): m_owners[m_owners.size() - 1] == n, m_owners.lookup(n) == m_owners.size() - 1
	// delete: delete m_owners[n]
	// clear: m_owners.clear(): m_owners.size() == 0
	//}

	/*
	// for now could just be:
	uint m_ownersCount;
	mapping (uint => address) m_owners;
	mapping (address => uint) m_ownersFind;
	*/

	// the ongoing operations.
	mapping { hash => PendingState } m_pending;
}

// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
// uses is specified in the modifier.
contract daylimit is multiowned {
	// constructor - just records the present day's index.
	function daylimit() {
		m_lastDay = today();
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function setDailyLimit(uint _newLimit) external onlyowners(sha3(msg.sig, _newLimit)) {
		m_dailyLimit = _newLimit;
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function resetSpentToday() external onlyowners(sha3(msg.sig)) {
		m_dailyLimit = _newLimit;
	}

	// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
	// returns true. otherwise just returns false.
	function underLimit(uint _value) protected onlyowner {
		// reset the spend limit if we're on a different day to last time.
		if (today() > m_lastDay) {
			m_spentToday = 0;
			m_lastDay = today();
		}
		// check to see if there's enough left - if so, subtract and return true.
		if (m_spentToday + _value <= m_dailyLimit) {
			m_spendToday += _value;
			return true;
		}
		return false;
	}

	// simple modifier for daily limit.
	modifier limitedDaily(uint _value) {
		if (underLimit(_value))
			_
	}

	// determines today's index.
	function today() private constant returns (uint r) { r = block.timestamp / (60 * 60 * 24); }

	uint m_spentToday;
	uint m_dailyLimit;
	uint m_lastDay;
}

// interface contract for multisig proxy contracts.
contract multisig {
	function changeOwner(address _from, address _to);
	function transact(address _to, uint _value) returns (hash _r);
	function confirm(hash _h);
}

// usage:
// hash h = Wallet(w).from(oneOwner).transact(to, value, data);
// Wallet(w).from(anotherOwner).confirm(h);
contract Wallet is multisig multiowned daylimit {
	// Transaction structure to remember details of transaction lest it need be saved for a later call.
	structure Transaction {
		address to;
		uint value;
		byte[] data;
	}

	// logged events:
	// Funds has arrived into the wallet (record how much).
	event CashIn(uint value);
	// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
	event SingleTransact(indexed string32 = "out", address owner, uint value, address to);
	// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
	event MultiTransact(indexed string32 = "out", address owner, hash operation, uint value, address to);

	// constructor - just pass on the owner arra to the multiowned.
	function Wallet(address[] _owners) multiowned(2, _owners) {}

	// kills the contract sending everything to `_to`.
	function kill(address _to) external onlyowners(sha3("kill", _to)) {
		this.suicide(_to);
	}

	// gets called when no other function matches
	function() {
		// just being sent some cash?
		if (msg.value) {
			CashIn(msg.value);
		}
	}

	// Outside-visible transact entry point. Executes transacion immediately if below daily spend limit.
	// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
	// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
	// and _data arguments). They still get the option of using them if they want, anyways.
	function transact(address _to, uint _value, bytes[] _data) external returns (hash _r) {
		// first, take the opportunity to check that we're under the daily limit.
		if (underLimit(_value)) {
			log SingleTransact(_value, _to);
			// yes - just execute the call.
			_to.call(_value, _data);
			return 0;
		}

		// determine our operation hash.
		_r = sha3("transact", _to, _value, _data);
		if (!confirm(_r) && m_txs[_r].to == 0) {
			m_txs[_r].to = _to;
			m_txs[_r].value = _value;
			m_txs[_r].data = _data;
		}
	}

	// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
	// to determine the body of the transaction from the hash provided.
	function confirm(hash _h) external onlyowners(_h) {
		if (m_txs[_h].to != 0) {
			m_txs[_h].to.call(m_txs[_h].value, m_txs[_h].data);
			MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to);
			delete m_txs[_h];
		}
	}

	// internally confirm transaction with all of the info. returns true iff confirmed good and executed.
	function confirm(hash _h, address _to, uint _value, bytes[] _data) private onlyowners(_h) returns (bool _r) {
		_to.call(_value, _data);
		MultiTransact(msg.sender, _h, _value, _to);
		_r = true;
	}

	// pending transactions we have at present.
	mapping (hash => Transaction) m_txs;
}


Fix _wipeProposals

Fix _wipeProposals

contract root {
    // PoC-8

    uint public currentVersion;
    mapping (uint => address) public api;
    mapping (address => address) public owners;
    address _ownersTail;
    uint _numOwners;
    uint public quorum;
    uint8 public quorumPercent;
    uint public marginForVictory;
    uint8 public marginForVictoryPercent;
    mapping (address => ProposalCollection) public proposals;

    enum ProposalType {
        AddOwner, RemoveOwner,
        SetQuorumPercent, SetMarginForVictoryPercent,
        SetContract, SetVersion, SetApi, WipeProposals,
        Spend
    }

    enum Vote {
        Null, Yes, No, Abstain
    }

    struct ProposalCollection {
        mapping (uint => Proposal) proposals;
        mapping (uint => uint) timestamps;
        uint timestampsTail;
        uint8 numProposals;
    }

    struct Proposal {
        mapping (address => Vote) votes;
        uint numVotes;
        ProposalType type;
        address targetAddress;
        string32 targetFunction;
        address proposedContract;
        uint8 proposedPercent;
        uint value;
    }

    function root() {
        quorum = 1;
        quorumPercent = 60;
        marginForVictory = 0;
        owners[msg.sender] = msg.sender;
        _ownersTail = msg.sender;
    }

    function withdrawProposal(uint timestamp) {
        _removeProposal(msg.sender, timestamp);
    }

    function addOwner(address proposedOwner) {
        _createProposal(msg.sender, ProposalType.AddOwner);
        proposals[msg.sender].proposals[block.timestamp].targetAddress = proposedOwner;
    }

    function removeOwner(address proposedOwner) {
        _createProposal(msg.sender, ProposalType.RemoveOwner);
        proposals[msg.sender].proposals[block.timestamp].targetAddress = proposedOwner;
    }

    function setQuorumPercent(uint8 proposedQuorum) {
        _createProposal(msg.sender, ProposalType.SetQuorumPercent);
        proposals[msg.sender].proposals[block.timestamp].proposedPercent = proposedQuorum;
    }

    function setMarginForVictoryPercent(uint8 proposedMargin) {
        _createProposal(msg.sender, ProposalType.SetMarginForVictoryPercent);
        proposals[msg.sender].proposals[block.timestamp].proposedPercent = proposedMargin;
    }

    function setContract(address targetContract, string32 targetFunction, address proposedContract) {
        _createProposal(msg.sender, ProposalType.SetContract);
        var proposal = proposals[msg.sender].proposals[block.timestamp];
        proposal.targetAddress = targetContract;
        proposal.targetFunction = targetFunction;
        proposal.proposedContract = proposedContract;
    }

    function setVersion(uint version) {
        _createProposal(msg.sender, ProposalType.SetVersion);
        proposals[msg.sender].proposals[block.timestamp].value = version;
    }

    function setApi(uint version, address proposedApi) {
        _createProposal(msg.sender, ProposalType.SetVersion);
        var proposal = proposals[msg.sender].proposals[block.timestamp];
        proposal.value = version;
        proposal.proposedContract = proposedApi;
    }

    function wipeProposals() {
        _createProposal(msg.sender, ProposalType.WipeProposals);
    }

    function vote(address owner, uint timestamp, Vote vote) {
        if (proposals[owner].numProposals == 0 || proposals[owner].timestamps[timestamp] == 0) return;

        proposals[owner].proposals[timestamp].votes[msg.sender] = vote;
        proposals[owner].proposals[timestamp].numVotes += 1;

        _checkVotes(owner, timestamp);
    }

    function execute(address owner, uint timestamp) {
        if (proposals[owner].numProposals == 0 || proposals[owner].timestamps[timestamp] == 0) return;
        _checkVotes(owner, timestamp);
    }

    function _removeProposal(address owner, uint timestamp) private {
        var collection = proposals[owner];
        if (collection.numProposals == 0 || collection.timestamps[timestamp] == 0) return;

        uint iter = timestamp;
        for (uint8 i=0; i < collection.numProposals-1; i += 1) {
            iter = collection.timestamps[iter];
        }
        collection.timestamps[iter] = collection.timestamps[timestamp];

        delete collection.proposals[timestamp];
        collection.numProposals -= 1;
    }

    function _addOwner(address owner) private {
        owners[owner] = owners[_ownersTail];
        owners[_ownersTail] = owner;
        _ownersTail = owner;
        _numOwners += 1;
        proposals[owner].numProposals = 0;

        _updateMargins();
    }

    function _removeOwner(address owner) private {
        if (owners[owner] == address(0)) return;

        uint timestamp;
        address iter = owner;

        for (uint i=0; i < _numOwners-1; i+=1) {
            iter = owners[iter];

            var collection = proposals[iter];

            if (collection.numProposals == 0) continue;

            timestamp = collection.timestampsTail;

            for (uint8 j=0; j < collection.numProposals; j+=1) {
                if (collection.proposals[timestamp].votes[owner] != Vote.Null) {
                    delete collection.proposals[timestamp].votes[owner];
                    collection.proposals[timestamp].numVotes -= 1;
                }
                timestamp = collection.timestamps[timestamp];
            }
        }

        owners[iter] = owners[owner];
        delete owners[owner];
        delete proposals[owner];
        _numOwners -= 1;

        _updateMargins();
    }

    function _setQuorumPercent(uint8 percent) private {
        quorumPercent = percent;
        _updateMargins();
    }

    function _setMarginForVictoryPercent(uint8 percent) private {
        marginForVictoryPercent = percent;
        _updateMargins();
    }

    function _setContract(address targetContract, string32 targetFunction, address newContract) private {
        targetContract.call(string4(string32(sha3("setFunction(string32, address)"))), targetFunction, newContract);
    }

    function _setVersion(uint version) private {
        currentVersion = version;
    }

    function _setApi(uint version, address proposedApi) private {
        api[version] = proposedApi;
    }

    function _wipeProposals() private {
        address iter = _ownersTail;
        for (uint i=0; i < _numOwners; i += 1) {
            delete proposals[iter];
            iter = owners[iter];
        }
    }

    function _spend(address recipient, uint amount) private {
        recipient.send(amount);
    }

    function _updateMargins() private {
        quorum = (_numOwners * 100) / quorumPercent;
        marginForVictory = (_numOwners * 100) / marginForVictoryPercent;
    }

    function _createProposal(address owner, ProposalType type) internal {
        var collection = proposals[owner];

        if (collection.numProposals == 0) {
            collection.timestampsTail = block.timestamp;
            collection.timestamps[block.timestamp] = block.timestamp;

        } else {
            collection.timestamps[block.timestamp] = collection.timestamps[collection.timestampsTail];
            collection.timestamps[collection.timestampsTail] = block.timestamp;
            collection.timestampsTail = block.timestamp;
        }
        collection.numProposals += 1;

        var proposal = collection.proposals[block.timestamp];
        proposal.type = type;
        proposal.numVotes = 1;
        proposal.votes[owner] = Vote.Yes;
    }

    function _checkVotes(address owner, uint timestamp) private {
        var proposal = proposals[owner].proposals[timestamp];

        if (proposal.numVotes < quorum) return;

        uint yesTally = 0;
        uint noTally = 0;
        address iter = _ownersTail;

        for (uint i=0; i < _numOwners; i+=1) {
            if (proposal.votes[iter] == Vote.Abstain || proposal.votes[iter] == Vote.Null) {
                 continue;
            }

            if (proposal.votes[iter] == Vote.Yes) {
                yesTally += 1;
            } else {
                noTally -= 1;
            }
        }

        if (yesTally > noTally && (yesTally - noTally) >= marginForVictory) {
            _execute(owner, timestamp);
        } else if (noTally > yesTally && (noTally - yesTally) >= marginForVictory) {
            _removeProposal(owner, timestamp);
        }
    }

    function _execute(address owner, uint timestamp) private {
        var proposal = proposals[owner].proposals[timestamp];

        if (proposal.type == ProposalType.AddOwner) {
            _addOwner(proposal.targetAddress);

        } else if (proposal.type == ProposalType.RemoveOwner) {
            _removeOwner(proposal.targetAddress);

        } else if (proposal.type == ProposalType.SetQuorumPercent) {
            _setQuorumPercent(proposal.proposedPercent);

        } else if (proposal.type == ProposalType.SetMarginForVictoryPercent) {
            _setQuorumPercent(proposal.proposedPercent);

        } else if (proposal.type == ProposalType.SetContract) {
            _setContract(proposal.targetAddress, proposal.targetFunction,
                              proposal.proposedContract);

        } else if (proposal.type == ProposalType.SetVersion) {
            _setVersion(proposal.value);

        } else if (proposal.type == ProposalType.SetApi) {
            _setApi(proposal.value, proposal.proposedContract);

        } else if (proposal.type == ProposalType.WipeProposals) {
            _wipeProposals();

        } else if (proposal.type == ProposalType.Spend) {
            _spend(proposal.targetAddress, proposal.value);
        }
        _removeProposal(owner, timestamp);
    }
}

contract root {
    // PoC-8

    uint public currentVersion;
    mapping (uint => address) public api;
    mapping (address => address) public owners;
    address _ownersTail;
    uint _numOwners;
    uint public quorum;
    uint8 public quorumPercent;
    uint public marginForVictory;
    uint8 public marginForVictoryPercent;
    mapping (address => ProposalCollection) public proposals;

    enum ProposalType {
        AddOwner, RemoveOwner,
        SetQuorumPercent, SetMarginForVictoryPercent,
        SetContract, SetVersion, SetApi, WipeProposals,
        Spend
    }

    enum Vote {
        Null, Yes, No, Abstain
    }

    struct ProposalCollection {
        mapping (uint => Proposal) proposals;
        mapping (uint => uint) timestamps;
        uint timestampsTail;
        uint8 numProposals;
    }

    struct Proposal {
        mapping (address => Vote) votes;
        uint numVotes;
        ProposalType type;
        address targetAddress;
        string32 targetFunction;
        address proposedContract;
        uint8 proposedPercent;
        uint value;
    }

    function root() {
        quorum = 1;
        quorumPercent = 60;
        marginForVictory = 0;
        owners[msg.sender] = msg.sender;
        _ownersTail = msg.sender;
    }

    function withdrawProposal(uint timestamp) {
        _removeProposal(msg.sender, timestamp);
    }

    function addOwner(address proposedOwner) {
        _createProposal(msg.sender, ProposalType.AddOwner);
        proposals[msg.sender].proposals[block.timestamp].targetAddress = proposedOwner;
    }

    function removeOwner(address proposedOwner) {
        _createProposal(msg.sender, ProposalType.RemoveOwner);
        proposals[msg.sender].proposals[block.timestamp].targetAddress = proposedOwner;
    }

    function setQuorumPercent(uint8 proposedQuorum) {
        _createProposal(msg.sender, ProposalType.SetQuorumPercent);
        proposals[msg.sender].proposals[block.timestamp].proposedPercent = proposedQuorum;
    }

    function setMarginForVictoryPercent(uint8 proposedMargin) {
        _createProposal(msg.sender, ProposalType.SetMarginForVictoryPercent);
        proposals[msg.sender].proposals[block.timestamp].proposedPercent = proposedMargin;
    }

    function setContract(address targetContract, string32 targetFunction, address proposedContract) {
        _createProposal(msg.sender, ProposalType.SetContract);
        var proposal = proposals[msg.sender].proposals[block.timestamp];
        proposal.targetAddress = targetContract;
        proposal.targetFunction = targetFunction;
        proposal.proposedContract = proposedContract;
    }

    function setVersion(uint version) {
        _createProposal(msg.sender, ProposalType.SetVersion);
        proposals[msg.sender].proposals[block.timestamp].value = version;
    }

    function setApi(uint version, address proposedApi) {
        _createProposal(msg.sender, ProposalType.SetVersion);
        var proposal = proposals[msg.sender].proposals[block.timestamp];
        proposal.value = version;
        proposal.proposedContract = proposedApi;
    }

    function wipeProposals() {
        _createProposal(msg.sender, ProposalType.WipeProposals);
    }

    function vote(address owner, uint timestamp, Vote vote) {
        if (proposals[owner].numProposals == 0 || proposals[owner].timestamps[timestamp] == 0) return;

        proposals[owner].proposals[timestamp].votes[msg.sender] = vote;
        proposals[owner].proposals[timestamp].numVotes += 1;

        _checkVotes(owner, timestamp);
    }

    function execute(address owner, uint timestamp) {
        if (proposals[owner].numProposals == 0 || proposals[owner].timestamps[timestamp] == 0) return;
        _checkVotes(owner, timestamp);
    }

    function _removeProposal(address owner, uint timestamp) private {
        var collection = proposals[owner];
        if (collection.numProposals == 0 || collection.timestamps[timestamp] == 0) return;

        uint iter = timestamp;
        for (uint8 i=0; i < collection.numProposals-1; i += 1) {
            iter = collection.timestamps[iter];
        }
        collection.timestamps[iter] = collection.timestamps[timestamp];

        delete collection.proposals[timestamp];
        collection.numProposals -= 1;
    }

    function _addOwner(address owner) private {
        owners[owner] = owners[_ownersTail];
        owners[_ownersTail] = owner;
        _ownersTail = owner;
        _numOwners += 1;
        proposals[owner].numProposals = 0;

        _updateMargins();
    }

    function _removeOwner(address owner) private {
        if (owners[owner] == address(0)) return;

        uint timestamp;
        address iter = owner;

        for (uint i=0; i < _numOwners-1; i+=1) {
            iter = owners[iter];

            var collection = proposals[iter];

            if (collection.numProposals == 0) continue;

            timestamp = collection.timestampsTail;

            for (uint8 j=0; j < collection.numProposals; j+=1) {
                if (collection.proposals[timestamp].votes[owner] != Vote.Null) {
                    delete collection.proposals[timestamp].votes[owner];
                    collection.proposals[timestamp].numVotes -= 1;
                }
                timestamp = collection.timestamps[timestamp];
            }
        }

        owners[iter] = owners[owner];
        delete owners[owner];
        delete proposals[owner];
        _numOwners -= 1;

        _updateMargins();
    }

    function _setQuorumPercent(uint8 percent) private {
        quorumPercent = percent;
        _updateMargins();
    }

    function _setMarginForVictoryPercent(uint8 percent) private {
        marginForVictoryPercent = percent;
        _updateMargins();
    }

    function _setContract(address targetContract, string32 targetFunction, address newContract) private {
        targetContract.call(string4(string32(sha3("setFunction(string32, address)"))), targetFunction, newContract);
    }

    function _setVersion(uint version) private {
        currentVersion = version;
    }

    function _setApi(uint version, address proposedApi) private {
        api[version] = proposedApi;
    }

    function _wipeProposals() private {
        address iter = _ownersTail;
        for (uint i=0; i < _numOwners; i += 1) {
            delete proposals[iter];
        }
        iter = owners[iter];
    }

    function _spend(address recipient, uint amount) private {
        recipient.send(amount);
    }

    function _updateMargins() private {
        quorum = (_numOwners * 100) / quorumPercent;
        marginForVictory = (_numOwners * 100) / marginForVictoryPercent;
    }

    function _createProposal(address owner, ProposalType type) internal {
        var collection = proposals[owner];

        if (collection.numProposals == 0) {
            collection.timestampsTail = block.timestamp;
            collection.timestamps[block.timestamp] = block.timestamp;

        } else {
            collection.timestamps[block.timestamp] = collection.timestamps[collection.timestampsTail];
            collection.timestamps[collection.timestampsTail] = block.timestamp;
            collection.timestampsTail = block.timestamp;
        }
        collection.numProposals += 1;

        var proposal = collection.proposals[block.timestamp];
        proposal.type = type;
        proposal.numVotes = 1;
        proposal.votes[owner] = Vote.Yes;
    }

    function _checkVotes(address owner, uint timestamp) private {
        var proposal = proposals[owner].proposals[timestamp];

        if (proposal.numVotes < quorum) return;

        uint yesTally = 0;
        uint noTally = 0;
        address iter = _ownersTail;

        for (uint i=0; i < _numOwners; i+=1) {
            if (proposal.votes[iter] == Vote.Abstain || proposal.votes[iter] == Vote.Null) {
                 continue;
            }

            if (proposal.votes[iter] == Vote.Yes) {
                yesTally += 1;
            } else {
                noTally -= 1;
            }
        }

        if (yesTally > noTally && (yesTally - noTally) >= marginForVictory) {
            _execute(owner, timestamp);
        } else if (noTally > yesTally && (noTally - yesTally) >= marginForVictory) {
            _removeProposal(owner, timestamp);
        }
    }

    function _execute(address owner, uint timestamp) private {
        var proposal = proposals[owner].proposals[timestamp];

        if (proposal.type == ProposalType.AddOwner) {
            _addOwner(proposal.targetAddress);

        } else if (proposal.type == ProposalType.RemoveOwner) {
            _removeOwner(proposal.targetAddress);

        } else if (proposal.type == ProposalType.SetQuorumPercent) {
            _setQuorumPercent(proposal.proposedPercent);

        } else if (proposal.type == ProposalType.SetMarginForVictoryPercent) {
            _setQuorumPercent(proposal.proposedPercent);

        } else if (proposal.type == ProposalType.SetContract) {
            _setContract(proposal.targetAddress, proposal.targetFunction,
                              proposal.proposedContract);

        } else if (proposal.type == ProposalType.SetVersion) {
            _setVersion(proposal.value);

        } else if (proposal.type == ProposalType.SetApi) {
            _setApi(proposal.value, proposal.proposedContract);

        } else if (proposal.type == ProposalType.WipeProposals) {
            _wipeProposals();

        } else if (proposal.type == ProposalType.Spend) {
            _spend(proposal.targetAddress, proposal.value);
        }
        _removeProposal(owner, timestamp);
    }
}