Update to preferred citation formation for ERC-721

pragma solidity ^0.5.2;

import "../../introspection/IERC165.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) public view returns (uint256 balance);
    function ownerOf(uint256 tokenId) public view returns (address owner);

    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);

    function transferFrom(address from, address to, uint256 tokenId) public;
    function safeTransferFrom(address from, address to, uint256 tokenId) public;

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}

pragma solidity ^0.5.2;

import "../../introspection/IERC165.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) public view returns (uint256 balance);
    function ownerOf(uint256 tokenId) public view returns (address owner);

    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);

    function transferFrom(address from, address to, uint256 tokenId) public;
    function safeTransferFrom(address from, address to, uint256 tokenId) public;

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}


Whoops. `truffle init` was broken!

Whoops. `truffle init` was broken!

import "./ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	event Transfer(address indexed _from, address indexed _to, uint256 _value);

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		Transfer(msg.sender, receiver, amount);
		return true;
	}

	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}

	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
}

import "ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	event Transfer(address indexed _from, address indexed _to, uint256 _value);

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		Transfer(msg.sender, receiver, amount);
		return true;
	}

	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}

	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
}


remove deprecated Linkable modifier

remove deprecated Linkable modifier


Add import for Ownable

Add import for Ownable

pragma solidity ^0.4.4;
import './Ownable.sol';

contract Migrations is Ownable {
  uint public lastCompletedMigration;

  function setCompleted(uint completed) onlyOwner {
    lastCompletedMigration = completed;
  }

  function upgrade(address newAddress) onlyOwner {
    Migrations upgraded = Migrations(newAddress);
    upgraded.setCompleted(lastCompletedMigration);
  }
}

pragma solidity ^0.4.4;
contract Migrations is Ownable {
  uint public lastCompletedMigration;

  function setCompleted(uint completed) onlyOwner {
    lastCompletedMigration = completed;
  }

  function upgrade(address newAddress) onlyOwner {
    Migrations upgraded = Migrations(newAddress);
    upgraded.setCompleted(lastCompletedMigration);
  }
}


Update functions

Update functions

pragma solidity ^0.4.8;

contract AbstractArbiter {
  function enableService();

  function disableService();

  function requestComputation(string _input1, string _input2, uint _operation, uint _numVerifiers);

  function executeComputation() payable;

  function receiveResults(string _result, address _origin);

  function compareResults() returns (uint);

  function requestIndex();

  function receiveIndex(uint _index1, uint _index2, uint _operation, address _origin, bool _end);

}

pragma solidity ^0.4.8;

contract Arbiter {
  function enableService();

  function disableService();

  function requestComputation(string _input1, string _input2, uint _operation);

  function executeComputation(uint _numVerifiers) payable;

  function rand(uint min, uint max) constant returns (uint256);

  function __callback();
}


Adds Eris contract implementation of DoublyLinkedList

/*
 * Third-party implementation by Eris Ltd.
 * src:
 */

/* TODO index on `address` type? */
contract DoublyLinkedList {

  struct Element {
    address previous;
    address next;

    bytes32 data;
  }

  // Make these public.
  uint public size;
  address public tail;
  address public head;
  mapping(address => Element) elements;

  function getData(address key) returns (bytes32){
    return elements[key].data;
  }

  function getElement(address key) private constant returns (Element){
      return elements[key];
  }

  function addElement(address key, bytes32 data) returns (bool){
    Element elem = elements[key];
    // Check that the key is not already taken. We have no null-check for structs atm., so
    // we need to check the fields inside the structs to verify. This works if the field we
    // check is not allowed to be null (which would be 0 or 0x0 in the case of addresses).
    if(elem.data != ""){
      return false;
    }

    elem.data = data;

      // Two cases - empty or not.
      if(size == 0){
        tail = key;
        head = key;
      } else {
        // Link
        elements[head].next = key;
        elem.previous = head;
        // Set this element as the new head.
        head = key;
      }
      // Regardless of case, increase the size of the list by one.
      size++;
       return true;
  }

    function removeElement(address key) returns (bool result) {

       Element elem = elements[key];

      // If no element - return false. Nothing to remove.
      if(elem.data == ""){
        return false;
      }

    // If this is the only element.
      if(size == 1){
        tail = 0x0;
        head = 0x0;
      // If this is the head.
      } else if (key == head){
        // Set this ones 'previous' to be the new head, then change its
        // next to be null (used to be this one).
        head = elem.previous;
        elements[head].next = 0x0;
      // If this one is the tail.
      } else if(key == tail){
        tail = elem.next;
        elements[tail].previous = 0x0;
      // Now it's a bit tougher. Getting here means the list has at least 3 elements,
      // and this element must have both a 'previous' and a 'next'.
      } else {
        address prevElem = elem.previous;
        address nextElem = elem.next;
        elements[prevElem].next = nextElem;
        elements[nextElem].previous = prevElem;
      }
      // Regardless of case, we will decrease the list size by 1, and delete the actual entry.
      size--;
      delete elements[key];
      return true;
    }

}

error: pathspec 'eris/chain/LinkedList.sol' did not match any file(s) known to git


Commented TicTacToeLockedState.sol

Commented TicTacToeLockedState.sol

import "LockedStateWithFunds.sol";

/**
 * TicTacToeLockedState
 *
 * The LockedState for a TicTacToe game.
 */
contract TicTacToeLockedState is LockedStateWithFunds {

    // byte mappings for state
    // 0-19 address1, the recipient of send1
    // 20-39 address2, the recipient of send2
    // 40-71 send1, amount of wei to send to address1
    // 72-104 send2, amount of wei to send to address2

    /**
     * Parses and returns a 4-tuple representing the address1, address2, send1, send2
     * corresponding to the state.
     *
     * state: the state to be parsed
     * returns: a 4-tuple, (address address1, address address2, uint send1, uint send2)
     */
    function parseState(bytes state)
        constant returns (address address1, address address2, uint send1, uint send2)
    {
        uint i;
        uint160 uintAddress1 = 0;
        uint160 uintAddress2 = 0;

        for (i = 0; i < 20; i++) {
            uintAddress1 |= uint8(state[i]) * uint160(2**(i*8));
        }
        address1 = uintAddress1;

        for (i = 0; i < 20; i++) {
            uintAddress2 |= uint8(state[i+20]) * uint160(2**(i*8));
        }
        address2 = uintAddress2;

        for (i = 0; i < 32; i++) {
            send1 |= uint8(state[i+40]) * 2**(i*8);
        }

        for (i = 0; i < 32; i++) {
            send2 |= uint8(state[i+72]) * 2**(i*8);
        }
    }

    /**
     * Checks if a given state is valid.
     * send1 + send2 must be equal to the balance of address1 + the balance of address2
     *
     * state: the state to check
     * returns: true if the state is valid, otherwise false
     */
    function checkState(bytes state) constant returns (bool) {
        address address1;
        address address2;
        uint send1;
        uint send2;

        (address1, address2, send1, send2) = parseState(state);
        return send1 + send2 == getBalance(address1) + getBalance(address2);
    }

    /**
     * Sends the amount of funds to each address, as allotted.
     *
     * state: the state that will be broadcast
     * returns: true if transaction sent sucessfully, otherwise false
     */
    function broadcastState(bytes state) external onlyOwner returns (bool) {
        if (!checkState(state)) {
            return false;
        }

        address address1;
        address address2;
        uint send1;
        uint send2;

        (address1, address2, send1, send2) = parseState(state);

        if (!address1.send(send1)) {
            throw;
        }

        if (!address2.send(send2)) {
            throw;
        }

        return true;
    }
}

import "LockedStateWithFunds.sol";

contract TicTacToeLockedState is LockedStateWithFunds {

    // byte mappings for state
    // 0-19 address1
    // 20-39 address2
    // 40-71 send1
    // 72-104 send2

    function parseState(bytes state)
        constant returns (address address1, address address2, uint send1, uint send2)
    {
        uint i;
        uint160 uintAddress1 = 0;
        uint160 uintAddress2 = 0;

        for (i = 0; i < 20; i++) {
            uintAddress1 |= uint8(state[i]) * uint160(2**(i*8));
        }
        address1 = uintAddress1;

        for (i = 0; i < 20; i++) {
            uintAddress2 |= uint8(state[i+20]) * uint160(2**(i*8));
        }
        address2 = uintAddress2;

        for (i = 0; i < 32; i++) {
            send1 |= uint8(state[i+40]) * 2**(i*8);
        }

        for (i = 0; i < 32; i++) {
            send2 |= uint8(state[i+72]) * 2**(i*8);
        }
    }

    function checkState(bytes state) constant returns (bool) {
        address address1;
        address address2;
        uint send1;
        uint send2;

        (address1, address2, send1, send2) = parseState(state);
        return send1 + send2 == getBalance(address1) + getBalance(address2);
    }

    function broadcastState(bytes state) external onlyOwner returns (bool) {
        if (!checkState(state)) {
            return false;
        }

        address address1;
        address address2;
        uint send1;
        uint send2;

        (address1, address2, send1, send2) = parseState(state);

        if (!address1.send(send1)) {
            throw;
        }

        if (!address2.send(send2)) {
            throw;
        }

        return true;
    }
}


Finish interactive protocol.

Finish interactive protocol.

/// This contract can be used (with some small additions to create an economic
/// incentive for the claimant to answer) to claim computation results for
/// scrypt (actually only the part where we do not have precompiled contracts)
/// and interactively convict a false claim.
/// Scrypt first applies a certain hash function to the input in 1024 iterations.
/// Then it applies the hash function another 1024 times but looks up an
/// additional input in the table of the first 1024 values where the look
/// up index depends on the first input.
/// Formally: Assume that H computes the salsa8 hash function as defined below.
/// If value[0] is the input and value[2048] is the output, we have the following
/// relation:
/// value[i] = H(value[i-1]) for 0 < i <= 1024
/// value[i] = H(value[i-1] ^ value[value[i-1] % 1024]) for 1024 < i <= 2048
/// Strictly, not the lowermost byte in value[i-1] is used for addressing,
/// but that does not matter here.
///
/// In this contract, a challenger can ask for each of the value[i]. If the
/// claimant was wrong and the challenger asks in a clever way, she can
/// force the claimant to commit to values for a certain step that do not
/// match the computation done in the actual step.
///
/// The strategy is as follows:
/// We start with a binary search for a point where value[i] is correct but
/// value[i+1] is incorrect (if the response is correct we go up, if it is
/// incorrect we go down).
/// If i <= 1024, the challenger can directly call convict because
/// the commited values do not match the computation.
/// If this ends up at a point i > 1024 it is more complicated because of
/// the second auxiliary input. The challenger has to compute the index
/// of the auxiliary input (value[i] % 1024) and query that. If it is correct,
/// we can again call convict because the output will not match the committed
/// value. If the auxiliary input value is incorrect, it might be that the
/// computation still matches. In this case, we cannot directly call convict
/// but we found an incorrect value at an index smaller than i. This means
/// that we can continue our binary search inside the first half and
/// will end up at a point i' <= 1024 where we can directyl call convict.
///
/// Overall, this should take not more than 22 rounds. Each round costs approximately
/// 100000 gas and a call to convict is about 60000 gas.
/// This means in total, convicting a false claim should not cost more than
/// around two million gas.
/// Of course, as usual, having to convict a false claimant is only a matter
/// of last resort, because every claimant knows that a false claim can be
/// detected and if this is connected with deposits from both sides that
/// go to the winning party, a false claim will probably not be attempted.
///
/// Disclaimer: This has not been tested and is only meant as a proof of concept
/// and a way to compute the gas costs.
contract Scrypt {
    address claimant;
    address challenger;

    function Scrypt(uint[4] _input, uint[4] _output) {
        claimant = msg.sender;
        queries.length = 2;
        queries.push(0);
        queries.push(2048);
        values.push(_input);
        values.push(_output);
    }
    event Convicted();

    modifier onlyClaimant() { if (msg.sender != claimant) throw; _ }
    modifier onlyChallenger() {
        if (challenger == 0) challenger = msg.sender;
        else if (msg.sender != challenger) throw;
        _
    }

    uint16[] public queries;
    /// Challenger queries claimant for the value on a wire `_i`.
    /// Value 0 is the input, value 1024 is the first input to the second
    /// half of the computation, value 2048 is the output.
    function query(uint16 _i) onlyChallenger {
        if (_i > 2048) throw;
        queries.push(_i);
    }

    uint[4][] public values;
    /// Claimant responds to challenge, committing to a value.
    function respond(uint[4] _value) onlyClaimant {
        if (values.length >= queries.length) throw;
        values.push(_value);
    }

    /// Convicts the claimant to have provided inputs and outputs for a single
    /// step that do not match the computation of the step.
    /// q1, q2 and q3 are query indices providing the relevant values.
    /// q1 is the query index of the first input, q2 the query index of
    /// the output and q2 is the query index of the auxiliary input only
    /// used in the second half of the scrypt computation.
    function convict(uint q1, uint q2, uint q3) {
        var i = queries[q1];
        if (queries[q2] != i + 1) throw;
        var input = values[q1];
        var output = values[q2];
        if (i < 1024) {
            if (!verifyFirstHalf(input, output))
                Convicted();
        } else {
            var auxIndex = queries[q3];
            if (auxIndex != (input[2] / 0x100000000000000000000000000000000000000000000000000000000) % 1024)
                throw;
            var auxInput = values[q3];
            if (!verifySecondHalf(input, auxInput, output))
                Convicted();
        }
    }

    /// Verifies a salsa step in the first half of the scrypt computation.
    function verifyFirstHalf(uint[4] input, uint[4] output) constant returns (bool) {
        var (a, b, c, d) = Salsa8.round(input[0], input[1], input[2], input[3]);
        return (a == output[0] && b == output[1] && c == output[2] && d == output[3]);
    }
    /// Verifies a salsa step in the second half of the scrypt computation.
    function verifySecondHalf(uint[4] input, uint[4] vinput, uint[4] output) constant returns (bool) {
        input[0] ^= vinput[0];
        input[1] ^= vinput[1];
        input[2] ^= vinput[2];
        input[3] ^= vinput[3];
        return verifyFirstHalf(input, output);
    }

}

library Salsa8 {
    uint constant m0 = 0x100000000000000000000000000000000000000000000000000000000;
    uint constant m1 = 0x1000000000000000000000000000000000000000000000000;
    uint constant m2 = 0x10000000000000000000000000000000000000000;
    uint constant m3 = 0x100000000000000000000000000000000;
    uint constant m4 = 0x1000000000000000000000000;
    uint constant m5 = 0x10000000000000000;
    uint constant m6 = 0x100000000;
    uint constant m7 = 0x1;
    function quarter(uint32 y0, uint32 y1, uint32 y2, uint32 y3)
        internal returns (uint32, uint32, uint32, uint32)
    {
        uint32 t;
        t = y0 + y3;
        y1 = y1 ^ ((t * 2**7) | (t / 2**(32-7)));
        t = y1 + y0;
        y2 = y2 ^ ((t * 2**9) | (t / 2**(32-9)));
        t = y2 + y1;
        y3 = y3 ^ ((t * 2**13) | (t / 2**(32-13)));
        t = y3 + y2;
        y0 = y0 ^ ((t * 2**18) | (t / 2**(32-18)));
        return (y0, y1, y2, y3);
    }
    function get(uint data, uint word) internal returns (uint32 x)
    {
        return uint32(data / 2**(256 - word * 32 - 32));
    }
    function put(uint x, uint word) internal returns (uint) {
        return x * 2**(256 - word * 32 - 32);
    }
    function rowround(uint first, uint second) internal returns (uint f, uint s)
    {
        var (a,b,c,d) = quarter(uint32(first / m0), uint32(first / m1), uint32(first / m2), uint32(first / m3));
        f = (((((uint(a) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (b,c,d,a) = quarter(uint32(first / m5), uint32(first / m6), uint32(first / m7), uint32(first / m4));
        f = (((((((f * 2**32) | uint(a)) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (c,d,a,b) = quarter(uint32(second / m2), uint32(second / m3), uint32(second / m0), uint32(second / m1));
        s = (((((uint(a) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (d,a,b,c) = quarter(uint32(second / m7), uint32(second / m4), uint32(second / m5), uint32(second / m6));
        s = (((((((s * 2**32) | uint(a)) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
    }
    function columnround(uint first, uint second) internal returns (uint f, uint s)
    {
        var (a,b,c,d) = quarter(uint32(first / m0), uint32(first / m4), uint32(second / m0), uint32(second / m4));
        f = (uint(a) * m0) | (uint(b) * m4);
        s = (uint(c) * m0) | (uint(d) * m4);
        (a,b,c,d) = quarter(uint32(first / m5), uint32(second / m1), uint32(second / m5), uint32(first / m1));
        f |= (uint(a) * m5) | (uint(d) * m1);
        s |= (uint(b) * m1) | (uint(c) * m5);
        (a,b,c,d) = quarter(uint32(second / m2), uint32(second / m6), uint32(first / m2), uint32(first / m6));
        f |= (uint(c) * m2) | (uint(d) * m6);
        s |= (uint(a) * m2) | (uint(b) * m6);
        (a,b,c,d) = quarter(uint32(second / m7), uint32(first / m3), uint32(first / m7), uint32(second / m3));
        f |= (uint(b) * m3) | (uint(c) * m7);
        s |= (uint(a) * m7) | (uint(d) * m3);
    }
    function salsa20_8(uint _first, uint _second) internal returns (uint rfirst, uint rsecond) {
        uint first = _first;
        uint second = _second;
        for (uint i = 0; i < 8; i += 2)
        {
            (first, second) = columnround(first, second);
            (first, second) = rowround(first, second);
        }
        for (i = 0; i < 8; i++)
        {
            rfirst |= put(get(_first, i) + get(first, i), i);
            rsecond |= put(get(_second, i) + get(second, i), i);
        }
    }
    function round(uint _a, uint _b, uint _c, uint _d) constant returns (uint, uint, uint, uint) {
        (_a, _b) = salsa20_8(_a ^ _c, _b ^ _d);
        (_c, _d) = salsa20_8(_a ^ _c, _b ^ _d);
        return (_a, _b, _c, _d);
    }
}

contract Scrypt {
    /// Verifies a salsa step in the first half of the scrypt computation.
    function verifyFirstHalf(uint[4] input, uint[4] output) constant returns (bool) {
        var (a, b, c, d) = Salsa8.round(input[0], input[1], input[2], input[3]);
        return (a == output[0] && b == output[1] && c == output[2] && d == output[3]);
    }
    /// Verifies a salsa step in the second half of the scrypt computation.
    function verifySecondHalf(uint[4] input, uint[4] vinput, uint[4] output) constant returns (bool) {
        input[0] ^= vinput[0];
        input[1] ^= vinput[1];
        input[2] ^= vinput[2];
        input[3] ^= vinput[3];
        return verifyFirstHalf(input, output);
    }

    event Convicted();

    uint[] queries;
    /// Challenger queries claimant for the inputs and outputs in step `_step`.
    function query(uint _step) {
        if (queries.length > commits.length) throw;
        queries.push(_step);
    }

    uint[4][3][] commits;
    /// Claimant responds to challenge, commiting to a value.
    function respond(uint[4][3] _response) {
        if (commits.length >= queries.length) throw;
        uint step = queries[queries.length - 1];
        if (step < 1024 && !verifyFirstHalf(_response[0], _response[1])) {
            Convicted();
            return;
        } else if (step >= 1024 && !verifySecondHalf(_response[0], _response[1], _response[2])) {
            Convicted();
            return;
        }

        commits.push(_response);
    }

    /// Invalid claims in direct computational steps are checked before
    /// storing the response. Another source of inconsistency could be
    /// different values at wires.
    function convictFirstHalfWire(uint q1, uint q2) {
        var step1 = queries[q1];
        var step2 = queries[q2];
        if (step2 != step1 + 1 || step1 > 1024) throw;
        if (commits[q1][1][0] != commits[q2][0][0] ||
            commits[q1][1][1] != commits[q2][0][1] ||
            commits[q1][1][2] != commits[q2][0][2] ||
            commits[q1][1][3] != commits[q2][0][3]
        )
            Convicted();
    }
    //@TODO convictSecondHalfWire
    //@TODO convictCrossWire: check that in step k with (input, vinput),
    // we have vinput = input_step[input % 32]
}
library Salsa8 {
    uint constant m0 = 0x100000000000000000000000000000000000000000000000000000000;
    uint constant m1 = 0x1000000000000000000000000000000000000000000000000;
    uint constant m2 = 0x10000000000000000000000000000000000000000;
    uint constant m3 = 0x100000000000000000000000000000000;
    uint constant m4 = 0x1000000000000000000000000;
    uint constant m5 = 0x10000000000000000;
    uint constant m6 = 0x100000000;
    uint constant m7 = 0x1;
    function quarter(uint32 y0, uint32 y1, uint32 y2, uint32 y3)
        internal returns (uint32, uint32, uint32, uint32)
    {
        uint32 t;
        t = y0 + y3;
        y1 = y1 ^ ((t * 2**7) | (t / 2**(32-7)));
        t = y1 + y0;
        y2 = y2 ^ ((t * 2**9) | (t / 2**(32-9)));
        t = y2 + y1;
        y3 = y3 ^ ((t * 2**13) | (t / 2**(32-13)));
        t = y3 + y2;
        y0 = y0 ^ ((t * 2**18) | (t / 2**(32-18)));
        return (y0, y1, y2, y3);
    }
    function get(uint data, uint word) internal returns (uint32 x)
    {
        return uint32(data / 2**(256 - word * 32 - 32));
    }
    function put(uint x, uint word) internal returns (uint) {
        return x * 2**(256 - word * 32 - 32);
    }
    function rowround(uint first, uint second) internal returns (uint f, uint s)
    {
        var (a,b,c,d) = quarter(uint32(first / m0), uint32(first / m1), uint32(first / m2), uint32(first / m3));
        f = (((((uint(a) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (b,c,d,a) = quarter(uint32(first / m5), uint32(first / m6), uint32(first / m7), uint32(first / m4));
        f = (((((((f * 2**32) | uint(a)) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (c,d,a,b) = quarter(uint32(second / m2), uint32(second / m3), uint32(second / m0), uint32(second / m1));
        s = (((((uint(a) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
        (d,a,b,c) = quarter(uint32(second / m7), uint32(second / m4), uint32(second / m5), uint32(second / m6));
        s = (((((((s * 2**32) | uint(a)) * 2**32) | uint(b)) * 2 ** 32) | uint(c)) * 2**32) | uint(d);
    }
    function columnround(uint first, uint second) internal returns (uint f, uint s)
    {
        var (a,b,c,d) = quarter(uint32(first / m0), uint32(first / m4), uint32(second / m0), uint32(second / m4));
        f = (uint(a) * m0) | (uint(b) * m4);
        s = (uint(c) * m0) | (uint(d) * m4);
        (a,b,c,d) = quarter(uint32(first / m5), uint32(second / m1), uint32(second / m5), uint32(first / m1));
        f |= (uint(a) * m5) | (uint(d) * m1);
        s |= (uint(b) * m1) | (uint(c) * m5);
        (a,b,c,d) = quarter(uint32(second / m2), uint32(second / m6), uint32(first / m2), uint32(first / m6));
        f |= (uint(c) * m2) | (uint(d) * m6);
        s |= (uint(a) * m2) | (uint(b) * m6);
        (a,b,c,d) = quarter(uint32(second / m7), uint32(first / m3), uint32(first / m7), uint32(second / m3));
        f |= (uint(b) * m3) | (uint(c) * m7);
        s |= (uint(a) * m7) | (uint(d) * m3);
    }
    function salsa20_8(uint _first, uint _second) internal returns (uint rfirst, uint rsecond) {
        uint first = _first;
        uint second = _second;
        for (uint i = 0; i < 8; i += 2)
        {
            (first, second) = columnround(first, second);
            (first, second) = rowround(first, second);
        }
        for (i = 0; i < 8; i++)
        {
            rfirst |= put(get(_first, i) + get(first, i), i);
            rsecond |= put(get(_second, i) + get(second, i), i);
        }
    }
    function round(uint _a, uint _b, uint _c, uint _d) constant returns (uint, uint, uint, uint) {
        (_a, _b) = salsa20_8(_a ^ _c, _b ^ _d);
        (_c, _d) = salsa20_8(_a ^ _c, _b ^ _d);
        return (_a, _b, _c, _d);
    }
}


Throws => Throw

Throws => Throw

pragma solidity ^0.4.4;

import "dapple/test.sol";
import "./blobstore.sol";
import "./blobstore_flags.sol";
import "./blobstore_proxy.sol";

/**
 * @title BlobStoreTest
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStoreTest is Test, BlobStoreFlags {

    BlobStoreRegistry blobStoreRegistry;
    BlobStore blobStore;
    BlobStoreProxy blobStoreProxy;

    function setUp() {
        blobStoreRegistry = new BlobStoreRegistry();
        blobStore = new BlobStore(blobStoreRegistry);
        blobStoreProxy = new BlobStoreProxy(blobStore);
    }

    function testThrowRegisterContractAgain() {
        blobStoreRegistry.register(blobStore.getContractId());
    }

    function testThrowBlobStoreNotRegistered() {
        blobStoreRegistry.getBlobStore(0);
    }

    function testBlobStoreRegistered() {
        assertEq(blobStoreRegistry.getBlobStore(blobStore.getContractId()), blobStore);
    }

    function testCreate() {
        bytes20 blobId0 = blobStore.create(0, hex"00");
        assertTrue(blobStore.getExists(blobId0));
        assertEq(blobStore.getOwner(blobId0), this);
        assertEq(blobStore.getRevisionCount(blobId0), 1);
        assertFalse(blobStore.getUpdatable(blobId0));
        assertFalse(blobStore.getEnforceRevisions(blobId0));
        assertFalse(blobStore.getRetractable(blobId0));
        assertFalse(blobStore.getTransferable(blobId0));

        bytes20 blobId1 = blobStore.create(UPDATABLE | ENFORCE_REVISIONS | RETRACTABLE | TRANSFERABLE | ANONYMOUS, hex"00");
        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), 0);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertTrue(blobStore.getUpdatable(blobId1));
        assertTrue(blobStore.getEnforceRevisions(blobId1));
        assertTrue(blobStore.getRetractable(blobId1));
        assertTrue(blobStore.getTransferable(blobId1));

        assertFalse(blobId0 == blobId1);
    }

    function testThrowCreateWithNonceExistingNonce() {
        blobStore.createWithNonce(0, hex"00");
        blobStore.createWithNonce(0, hex"00");
    }

    function testCreateWithNonce() {
        bytes20 blobId0 = blobStore.createWithNonce(0, hex"00");
        assertTrue(blobStore.getExists(blobId0));
        assertEq(blobStore.getOwner(blobId0), this);
        assertEq(blobStore.getRevisionCount(blobId0), 1);
        assertFalse(blobStore.getUpdatable(blobId0));
        assertFalse(blobStore.getEnforceRevisions(blobId0));
        assertFalse(blobStore.getRetractable(blobId0));
        assertFalse(blobStore.getTransferable(blobId0));

        bytes20 blobId1 = blobStoreProxy.createWithNonce(0, hex"00");

        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), blobStoreProxy);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertFalse(blobStore.getUpdatable(blobId1));
        assertFalse(blobStore.getEnforceRevisions(blobId1));
        assertFalse(blobStore.getRetractable(blobId1));
        assertFalse(blobStore.getTransferable(blobId1));
        assertFalse(blobId0 == blobId1);

        blobId1 = blobStore.createWithNonce(UPDATABLE | ENFORCE_REVISIONS | RETRACTABLE | TRANSFERABLE | ANONYMOUS, hex"00");
        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), 0);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertTrue(blobStore.getUpdatable(blobId1));
        assertTrue(blobStore.getEnforceRevisions(blobId1));
        assertTrue(blobStore.getRetractable(blobId1));
        assertTrue(blobStore.getTransferable(blobId1));
        assertFalse(blobId0 == blobId1);
    }

    function testThrowCreateWithNonceRetracted() {
        bytes20 blobId = blobStore.createWithNonce(RETRACTABLE, hex"00");
        blobStore.retract(blobId);
        blobStore.createWithNonce(RETRACTABLE, hex"00");
    }

    function testThrowCreateNewRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.createNewRevision(blobId, hex"00");
    }

    function testThrowCreateNewRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
    }

    function testCreateNewRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        uint revisionId = blobStore.createNewRevision(blobId, hex"00");
        assertEq(revisionId, 1);
        assertEq(blobStore.getRevisionCount(blobId), 2);
    }

    function testThrowUpdateLatestRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.updateLatestRevision(blobId, hex"00");
    }

    function testThrowUpdateLatestRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
    }

    function testThrowUpdateLatestRevisionEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
    }

    function testUpdateLatestRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 1);
    }

    function testThrowRetractLatestRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStoreProxy.retractLatestRevision(blobId);
    }

    function testThrowRetractLatestRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.setNotUpdatable(blobId);
        blobStore.retractLatestRevision(blobId);
    }

    function testThrowRetractLatestRevisionEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.retractLatestRevision(blobId);
    }

    function testThrowRetractLatestRevisionDoesntHaveAdditionalRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.retractLatestRevision(blobId);
    }

    function testRetractLatestRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 3);
        blobStore.retractLatestRevision(blobId);
        assertEq(blobStore.getRevisionCount(blobId), 2);
    }

    function testThrowRestartNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.restart(blobId, hex"00");
    }

    function testThrowRestartNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.restart(blobId, hex"00");
    }

    function testThrowRestartEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.restart(blobId, hex"00");
    }

    function testRestart() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 3);
        blobStore.restart(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 1);
    }

    function testThrowRetractNotOwner() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStoreProxy.retract(blobId);
    }

    function testThrowRetractNotRetractable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.retract(blobId);
    }

    function testRetract() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStore.retract(blobId);
        assertEq(blobStore.getExists(blobId), false);
    }

    function testThrowTransferEnableNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.transferEnable(blobId);
    }

    function testThrowTransferDisableNotEnabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferDisable(blobId);
    }

    function testThrowTransferNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
    }

    function testThrowTransferNotEnabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStore.transfer(blobId, blobStoreProxy);
    }

    function testThrowTransferDisabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStoreProxy.transferDisable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
        assertEq(blobStore.getOwner(blobId), blobStoreProxy);
    }

    function testTransfer() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
        assertEq(blobStore.getOwner(blobId), blobStoreProxy);
    }

    function testThrowDisownNotOwner() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.disown(blobId);
    }

    function testThrowDisownNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.disown(blobId);
    }

    function testDisown() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        assertEq(blobStore.getOwner(blobId), this);
        blobStore.disown(blobId);
        assertEq(blobStore.getOwner(blobId), 0);
    }

    function testThrowSetNotUpdatableNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.setNotUpdatable(blobId);
    }

    function testSetNotUpdatable() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        assertTrue(blobStore.getUpdatable(blobId));
        blobStore.setNotUpdatable(blobId);
        assertEq(blobStore.getUpdatable(blobId), false);
    }

    function testThrowSetEnforceRevisionsNotOwner() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.setEnforceRevisions(blobId);
    }

    function testSetEnforceRevisions() {
        bytes20 blobId = blobStore.create(0, hex"00");
        assertEq(blobStore.getEnforceRevisions(blobId), false);
        blobStore.setEnforceRevisions(blobId);
        assertTrue(blobStore.getEnforceRevisions(blobId));
    }

    function testThrowSetNotRetractableNotOwner() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStoreProxy.setNotRetractable(blobId);
    }

    function testSetNotRetractable() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        assertTrue(blobStore.getRetractable(blobId));
        blobStore.setNotRetractable(blobId);
        assertEq(blobStore.getRetractable(blobId), false);
    }

    function testThrowSetNotTransferableNotOwner() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.setNotTransferable(blobId);
    }

    function testSetNotTransferable() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        assertTrue(blobStore.getTransferable(blobId));
        blobStore.setNotTransferable(blobId);
        assertEq(blobStore.getTransferable(blobId), false);
    }

}

pragma solidity ^0.4.4;

import "dapple/test.sol";
import "./blobstore.sol";
import "./blobstore_flags.sol";
import "./blobstore_proxy.sol";

/**
 * @title BlobStoreTest
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStoreTest is Test, BlobStoreFlags {

    BlobStoreRegistry blobStoreRegistry;
    BlobStore blobStore;
    BlobStoreProxy blobStoreProxy;

    function setUp() {
        blobStoreRegistry = new BlobStoreRegistry();
        blobStore = new BlobStore(blobStoreRegistry);
        blobStoreProxy = new BlobStoreProxy(blobStore);
    }

    function testThrowRegisterContractAgain() {
        blobStoreRegistry.register(blobStore.getContractId());
    }

    function testThrowBlobStoreNotRegistered() {
        blobStoreRegistry.getBlobStore(0);
    }

    function testBlobStoreRegistered() {
        assertEq(blobStoreRegistry.getBlobStore(blobStore.getContractId()), blobStore);
    }

    function testCreate() {
        bytes20 blobId0 = blobStore.create(0, hex"00");
        assertTrue(blobStore.getExists(blobId0));
        assertEq(blobStore.getOwner(blobId0), this);
        assertEq(blobStore.getRevisionCount(blobId0), 1);
        assertFalse(blobStore.getUpdatable(blobId0));
        assertFalse(blobStore.getEnforceRevisions(blobId0));
        assertFalse(blobStore.getRetractable(blobId0));
        assertFalse(blobStore.getTransferable(blobId0));

        bytes20 blobId1 = blobStore.create(UPDATABLE | ENFORCE_REVISIONS | RETRACTABLE | TRANSFERABLE | ANONYMOUS, hex"00");
        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), 0);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertTrue(blobStore.getUpdatable(blobId1));
        assertTrue(blobStore.getEnforceRevisions(blobId1));
        assertTrue(blobStore.getRetractable(blobId1));
        assertTrue(blobStore.getTransferable(blobId1));

        assertFalse(blobId0 == blobId1);
    }

    function testThrowCreateWithNonceExistingNonce() {
        blobStore.createWithNonce(0, hex"00");
        blobStore.createWithNonce(0, hex"00");
    }

    function testCreateWithNonce() {
        bytes20 blobId0 = blobStore.createWithNonce(0, hex"00");
        assertTrue(blobStore.getExists(blobId0));
        assertEq(blobStore.getOwner(blobId0), this);
        assertEq(blobStore.getRevisionCount(blobId0), 1);
        assertFalse(blobStore.getUpdatable(blobId0));
        assertFalse(blobStore.getEnforceRevisions(blobId0));
        assertFalse(blobStore.getRetractable(blobId0));
        assertFalse(blobStore.getTransferable(blobId0));

        bytes20 blobId1 = blobStoreProxy.createWithNonce(0, hex"00");

        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), blobStoreProxy);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertFalse(blobStore.getUpdatable(blobId1));
        assertFalse(blobStore.getEnforceRevisions(blobId1));
        assertFalse(blobStore.getRetractable(blobId1));
        assertFalse(blobStore.getTransferable(blobId1));
        assertFalse(blobId0 == blobId1);

        blobId1 = blobStore.createWithNonce(UPDATABLE | ENFORCE_REVISIONS | RETRACTABLE | TRANSFERABLE | ANONYMOUS, hex"00");
        assertTrue(blobStore.getExists(blobId1));
        assertEq(blobStore.getOwner(blobId1), 0);
        assertEq(blobStore.getRevisionCount(blobId1), 1);
        assertTrue(blobStore.getUpdatable(blobId1));
        assertTrue(blobStore.getEnforceRevisions(blobId1));
        assertTrue(blobStore.getRetractable(blobId1));
        assertTrue(blobStore.getTransferable(blobId1));
        assertFalse(blobId0 == blobId1);
    }

    function testThrowCreateWithNonceRetracted() {
        bytes20 blobId = blobStore.createWithNonce(RETRACTABLE, hex"00");
        blobStore.retract(blobId);
        blobStore.createWithNonce(RETRACTABLE, hex"00");
    }

    function testThrowsCreateNewRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.createNewRevision(blobId, hex"00");
    }

    function testThrowsCreateNewRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
    }

    function testCreateNewRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        uint revisionId = blobStore.createNewRevision(blobId, hex"00");
        assertEq(revisionId, 1);
        assertEq(blobStore.getRevisionCount(blobId), 2);
    }

    function testThrowsUpdateLatestRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.updateLatestRevision(blobId, hex"00");
    }

    function testThrowsUpdateLatestRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
    }

    function testThrowsUpdateLatestRevisionEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
    }

    function testUpdateLatestRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.updateLatestRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 1);
    }

    function testThrowsRetractLatestRevisionNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStoreProxy.retractLatestRevision(blobId);
    }

    function testThrowsRetractLatestRevisionNotUpdatable() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.setNotUpdatable(blobId);
        blobStore.retractLatestRevision(blobId);
    }

    function testThrowsRetractLatestRevisionEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.retractLatestRevision(blobId);
    }

    function testThrowsRetractLatestRevisionDoesntHaveAdditionalRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.retractLatestRevision(blobId);
    }

    function testRetractLatestRevision() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 3);
        blobStore.retractLatestRevision(blobId);
        assertEq(blobStore.getRevisionCount(blobId), 2);
    }

    function testThrowsRestartNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.restart(blobId, hex"00");
    }

    function testThrowsRestartNotUpdatable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.restart(blobId, hex"00");
    }

    function testThrowsRestartEnforceRevisions() {
        bytes20 blobId = blobStore.create(UPDATABLE | ENFORCE_REVISIONS, hex"00");
        blobStore.restart(blobId, hex"00");
    }

    function testRestart() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        blobStore.createNewRevision(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 3);
        blobStore.restart(blobId, hex"00");
        assertEq(blobStore.getRevisionCount(blobId), 1);
    }

    function testThrowsRetractNotOwner() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStoreProxy.retract(blobId);
    }

    function testThrowsRetractNotRetractable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.retract(blobId);
    }

    function testRetract() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStore.retract(blobId);
        assertEq(blobStore.getExists(blobId), false);
    }

    function testThrowsTransferEnableNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.transferEnable(blobId);
    }

    function testThrowsTransferDisableNotEnabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferDisable(blobId);
    }

    function testThrowsTransferNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
    }

    function testThrowsTransferNotEnabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStore.transfer(blobId, blobStoreProxy);
    }

    function testThrowsTransferDisabled() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStoreProxy.transferDisable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
        assertEq(blobStore.getOwner(blobId), blobStoreProxy);
    }

    function testTransfer() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.transferEnable(blobId);
        blobStore.transfer(blobId, blobStoreProxy);
        assertEq(blobStore.getOwner(blobId), blobStoreProxy);
    }

    function testThrowsDisownNotOwner() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.disown(blobId);
    }

    function testThrowsDisownNotTransferable() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStore.disown(blobId);
    }

    function testDisown() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        assertEq(blobStore.getOwner(blobId), this);
        blobStore.disown(blobId);
        assertEq(blobStore.getOwner(blobId), 0);
    }

    function testThrowsSetNotUpdatableNotOwner() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        blobStoreProxy.setNotUpdatable(blobId);
    }

    function testSetNotUpdatable() {
        bytes20 blobId = blobStore.create(UPDATABLE, hex"00");
        assertTrue(blobStore.getUpdatable(blobId));
        blobStore.setNotUpdatable(blobId);
        assertEq(blobStore.getUpdatable(blobId), false);
    }

    function testThrowsSetEnforceRevisionsNotOwner() {
        bytes20 blobId = blobStore.create(0, hex"00");
        blobStoreProxy.setEnforceRevisions(blobId);
    }

    function testSetEnforceRevisions() {
        bytes20 blobId = blobStore.create(0, hex"00");
        assertEq(blobStore.getEnforceRevisions(blobId), false);
        blobStore.setEnforceRevisions(blobId);
        assertTrue(blobStore.getEnforceRevisions(blobId));
    }

    function testThrowsSetNotRetractableNotOwner() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        blobStoreProxy.setNotRetractable(blobId);
    }

    function testSetNotRetractable() {
        bytes20 blobId = blobStore.create(RETRACTABLE, hex"00");
        assertTrue(blobStore.getRetractable(blobId));
        blobStore.setNotRetractable(blobId);
        assertEq(blobStore.getRetractable(blobId), false);
    }

    function testThrowsSetNotTransferableNotOwner() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        blobStoreProxy.setNotTransferable(blobId);
    }

    function testSetNotTransferable() {
        bytes20 blobId = blobStore.create(TRANSFERABLE, hex"00");
        assertTrue(blobStore.getTransferable(blobId));
        blobStore.setNotTransferable(blobId);
        assertEq(blobStore.getTransferable(blobId), false);
    }

}


calling assert against htlc double spend

contract MicropaymentsNetwork
{

    enum ChannelStage
    {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing,
        Closed
    }

    struct MicropaymentsChannel
    {
        ChannelStage stage;

        address from;
        uint fromBalance;

        address to;
        uint toBalance;

        uint balanceTimestamp;
        uint closingBlockNumber;

        mapping(bytes32 => bool) hashesUsed;
    }

    uint public constant closingDelay = 10;

    mapping(uint => MicropaymentsChannel) channels;
    mapping(uint => bool) reserved;

    function MicropaymentsNetwork()
    {
    }

    function isAvailable(uint _cid)
        constant
        returns (bool)
    {
        return !reserved[_cid];
    }

    function assertAvailable(uint _cid)
        internal
    {
        if (!isAvailable(_cid))
        {
            throw;
        }
    }

    function assertOnlyFrom(uint _cid)
        internal
    {
        if (msg.sender != channels[_cid].from)
        {
            throw;
        }
    }

    function assertOnlyTo(uint _cid)
        internal
    {
        if (msg.sender != channels[_cid].to)
        {
            throw;
        }
    }

    function assertOnlyParticipants(uint _cid)
        internal
    {
        if ((msg.sender != channels[_cid].from) && (msg.sender != channels[_cid].to))
        {
            throw;
        }
    }

    function assertAtStage(uint _cid, ChannelStage _stage)
        internal
    {
        if (channels[_cid].stage != _stage)
        {
            throw;
        }
    }

    function assertAtOneOfStages(uint _cid, ChannelStage _stage1, ChannelStage _stage2)
    {
        if ((channels[_cid].stage != _stage1) && (channels[_cid].stage != _stage2))
        {
            throw;
        }
    }

    function assertReadyToClose(uint _cid)
    {
        if (block.number < channels[_cid].closingBlockNumber)
        {
            throw;
        }
    }

    function assertYoungerBalance(uint _cid, uint _balanceTimestamp)
        internal
    {
        if (_balanceTimestamp <= channels[_cid].balanceTimestamp)
        {
            throw;
        }
    }

    function assertMatchingBalance(uint _cid, uint _balanceTimestamp)
        internal
    {
        if (_balanceTimestamp != channels[_cid].balanceTimestamp)
        {
            throw;
        }
    }

    function assertSaneBalance(uint _cid, uint _fromBalance, uint _toBalance)
        internal
    {
        if (channels[_cid].fromBalance + channels[_cid].toBalance < _fromBalance + _toBalance)
        {
            throw;
        }
    }

    function assertStillValid(uint _timeout)
        internal
    {
        if (_timeout < now)
        {
            throw;
        }
    }

    function assertSaneHTLC(uint _cid, int _fromToDelta)
        internal
    {
        if ((int(channels[_cid].fromBalance) - _fromToDelta < 0) ||
            (int(channels[_cid].toBalance) + _fromToDelta < 0))
        {
            throw;
        }
    }

    function assertHash(bytes32 _data, bytes32 _hash)
        internal
    {
        if (getHash(_data) != _hash)
        {
            throw;
        }
    }

    function assertNotSpent(uint _cid, uint _balanceTimestamp, bytes32 _hash)
        internal
    {
        if (channels[_cid].hashesUsed[getHTLCSpendingHash(_balanceTimestamp, _hash)])
        {
            throw;
        }
    }

    function assertSignedByBoth(
        uint _cid,
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
        internal
    {
        address signer = getSigner(_sigHash, _sigV, _sigR, _sigS);
        if (!(((channels[_cid].from == msg.sender) && (channels[_cid].to == signer)) ||
              ((channels[_cid].from == signer) && (channels[_cid].to == msg.sender))))
        {
            throw;
        }
    }

    function getHTLCSpendingHash(uint _balanceTimestamp, bytes32 _hash)
        constant
        returns (bytes32)
    {
        return sha3(_balanceTimestamp, _hash);
    }

    function getHash(bytes32 _data)
        constant
        returns (bytes32)
    {
        return sha3(_data);
    }

    function getUpdateHash(
        uint _cid,
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance)
        constant
        returns(bytes32)
    {
        return sha3(_cid, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getHTLCHash(
        uint _cid,
        uint _balanceTimestamp,
        uint _timeout,
        bytes32 _hash,
        int _fromToDelta)
        constant
        returns(bytes32)
    {
        return sha3(_cid, _timeout, _hash, _fromToDelta);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
        constant
        returns(address)
    {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function getTimestampInSeconds()
        constant
        returns(uint)
    {
        return now;
    }

    function createChannel(uint _cid, address _from, address _to)
    {
        assertAvailable(_cid);

        reserved[_cid] = true;
        channels[_cid] = MicropaymentsChannel(ChannelStage.Empty, _from, 0, _to, 0, 0, 0);
    }

    function getStage(uint _cid)
        constant
        returns (uint8)
    {
        return uint8(channels[_cid].stage);
    }

    function getFrom(uint _cid)
        constant
        returns (address)
    {
        return channels[_cid].from;
    }

    function getFromBalance(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].fromBalance;
    }

    function getTo(uint _cid)
        constant
        returns (address)
    {
        return channels[_cid].to;
    }

    function getToBalance(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].toBalance;
    }

    function getBalanceTimestamp(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].balanceTimestamp;
    }

    function getClosingBlockNumber(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].closingBlockNumber;
    }

    function openChannel(uint _cid)
    {
        assertOnlyFrom(_cid);
        assertAtStage(_cid, ChannelStage.Empty);

        channels[_cid].stage = ChannelStage.PartiallyConfirmed;
        channels[_cid].fromBalance = msg.value;
    }

    function confirmChannel(uint _cid)
    {
        assertOnlyTo(_cid);
        assertAtStage(_cid, ChannelStage.PartiallyConfirmed);

        channels[_cid].stage = ChannelStage.Confirmed;
        channels[_cid].toBalance = msg.value;
    }

    function requestClosingChannel(uint _cid)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.PartiallyConfirmed, ChannelStage.Confirmed);

        if (channels[_cid].stage == ChannelStage.PartiallyConfirmed)
        {
            channels[_cid].stage = ChannelStage.Closed;
        }
        else
        {
            channels[_cid].stage = ChannelStage.Closing;
            channels[_cid].closingBlockNumber = block.number + closingDelay;
        }
    }

    function closeChannel(uint _cid)
    {
        assertOnlyParticipants(_cid);
        assertAtStage(_cid, ChannelStage.Closing);
        assertReadyToClose(_cid);

        channels[_cid].stage = ChannelStage.Closed;
    }

    function withdrawFrom(uint _cid)
    {
        assertOnlyFrom(_cid);
        assertAtStage(_cid, ChannelStage.Closed);

        uint balance = channels[_cid].fromBalance;
        channels[_cid].fromBalance = 0;
        channels[_cid].from.send(balance);
    }

    function withdrawTo(uint _cid)
    {
        assertOnlyTo(_cid);
        assertAtStage(_cid, ChannelStage.Closed);

        uint balance = channels[_cid].toBalance;
        channels[_cid].toBalance = 0;
        channels[_cid].to.send(balance);
    }

    function updateChannelState(
        uint _cid,
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.Confirmed, ChannelStage.Closing);
        assertYoungerBalance(_cid, _balanceTimestamp);
        assertSaneBalance(_cid, _fromBalance, _toBalance);
        assertSignedByBoth(_cid, getUpdateHash(_cid, _balanceTimestamp, _fromBalance, _toBalance), _sigV, _sigR, _sigS);

        channels[_cid].balanceTimestamp = _balanceTimestamp;
        channels[_cid].fromBalance = _fromBalance;
        channels[_cid].toBalance = _toBalance;
    }

    function resolveHTLC(
        uint _cid,
        uint _balanceTimestamp,
        uint _timeout,
        bytes32 _hash,
        int _fromToDelta,
        bytes32 _data,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.Confirmed, ChannelStage.Closing);
        assertMatchingBalance(_cid, _balanceTimestamp);
        assertStillValid(_timeout);
        assertSaneHTLC(_cid, _fromToDelta);
        assertHash(_data, _hash);
        assertNotSpent(_cid, _balanceTimestamp, _hash);
        assertSignedByBoth(_cid, getHTLCHash(_cid, _balanceTimestamp, _timeout, _hash, _fromToDelta), _sigV, _sigR, _sigS);

        channels[_cid].fromBalance = uint(int(channels[_cid].fromBalance) - _fromToDelta);
        channels[_cid].toBalance = uint(int(channels[_cid].toBalance) + _fromToDelta);
        channels[_cid].hashesUsed[getHTLCSpendingHash(_balanceTimestamp, _hash)] = true;
    }
}

contract MicropaymentsNetwork
{

    enum ChannelStage
    {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing,
        Closed
    }

    struct MicropaymentsChannel
    {
        ChannelStage stage;

        address from;
        uint fromBalance;

        address to;
        uint toBalance;

        uint balanceTimestamp;
        uint closingBlockNumber;

        mapping(bytes32 => bool) hashesUsed;
    }

    uint public constant closingDelay = 10;

    mapping(uint => MicropaymentsChannel) channels;
    mapping(uint => bool) reserved;

    function MicropaymentsNetwork()
    {
    }

    function isAvailable(uint _cid)
        constant
        returns (bool)
    {
        return !reserved[_cid];
    }

    function assertAvailable(uint _cid)
        internal
    {
        if (!isAvailable(_cid))
        {
            throw;
        }
    }

    function assertOnlyFrom(uint _cid)
        internal
    {
        if (msg.sender != channels[_cid].from)
        {
            throw;
        }
    }

    function assertOnlyTo(uint _cid)
        internal
    {
        if (msg.sender != channels[_cid].to)
        {
            throw;
        }
    }

    function assertOnlyParticipants(uint _cid)
        internal
    {
        if ((msg.sender != channels[_cid].from) && (msg.sender != channels[_cid].to))
        {
            throw;
        }
    }

    function assertAtStage(uint _cid, ChannelStage _stage)
        internal
    {
        if (channels[_cid].stage != _stage)
        {
            throw;
        }
    }

    function assertAtOneOfStages(uint _cid, ChannelStage _stage1, ChannelStage _stage2)
    {
        if ((channels[_cid].stage != _stage1) && (channels[_cid].stage != _stage2))
        {
            throw;
        }
    }

    function assertReadyToClose(uint _cid)
    {
        if (block.number < channels[_cid].closingBlockNumber)
        {
            throw;
        }
    }

    function assertYoungerBalance(uint _cid, uint _balanceTimestamp)
        internal
    {
        if (_balanceTimestamp <= channels[_cid].balanceTimestamp)
        {
            throw;
        }
    }

    function assertMatchingBalance(uint _cid, uint _balanceTimestamp)
        internal
    {
        if (_balanceTimestamp != channels[_cid].balanceTimestamp)
        {
            throw;
        }
    }

    function assertSaneBalance(uint _cid, uint _fromBalance, uint _toBalance)
        internal
    {
        if (channels[_cid].fromBalance + channels[_cid].toBalance < _fromBalance + _toBalance)
        {
            throw;
        }
    }

    function assertStillValid(uint _timeout)
        internal
    {
        if (_timeout < now)
        {
            throw;
        }
    }

    function assertSaneHTLC(uint _cid, int _fromToDelta)
        internal
    {
        if ((int(channels[_cid].fromBalance) - _fromToDelta < 0) ||
            (int(channels[_cid].toBalance) + _fromToDelta < 0))
        {
            throw;
        }
    }

    function assertHash(uint _cid, bytes32 _data, bytes32 _hash)
        internal
    {
        if ((channels[_cid].hashesUsed[_hash]) || (getHash(_data) != _hash))
        {
            throw;
        }
    }

    function assertNotSpent(uint _cid, uint _balanceTimestamp, bytes32 _hash)
        internal
    {
        if (channels[_cid].hashesUsed[getHTLCSpendingHash(_balanceTimestamp, _hash)])
        {
            throw;
        }
    }

    function assertSignedByBoth(
        uint _cid,
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
        internal
    {
        address signer = getSigner(_sigHash, _sigV, _sigR, _sigS);
        if (!(((channels[_cid].from == msg.sender) && (channels[_cid].to == signer)) ||
              ((channels[_cid].from == signer) && (channels[_cid].to == msg.sender))))
        {
            throw;
        }
    }

    function getHTLCSpendingHash(uint _balanceTimestamp, bytes32 _hash)
        constant
        returns (bytes32)
    {
        return sha3(_balanceTimestamp, _hash);
    }

    function getHash(bytes32 _data)
        constant
        returns (bytes32)
    {
        return sha3(_data);
    }

    function getUpdateHash(
        uint _cid,
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance)
        constant
        returns(bytes32)
    {
        return sha3(_cid, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getHTLCHash(
        uint _cid,
        uint _balanceTimestamp,
        uint _timeout,
        bytes32 _hash,
        int _fromToDelta)
        constant
        returns(bytes32)
    {
        return sha3(_cid, _timeout, _hash, _fromToDelta);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
        constant
        returns(address)
    {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function getTimestampInSeconds()
        constant
        returns(uint)
    {
        return now;
    }

    function createChannel(uint _cid, address _from, address _to)
    {
        assertAvailable(_cid);

        reserved[_cid] = true;
        channels[_cid] = MicropaymentsChannel(ChannelStage.Empty, _from, 0, _to, 0, 0, 0);
    }

    function getStage(uint _cid)
        constant
        returns (uint8)
    {
        return uint8(channels[_cid].stage);
    }

    function getFrom(uint _cid)
        constant
        returns (address)
    {
        return channels[_cid].from;
    }

    function getFromBalance(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].fromBalance;
    }

    function getTo(uint _cid)
        constant
        returns (address)
    {
        return channels[_cid].to;
    }

    function getToBalance(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].toBalance;
    }

    function getBalanceTimestamp(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].balanceTimestamp;
    }

    function getClosingBlockNumber(uint _cid)
        constant
        returns (uint)
    {
        return channels[_cid].closingBlockNumber;
    }

    function openChannel(uint _cid)
    {
        assertOnlyFrom(_cid);
        assertAtStage(_cid, ChannelStage.Empty);

        channels[_cid].stage = ChannelStage.PartiallyConfirmed;
        channels[_cid].fromBalance = msg.value;
    }

    function confirmChannel(uint _cid)
    {
        assertOnlyTo(_cid);
        assertAtStage(_cid, ChannelStage.PartiallyConfirmed);

        channels[_cid].stage = ChannelStage.Confirmed;
        channels[_cid].toBalance = msg.value;
    }

    function requestClosingChannel(uint _cid)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.PartiallyConfirmed, ChannelStage.Confirmed);

        if (channels[_cid].stage == ChannelStage.PartiallyConfirmed)
        {
            channels[_cid].stage = ChannelStage.Closed;
        }
        else
        {
            channels[_cid].stage = ChannelStage.Closing;
            channels[_cid].closingBlockNumber = block.number + closingDelay;
        }
    }

    function closeChannel(uint _cid)
    {
        assertOnlyParticipants(_cid);
        assertAtStage(_cid, ChannelStage.Closing);
        assertReadyToClose(_cid);

        channels[_cid].stage = ChannelStage.Closed;
    }

    function withdrawFrom(uint _cid)
    {
        assertOnlyFrom(_cid);
        assertAtStage(_cid, ChannelStage.Closed);

        uint balance = channels[_cid].fromBalance;
        channels[_cid].fromBalance = 0;
        channels[_cid].from.send(balance);
    }

    function withdrawTo(uint _cid)
    {
        assertOnlyTo(_cid);
        assertAtStage(_cid, ChannelStage.Closed);

        uint balance = channels[_cid].toBalance;
        channels[_cid].toBalance = 0;
        channels[_cid].to.send(balance);
    }

    function updateChannelState(
        uint _cid,
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.Confirmed, ChannelStage.Closing);
        assertYoungerBalance(_cid, _balanceTimestamp);
        assertSaneBalance(_cid, _fromBalance, _toBalance);
        assertSignedByBoth(_cid, getUpdateHash(_cid, _balanceTimestamp, _fromBalance, _toBalance), _sigV, _sigR, _sigS);

        channels[_cid].balanceTimestamp = _balanceTimestamp;
        channels[_cid].fromBalance = _fromBalance;
        channels[_cid].toBalance = _toBalance;
    }

    function resolveHTLC(
        uint _cid,
        uint _balanceTimestamp,
        uint _timeout,
        bytes32 _hash,
        int _fromToDelta,
        bytes32 _data,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS)
    {
        assertOnlyParticipants(_cid);
        assertAtOneOfStages(_cid, ChannelStage.Confirmed, ChannelStage.Closing);
        assertMatchingBalance(_cid, _balanceTimestamp);
        assertStillValid(_timeout);
        assertSaneHTLC(_cid, _fromToDelta);
        assertHash(_cid, _data, _hash);
        assertSignedByBoth(_cid, getHTLCHash(_cid, _balanceTimestamp, _timeout, _hash, _fromToDelta), _sigV, _sigR, _sigS);

        channels[_cid].fromBalance = uint(int(channels[_cid].fromBalance) - _fromToDelta);
        channels[_cid].toBalance = uint(int(channels[_cid].toBalance) + _fromToDelta);
        channels[_cid].hashesUsed[getHTLCSpendingHash(_balanceTimestamp, _hash)] = true;
    }
}


merging

merging

pragma solidity ^0.4.2;

// This is the main contract that governs execution of auctions
// of non-fungible on-chain assets. Any user can initiate an auction
// for an item that conforms to the Asset interface described in
// Asset.sol

import "Asset.sol";

contract AuctionHouse {

    struct Bid {
        address bidder;
        uint256 amount;
        uint timestamp;
    }

    enum AuctionStatus {Pending, Active, Inactive}

    struct Auction {
        // Location and ownership information of the item for sale
        address seller;
        address contractAddress; // Contract where the item exists
        string recordId;         // RecordID within the contract as per the Asset interface

        // Auction metadata
        string title;
        string description;      // Optionally markdown formatted?
        uint blockNumberOfDeadline;
        AuctionStatus status;

        // Distribution bonus
        uint distributionCut;    // In percent, ie 10 is a 10% cut to the distribution address
        address distributionAddress;

        // Pricing
        uint256 startingPrice;   // In wei
        uint256 reservePrice;
        uint256 currentBid;

        Bid[] bids;
    }

    Auction[] public auctions;          // All auctions
    mapping(address => uint[]) public auctionsRunByUser; // Pointer to auctions index for auctions run by this user

    mapping(address => uint[]) public auctionsBidOnByUser; // Pointer to auctions index for auctions this user has bid on

    mapping(string => bool) activeContractRecordConcat;

    mapping(address => uint) refunds;

    address owner;

    // Events
    event AuctionCreated(uint id, string title, uint256 startingPrice, uint256 reservePrice);
    event AuctionActivated(uint id);
    event AuctionCancelled(uint id);
    event BidPlaced(uint auctionId, address bidder, uint256 amount);
    event AuctionEndedWithWinner(uint auctionId, address winningBidder, uint256 amount);
    event AuctionEndedWithoutWinner(uint auctionId, uint256 topBid, uint256 reservePrice);

    event LogFailure(string message);

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

    modifier onlySeller(uint auctionId) {
        if (auctions[auctionId].seller != msg.sender) throw;
        _;
    }

    modifier onlyLive(uint auctionId) {
        Auction a = auctions[auctionId];
        if (a.status != AuctionStatus.Active) {
            throw;
        }

        // Auction should not be over
        if (block.number >= a.blockNumberOfDeadline) {
            throw;
        }
        _;
    }

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

    // Create an auction, transfer the item to this contract, activate the auction
    function createAuction(
                           string _title,
                           string _description,
                           address _contractAddressOfAsset,
                           string _recordIdOfAsset,
                           uint _deadline,   // in blocknumber
                           uint256 _startingPrice,
                           uint256 _reservePrice,
                           uint _distributionCut,
                           address _distributionCutAddress) returns (uint auctionId) {

        // Check to see if the seller owns the asset at the contract
        if (!partyOwnsAsset(msg.sender, _contractAddressOfAsset, _recordIdOfAsset)) {
            LogFailure("Seller does not own this asset");
            throw;
        }

        // Check to see if the auction deadline is in the future
        if (block.number >= _deadline) {
            LogFailure("Block number is not in the future");
            throw;
        }

        // Price validations
        if (_startingPrice < 0 || _reservePrice < 0) {
            LogFailure("StartingPrice or ReservePrice was below zero");
            throw;
        }

        // Distribution validations
        if (_distributionCut < 0 || _distributionCut > 100) {
            LogFailure("DistributionCut is invalid");
            throw;
        }

        if (activeContractRecordConcat[strConcat(addrToString(_contractAddressOfAsset), _recordIdOfAsset)] == true) {
            LogFailure("Item already on auction");
            throw;
        }

        auctionId = auctions.length++;
        Auction a = auctions[auctionId];
        a.seller = msg.sender;
        a.contractAddress = _contractAddressOfAsset;
        a.recordId = _recordIdOfAsset;
        a.title = _title;
        a.description = _description;
        a.blockNumberOfDeadline = _deadline;
        a.status = AuctionStatus.Pending;
        a.distributionCut = _distributionCut;
        a.distributionAddress = _distributionCutAddress;
        a.startingPrice = _startingPrice;
        a.reservePrice = _reservePrice;
        a.currentBid = _startingPrice;

        auctionsRunByUser[a.seller].push(auctionId);
        activeContractRecordConcat[strConcat(addrToString(_contractAddressOfAsset), _recordIdOfAsset)] = true;

        AuctionCreated(auctionId, a.title, a.startingPrice, a.reservePrice);

        return auctionId;
    }

    function partyOwnsAsset(address _party, address _contract, string _recordId) returns (bool success) {
        Asset assetContract = Asset(_contract);
        return assetContract.owner(_recordId) == _party;
    }

    /**
     * The auction fields are indexed in the return val as follows
     * [0]  -> Auction.seller
     * [1]  -> Auction.contractAddress
     * [2]  -> Auction.recordId
     * [3]  -> Auction.title
     * [4]  -> Auction.description
     * [5]  -> Auction.blockNumberOfDeadline
     * [6]  -> Auction.distributionCut
     * [7]  -> Auction.distributionAddress
     * [8]  -> Auction.startingPrice
     * [9] -> Auction.reservePrice
     * [10] -> Auction.currentBid
     * [11] -> Auction.bids.length
     * []  -> Auction.status (Not included right now)
     */
    function getAuction(uint idx) returns (address, address, string, string, string, uint, uint, address, uint256, uint256, uint256, uint) {
        Auction a = auctions[idx];
        if (a.seller == 0) {
            throw;
        }

        return (a.seller,
                a.contractAddress,
                a.recordId,
                a.title,
                a.description,
                a.blockNumberOfDeadline,
                a.distributionCut,
                a.distributionAddress,
                a.startingPrice,
                a.reservePrice,
                a.currentBid,
                a.bids.length
                );
    }

    function getAuctionCount() returns (uint) {
        return auctions.length;
    }

    function getStatus(uint idx) returns (uint) {
        Auction a = auctions[idx];
        return uint(a.status);
    }

    function getAuctionsCountForUser(address addr) returns (uint) {
        return auctionsRunByUser[addr].length;
    }

    function getAuctionIdForUserAndIdx(address addr, uint idx) returns (uint) {
        return auctionsRunByUser[addr][idx];
    }

    function getActiveContractRecordConcat(string _contractRecordConcat) returns (bool) {
        return activeContractRecordConcat[_contractRecordConcat];
    }

    // Checks if this contract address is the owner of the item for the auction
    function activateAuction(uint auctionId) onlySeller(auctionId) returns (bool){
        Auction a = auctions[auctionId];

        if (!partyOwnsAsset(this, a.contractAddress, a.recordId)) throw;

        a.status = AuctionStatus.Active;
        AuctionActivated(auctionId);
        return true;
    }

    function cancelAuction(uint auctionId) onlySeller(auctionId) returns (bool) {
        Auction a = auctions[auctionId];

        if (!partyOwnsAsset(this, a.contractAddress, a.recordId)) throw;
        if (a.currentBid >= a.reservePrice) throw;   // Can't cancel the auction if someone has already outbid the reserve.

        Asset asset = Asset(a.contractAddress);
        if(!asset.setOwner(a.recordId, a.seller)) {
            throw;
        }

        // Refund to the bidder
        uint bidsLength = a.bids.length;
        if (bidsLength > 0) {
            Bid topBid = a.bids[bidsLength - 1];
            refunds[topBid.bidder] += topBid.amount;

            activeContractRecordConcat[strConcat(addrToString(a.contractAddress), a.recordId)] = false;
        }

        AuctionCancelled(auctionId);
        a.status = AuctionStatus.Inactive;
        return true;
    }

    /* BIDS */
    function getBidCountForAuction(uint auctionId) returns (uint) {
        Auction a = auctions[auctionId];
        return a.bids.length;
    }

    function getBidForAuctionByIdx(uint auctionId, uint idx) returns (address bidder, uint256 amount, uint timestamp) {
        Auction a = auctions[auctionId];
        if(idx > a.bids.length - 1) {
            throw;
        }

        Bid b = a.bids[idx];
        return (b.bidder, b.amount, b.timestamp);
    }

    function placeBid(uint auctionId) payable onlyLive(auctionId) returns (bool success) {
        uint256 amount = msg.value;
        Auction a = auctions[auctionId];

        if (a.currentBid >= amount) throw;

        uint bidIdx = a.bids.length++;
        Bid b = a.bids[bidIdx];
        b.bidder = msg.sender;
        b.amount = amount;
        b.timestamp = now;
        a.currentBid = amount;

        auctionsBidOnByUser[b.bidder].push(auctionId);

        // Log refunds for the previous bidder
        if (bidIdx > 0) {
            Bid previousBid = a.bids[bidIdx - 1];
            refunds[previousBid.bidder] += previousBid.amount;
        }

        BidPlaced(auctionId, b.bidder, b.amount);
        return true;
    }

    function getRefundValue() returns (uint) {
        return refunds[msg.sender];
    }

    function withdrawRefund() {
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        if (!msg.sender.send(refund))
            refunds[msg.sender] = refund;
    }

    function endAuction(uint auctionId) returns (bool success) {
        // Check if the auction is passed the end date
        Auction a = auctions[auctionId];
        activeContractRecordConcat[strConcat(addrToString(a.contractAddress), a.recordId)] = false;

        // Make sure auction hasn't already been ended
        if (a.status != AuctionStatus.Active) {
            LogFailure("Can not end an auction that's already ended");
            throw;
        }

        if (block.number < a.blockNumberOfDeadline) {
            LogFailure("Can not end an auction that hasn't hit the deadline yet");
            throw;
        }

        Asset asset = Asset(a.contractAddress);

        // No bids, make the auction inactive
        if (a.bids.length == 0) {
            if(!asset.setOwner(a.recordId, a.seller)) {
                throw;
            }
            a.status = AuctionStatus.Inactive;
            return true;
        }

        Bid topBid = a.bids[a.bids.length - 1];

        // If the auction hit its reserve price
        if (a.currentBid >= a.reservePrice) {
            uint distributionShare = a.currentBid * a.distributionCut / 100;  // Calculate the distribution cut
            uint sellerShare = a.currentBid - distributionShare;

            if(!asset.setOwner(a.recordId, topBid.bidder)) {
                throw;
            } // Set the items new owner

            refunds[a.distributionAddress] += distributionShare;
            refunds[a.seller] += sellerShare;

            AuctionEndedWithWinner(auctionId, topBid.bidder, a.currentBid);
        } else {
            // Return the item to the owner and the money to the top bidder
            if(!asset.setOwner(a.recordId, a.seller)) {
                throw;
            }

            refunds[topBid.bidder] += a.currentBid;

            AuctionEndedWithoutWinner(auctionId, a.currentBid, a.reservePrice);
        }

        a.status = AuctionStatus.Inactive;
        return true;
    }

    function() {
        // Don't allow ether to be sent blindly to this contract
        throw;
    }

    function strConcat(string _a, string _b) internal returns (string) {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        bytes memory ab = new bytes (_ba.length + _bb.length);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++) ab[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) ab[k++] = _bb[i];
        return string(ab);
    }

    function addrToString(address x) returns (string) {
        bytes memory b = new bytes(20);
        for (uint i = 0; i < 20; i++)
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        return string(b);
    }
}

pragma solidity ^0.4.2;

// This is the main contract that governs execution of auctions
// of non-fungible on-chain assets. Any user can initiate an auction
// for an item that conforms to the Asset interface described in
// Asset.sol

import "Asset.sol";

contract AuctionHouse {

    struct Bid {
        address bidder;
        uint256 amount;
        uint timestamp;
    }

    enum AuctionStatus {Pending, Active, Inactive}

    struct Auction {
        // Location and ownership information of the item for sale
        address seller;
        address contractAddress; // Contract where the item exists
        string recordId;         // RecordID within the contract as per the Asset interface

        // Auction metadata
        string title;
        string description;      // Optionally markdown formatted?
        uint blockNumberOfDeadline;
        AuctionStatus status;

        // Distribution bonus
        uint distributionCut;    // In percent, ie 10 is a 10% cut to the distribution address
        address distributionAddress;

        // Pricing
        uint256 startingPrice;   // In wei
        uint256 reservePrice;
        uint256 currentBid;

        Bid[] bids;
    }

    Auction[] public auctions;          // All auctions
    mapping(address => uint[]) public auctionsRunByUser; // Pointer to auctions index for auctions run by this user

    mapping(address => uint[]) public auctionsBidOnByUser; // Pointer to auctions index for auctions this user has bid on

    mapping(string => bool) activeContractRecordConcat;

    mapping(address => uint) refunds;

    address owner;

    // Events
    event AuctionCreated(uint id, string title, uint256 startingPrice, uint256 reservePrice);
    event AuctionActivated(uint id);
    event AuctionCancelled(uint id);
    event BidPlaced(uint auctionId, address bidder, uint256 amount);
    event AuctionEndedWithWinner(uint auctionId, address winningBidder, uint256 amount);
    event AuctionEndedWithoutWinner(uint auctionId, uint256 topBid, uint256 reservePrice);

    event LogFailure(string message);

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

    modifier onlySeller(uint auctionId) {
        if (auctions[auctionId].seller != msg.sender) throw;
        _;
    }

    modifier onlyLive(uint auctionId) {
        Auction a = auctions[auctionId];
        if (a.status != AuctionStatus.Active) {
            throw;
        }

        // Auction should not be over
        if (block.number >= a.blockNumberOfDeadline) {
            throw;
        }
        _;
    }

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

    // Create an auction, transfer the item to this contract, activate the auction
    function createAuction(
                           string _title,
                           string _description,
                           address _contractAddressOfAsset,
                           string _recordIdOfAsset,
                           uint _deadline,   // in blocknumber
                           uint256 _startingPrice,
                           uint256 _reservePrice,
                           uint _distributionCut,
                           address _distributionCutAddress) returns (uint auctionId) {

        // Check to see if the seller owns the asset at the contract
        if (!partyOwnsAsset(msg.sender, _contractAddressOfAsset, _recordIdOfAsset)) {
            LogFailure("Seller does not own this asset");
            throw;
        }

        // Check to see if the auction deadline is in the future
        if (block.number >= _deadline) {
            LogFailure("Block number is not in the future");
            throw;
        }

        // Price validations
        if (_startingPrice < 0 || _reservePrice < 0) {
            LogFailure("StartingPrice or ReservePrice was below zero");
            throw;
        }

        // Distribution validations
        if (_distributionCut < 0 || _distributionCut > 100) {
            LogFailure("DistributionCut is invalid");
            throw;
        }

        if (activeContractRecordConcat[strConcat(addrToString(_contractAddressOfAsset), _recordIdOfAsset)] == true) {
            LogFailure("Item already on auction");
            throw;
        }

        auctionId = auctions.length++;
        Auction a = auctions[auctionId];
        a.seller = msg.sender;
        a.contractAddress = _contractAddressOfAsset;
        a.recordId = _recordIdOfAsset;
        a.title = _title;
        a.description = _description;
        a.blockNumberOfDeadline = _deadline;
        a.status = AuctionStatus.Pending;
        a.distributionCut = _distributionCut;
        a.distributionAddress = _distributionCutAddress;
        a.startingPrice = _startingPrice;
        a.reservePrice = _reservePrice;
        a.currentBid = _startingPrice;

        auctionsRunByUser[a.seller].push(auctionId);
        activeContractRecordConcat[strConcat(addrToString(_contractAddressOfAsset), _recordIdOfAsset)] = true;

        AuctionCreated(auctionId, a.title, a.startingPrice, a.reservePrice);

        return auctionId;
    }

    function partyOwnsAsset(address _party, address _contract, string _recordId) returns (bool success) {
        Asset assetContract = Asset(_contract);
        return assetContract.owner(_recordId) == _party;
    }

    /**
     * The auction fields are indexed in the return val as follows
     * [0]  -> Auction.seller
     * [1]  -> Auction.contractAddress
     * [2]  -> Auction.recordId
     * [3]  -> Auction.title
     * [4]  -> Auction.description
     * [5]  -> Auction.blockNumberOfDeadline
     * [6]  -> Auction.distributionCut
     * [7]  -> Auction.distributionAddress
     * [8]  -> Auction.startingPrice
     * [9] -> Auction.reservePrice
     * [10] -> Auction.currentBid
     * [11] -> Auction.bids.length
     * []  -> Auction.status (Not included right now)
     */
    function getAuction(uint idx) returns (address, address, string, string, string, uint, uint, address, uint256, uint256, uint256, uint) {
        Auction a = auctions[idx];
        if (a.seller == 0) {
            throw;
        }

        return (a.seller,
                a.contractAddress,
                a.recordId,
                a.title,
                a.description,
                a.blockNumberOfDeadline,
                a.distributionCut,
                a.distributionAddress,
                a.startingPrice,
                a.reservePrice,
                a.currentBid,
                a.bids.length
                );
    }

    function getAuctionCount() returns (uint) {
        return auctions.length;
    }

    function getStatus(uint idx) returns (uint) {
        Auction a = auctions[idx];
        return uint(a.status);
    }

    function getAuctionsCountForUser(address addr) returns (uint) {
        return auctionsRunByUser[addr].length;
    }

    function getAuctionIdForUserAndIdx(address addr, uint idx) returns (uint) {
        return auctionsRunByUser[addr][idx];
    }

    function getActiveContractRecordConcat(string _contractRecordConcat) returns (bool) {
        return activeContractRecordConcat[_contractRecordConcat];
    }

    // Checks if this contract address is the owner of the item for the auction
    function activateAuction(uint auctionId) onlySeller(auctionId) returns (bool){
        Auction a = auctions[auctionId];

        if (!partyOwnsAsset(this, a.contractAddress, a.recordId)) throw;

        a.status = AuctionStatus.Active;
        AuctionActivated(auctionId);
        return true;
    }

    function cancelAuction(uint auctionId) onlySeller(auctionId) returns (bool) {
        Auction a = auctions[auctionId];

        if (!partyOwnsAsset(this, a.contractAddress, a.recordId)) throw;
        if (a.currentBid >= a.reservePrice) throw;   // Can't cancel the auction if someone has already outbid the reserve.

        Asset asset = Asset(a.contractAddress);
        if(!asset.setOwner(a.recordId, a.seller)) {
            throw;
        }

        // Refund to the bidder
        uint bidsLength = a.bids.length;
        if (bidsLength > 0) {
            Bid topBid = a.bids[bidsLength - 1];
            refunds[topBid.bidder] += topBid.amount;

            activeContractRecordConcat[strConcat(addrToString(a.contractAddress), a.recordId)] = false;
        }

        AuctionCancelled(auctionId);
        a.status = AuctionStatus.Inactive;
        return true;
    }

    /* BIDS */
    function getBidCountForAuction(uint auctionId) returns (uint) {
        Auction a = auctions[auctionId];
        return a.bids.length;
    }

    function getBidForAuctionByIdx(uint auctionId, uint idx) returns (address bidder, uint256 amount, uint timestamp) {
        Auction a = auctions[auctionId];
        if(idx > a.bids.length - 1) {
            throw;
        }

        Bid b = a.bids[idx];
        return (b.bidder, b.amount, b.timestamp);
    }

    function placeBid(uint auctionId) payable onlyLive(auctionId) returns (bool success) {
        uint256 amount = msg.value;
        Auction a = auctions[auctionId];

        if (a.currentBid >= amount) throw;

        uint bidIdx = a.bids.length++;
        Bid b = a.bids[bidIdx];
        b.bidder = msg.sender;
        b.amount = amount;
        b.timestamp = now;
        a.currentBid = amount;

        auctionsBidOnByUser[b.bidder].push(auctionId);

        // Log refunds for the previous bidder
        if (bidIdx > 0) {
            Bid previousBid = a.bids[bidIdx - 1];
            refunds[previousBid.bidder] += previousBid.amount;
        }

        BidPlaced(auctionId, b.bidder, b.amount);
        return true;
    }

    function getRefundValue() returns (uint) {
        return refunds[msg.sender];
    }

    function withdrawRefund() {
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        if (!msg.sender.send(refund))
            refunds[msg.sender] = refund;
    }

    function endAuction(uint auctionId) returns (bool success) {
        // Check if the auction is passed the end date
        Auction a = auctions[auctionId];
        activeContractRecordConcat[strConcat(addrToString(a.contractAddress), a.recordId)] = false;

        if (block.number < a.blockNumberOfDeadline) {
            LogFailure("Can not end an auction that hasn't hit the deadline yet");
            return false;
        }

        Asset asset = Asset(a.contractAddress);

        // No bids, make the auction inactive
        if (a.bids.length == 0) {
            if(!asset.setOwner(a.recordId, a.seller)) {
                throw;
            }
            a.status = AuctionStatus.Inactive;
            return true;
        }

        Bid topBid = a.bids[a.bids.length - 1];

        // If the auction hit its reserve price
        if (a.currentBid >= a.reservePrice) {
            uint distributionShare = a.currentBid * a.distributionCut / 100;  // Calculate the distribution cut
            uint sellerShare = a.currentBid - distributionShare;

            if(!asset.setOwner(a.recordId, topBid.bidder)) {
                throw;
            } // Set the items new owner

            refunds[a.distributionAddress] += distributionShare;
            refunds[a.seller] += sellerShare;

            AuctionEndedWithWinner(auctionId, topBid.bidder, a.currentBid);
        } else {
            // Return the item to the owner and the money to the top bidder
            if(!asset.setOwner(a.recordId, a.seller)) {
                throw;
            }

            refunds[topBid.bidder] += a.currentBid;

            AuctionEndedWithoutWinner(auctionId, a.currentBid, a.reservePrice);
        }

        a.status = AuctionStatus.Inactive;
        return true;
    }

    function() {
        // Don't allow ether to be sent blindly to this contract
        throw;
    }

    function strConcat(string _a, string _b) internal returns (string) {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        bytes memory ab = new bytes (_ba.length + _bb.length);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++) ab[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) ab[k++] = _bb[i];
        return string(ab);
    }

    function addrToString(address x) returns (string) {
        bytes memory b = new bytes(20);
        for (uint i = 0; i < 20; i++)
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        return string(b);
    }
}