Warning: Functions in interfaces should be declared external.

pragma solidity ^0.4.23;

/**
 * @title ItemStoreInterface
 * @author Jonathan Brown <jbrown@mix-blockchain.org>
 * @dev ItemStore implementation interface.
 */
interface ItemStoreInterface {

    /**
     * @dev A child item has been attached to this item.
     * @param itemId itemId of the parent.
     * @param child itemId of the new child.
     */
    event AddChild(bytes32 indexed itemId, bytes32 child);

    /**
     * @dev A revision has been retracted.
     * @param itemId itemId of the item.
     * @param revisionId Id of the revision.
     */
    event RetractRevision(bytes32 indexed itemId, uint revisionId);

    /**
     * @dev An entire item has been retracted. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event Retract(bytes32 indexed itemId);

    /**
     * @dev An item has been transfered to a new owner.
     * @param itemId itemId of the item.
     * @param recipient The address that now owns the item.
     */
    event Transfer(bytes32 indexed itemId, address recipient);

    /**
     * @dev An item has been disowned. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event Disown(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not updatable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotUpdatable(bytes32 indexed itemId);

    /**
     * @dev An item has been set as enforcing revisions. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetEnforceRevisions(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not retractable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotRetractable(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not transferable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotTransferable(bytes32 indexed itemId);

    /**
     * @dev Generates an itemId from sender and nonce and checks that it is unused.
     * @param nonce Nonce that this sender has never used before.
     * @return itemId itemId of the item with this sender and nonce.
     */
    function getNewItemId(bytes32 nonce) public view returns (bytes32 itemId);

    /**
     * @dev Add a child from another item store contract.
     * @param itemId itemId of parent.
     * @param childId itemId of child.
     */
    function addForeignChild(bytes32 itemId, bytes32 childId) external;

    /**
     * @dev Retract an item's latest revision. Revision 0 cannot be retracted.
     * @param itemId itemId of the item.
     */
    function retractLatestRevision(bytes32 itemId) external;

    /**
     * @dev Retract an item.
     * @param itemId itemId of the item. This itemId can never be used again.
     */
    function retract(bytes32 itemId) external;

    /**
     * @dev Enable transfer of the item to the current user.
     * @param itemId itemId of the item.
     */
    function transferEnable(bytes32 itemId) external;

    /**
     * @dev Disable transfer of the item to the current user.
     * @param itemId itemId of the item.
     */
    function transferDisable(bytes32 itemId) external;

    /**
     * @dev Transfer an item to a new user.
     * @param itemId itemId of the item.
     * @param recipient Address of the user to transfer to item to.
     */
    function transfer(bytes32 itemId, address recipient) external;

    /**
     * @dev Disown an item.
     * @param itemId itemId of the item.
     */
    function disown(bytes32 itemId) external;

    /**
     * @dev Set an item as not updatable.
     * @param itemId itemId of the item.
     */
    function setNotUpdatable(bytes32 itemId) external;

    /**
     * @dev Set an item to enforce revisions.
     * @param itemId itemId of the item.
     */
    function setEnforceRevisions(bytes32 itemId) external;

    /**
     * @dev Set an item to not be retractable.
     * @param itemId itemId of the item.
     */
    function setNotRetractable(bytes32 itemId) external;

    /**
     * @dev Set an item to not be transferable.
     * @param itemId itemId of the item.
     */
    function setNotTransferable(bytes32 itemId) external;

    /**
     * @dev Get the ABI version for this ItemStore contract.
     * @return ABI version.
     */
    function getAbiVersion() external view returns (uint);

    /**
     * @dev Get the id for this ItemStore contract.
     * @return Id of the contract.
     */
    function getContractId() external view returns (bytes8);

    /**
     * @dev Check if an itemId is in use.
     * @param itemId itemId of the item.
     * @return True if the itemId is in use.
     */
    function getInUse(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item is updatable.
     * @param itemId itemId of the item.
     * @return True if the item is updatable.
     */
    function getUpdatable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item enforces revisions.
     * @param itemId itemId of the item.
     * @return True if the item enforces revisions.
     */
    function getEnforceRevisions(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item is retractable.
     * @param itemId itemId of the item.
     * @return retractable True if the item is item retractable.
     */
    function getRetractable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item is transferable.
     * @param itemId itemId of the item.
     * @return True if the item is transferable.
     */
    function getTransferable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Get the owner of an item.
     * @param itemId itemId of the item.
     * @return Owner of the item.
     */
    function getOwner(bytes32 itemId) external view returns (address);

    /**
     * @dev Get the number of revisions an item has.
     * @param itemId itemId of the item.
     * @return How many revisions the item has.
     */
    function getRevisionCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get the number of parents an item has.
     * @param itemId itemId of the item.
     * @return How many parents the item has.
     */
    function getParentCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get a specific parent
     * @param itemId itemId of the item.
     * @param i Index of the parent.
     * @return itemId of the parent.
     */
    function getParentId(bytes32 itemId, uint i) external view returns (bytes32);

    /**
     * @dev Get the number of children an item has.
     * @param itemId itemId of the item.
     * @return How many children the item has.
     */
    function getChildCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get a specific child
     * @param itemId itemId of the item.
     * @param i Index of the child.
     * @return itemId of the child.
     */
    function getChildId(bytes32 itemId, uint i) external view returns (bytes32);

}

pragma solidity ^0.4.23;

/**
 * @title ItemStoreInterface
 * @author Jonathan Brown <jbrown@mix-blockchain.org>
 * @dev ItemStore implementation interface.
 */
interface ItemStoreInterface {

    /**
     * @dev A child item has been attached to this item.
     * @param itemId itemId of the parent.
     * @param child itemId of the new child.
     */
    event AddChild(bytes32 indexed itemId, bytes32 child);

    /**
     * @dev A revision has been retracted.
     * @param itemId itemId of the item.
     * @param revisionId Id of the revision.
     */
    event RetractRevision(bytes32 indexed itemId, uint revisionId);

    /**
     * @dev An entire item has been retracted. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event Retract(bytes32 indexed itemId);

    /**
     * @dev An item has been transfered to a new owner.
     * @param itemId itemId of the item.
     * @param recipient The address that now owns the item.
     */
    event Transfer(bytes32 indexed itemId, address recipient);

    /**
     * @dev An item has been disowned. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event Disown(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not updatable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotUpdatable(bytes32 indexed itemId);

    /**
     * @dev An item has been set as enforcing revisions. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetEnforceRevisions(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not retractable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotRetractable(bytes32 indexed itemId);

    /**
     * @dev An item has been set as not transferable. This cannot be undone.
     * @param itemId itemId of the item.
     */
    event SetNotTransferable(bytes32 indexed itemId);

    /**
     * @dev Generates an itemId from sender and nonce and checks that it is unused.
     * @param nonce Nonce that this sender has never used before.
     * @return itemId itemId of the item with this sender and nonce.
     */
    function getNewItemId(bytes32 nonce) public view returns (bytes32 itemId);

    /**
     * @dev Add a child from another item store contract.
     * @param itemId itemId of parent.
     * @param childId itemId of child.
     */
    function addForeignChild(bytes32 itemId, bytes32 childId) external;

    /**
     * @dev Retract an item's latest revision. Revision 0 cannot be retracted.
     * @param itemId itemId of the item.
     */
    function retractLatestRevision(bytes32 itemId) external;

    /**
     * @dev Retract an item.
     * @param itemId itemId of the item. This itemId can never be used again.
     */
    function retract(bytes32 itemId) external;

    /**
     * @dev Enable transfer of the item to the current user.
     * @param itemId itemId of the item.
     */
    function transferEnable(bytes32 itemId) external;

    /**
     * @dev Disable transfer of the item to the current user.
     * @param itemId itemId of the item.
     */
    function transferDisable(bytes32 itemId) external;

    /**
     * @dev Transfer an item to a new user.
     * @param itemId itemId of the item.
     * @param recipient Address of the user to transfer to item to.
     */
    function transfer(bytes32 itemId, address recipient) external;

    /**
     * @dev Disown an item.
     * @param itemId itemId of the item.
     */
    function disown(bytes32 itemId) external;

    /**
     * @dev Set an item as not updatable.
     * @param itemId itemId of the item.
     */
    function setNotUpdatable(bytes32 itemId) external;

    /**
     * @dev Set an item to enforce revisions.
     * @param itemId itemId of the item.
     */
    function setEnforceRevisions(bytes32 itemId) external;

    /**
     * @dev Set an item to not be retractable.
     * @param itemId itemId of the item.
     */
    function setNotRetractable(bytes32 itemId) external;

    /**
     * @dev Set an item to not be transferable.
     * @param itemId itemId of the item.
     */
    function setNotTransferable(bytes32 itemId) external;

    /**
     * @dev Get the ABI version for this ItemStore contract.
     * @return ABI version.
     */
    function getAbiVersion() external view returns (uint);

    /**
     * @dev Get the id for this ItemStore contract.
     * @return Id of the contract.
     */
    function getContractId() external view returns (bytes8);

    /**
     * @dev Check if an itemId is in use.
     * @param itemId itemId of the item.
     * @return True if the itemId is in use.
     */
    function getInUse(bytes32 itemId) public view returns (bool);

    /**
     * @dev Determine if an item is updatable.
     * @param itemId itemId of the item.
     * @return True if the item is updatable.
     */
    function getUpdatable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item enforces revisions.
     * @param itemId itemId of the item.
     * @return True if the item enforces revisions.
     */
    function getEnforceRevisions(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item is retractable.
     * @param itemId itemId of the item.
     * @return retractable True if the item is item retractable.
     */
    function getRetractable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Determine if an item is transferable.
     * @param itemId itemId of the item.
     * @return True if the item is transferable.
     */
    function getTransferable(bytes32 itemId) external view returns (bool);

    /**
     * @dev Get the owner of an item.
     * @param itemId itemId of the item.
     * @return Owner of the item.
     */
    function getOwner(bytes32 itemId) external view returns (address);

    /**
     * @dev Get the number of revisions an item has.
     * @param itemId itemId of the item.
     * @return How many revisions the item has.
     */
    function getRevisionCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get the number of parents an item has.
     * @param itemId itemId of the item.
     * @return How many parents the item has.
     */
    function getParentCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get a specific parent
     * @param itemId itemId of the item.
     * @param i Index of the parent.
     * @return itemId of the parent.
     */
    function getParentId(bytes32 itemId, uint i) external view returns (bytes32);

    /**
     * @dev Get the number of children an item has.
     * @param itemId itemId of the item.
     * @return How many children the item has.
     */
    function getChildCount(bytes32 itemId) external view returns (uint);

    /**
     * @dev Get a specific child
     * @param itemId itemId of the item.
     * @param i Index of the child.
     * @return itemId of the child.
     */
    function getChildId(bytes32 itemId, uint i) external view returns (bytes32);

}


refactor(ERC165Checker) replaced assembly code with staticcall() (#1829)

* refactor(ERC165Checker) replaced assembly code with function

* returned false if result.length==0

* trigger ci

* updated ERC165Checker to return false if result.length < 32

pragma solidity ^0.5.10;

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function _supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return _supportsERC165(account) &&
            _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!_supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with the `supportsERC165` method in this library.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        // success determines whether the staticcall succeeded and result determines
        // whether the contract at account indicates support of _interfaceId
        (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);

        return (success && result);
    }

    /**
     * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return success true if the STATICCALL succeeded, false otherwise
     * @return result true if the STATICCALL succeeded and the contract at account
     * indicates support of the interface with identifier interfaceId, false otherwise
     */
    function _callERC165SupportsInterface(address account, bytes4 interfaceId)
        private
        view
        returns (bool, bool)
    {
        bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
        (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams);
        if (result.length < 32) return (false, false);
        return (success, abi.decode(result, (bool)));
    }
}

pragma solidity ^0.5.0;

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function _supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return _supportsERC165(account) &&
            _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!_supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with the `supportsERC165` method in this library.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        // success determines whether the staticcall succeeded and result determines
        // whether the contract at account indicates support of _interfaceId
        (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);

        return (success && result);
    }

    /**
     * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return success true if the STATICCALL succeeded, false otherwise
     * @return result true if the STATICCALL succeeded and the contract at account
     * indicates support of the interface with identifier interfaceId, false otherwise
     */
    function _callERC165SupportsInterface(address account, bytes4 interfaceId)
        private
        view
        returns (bool success, bool result)
    {
        bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);

        // solhint-disable-next-line no-inline-assembly
        assembly {
            let encodedParams_data := add(0x20, encodedParams)
            let encodedParams_size := mload(encodedParams)

            let output := mload(0x40)    // Find empty storage location using "free memory pointer"
            mstore(output, 0x0)

            success := staticcall(
                30000,                   // 30k gas
                account,                 // To addr
                encodedParams_data,
                encodedParams_size,
                output,
                0x20                     // Outputs are 32 bytes long
            )

            result := mload(output)      // Load the result
        }
    }
}


Moves User contract creation into conditional statement

This avoids calling the User contract unnecessarily in the case of the username already existing.

import "SequenceList.sol";
import "User.sol";

contract UserManager {
    SequenceList list = new SequenceList();

    /* TODO extend with eventObject if possible; `bytes32[]`? */
    event ActionEvent(address indexed userAddr, bytes32 actionType);
    function registerActionEvent(bytes32 actionType) {
      ActionEvent(msg.sender, actionType);
    }

    function addUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _password
        )
        returns (address)
        {
            registerActionEvent("ADD USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;

            bool isOverwrite = list.exists(key);
            // if this would be an overwrite -> return null address
            if (isOverwrite) {
                return 0x0;
            } else {
                User u = new User(_id, _username, _email, _name, _password);
                list.insert(key, u);
                return u;
            }
    }

    function updateUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _password
        )
        returns (bool success)
        {
            registerActionEvent("UPDATE USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;
            User u = new User(_id, _username, _email, _name, _password);

            bool exists = list.exists(key);
            // if record does not exist -> return null address
            if (!exists) {
                return false;
            } else {
                bool isOverwrite = list.insert(key, u);
                return isOverwrite;
            }
    }

    function isUsernameTaken(bytes32 _username) constant returns (bool) {
        registerActionEvent("IS USERNAME TAKEN");
        return list.exists(_username);
    }

    function getUserListSize() constant returns (uint) {
        registerActionEvent("GET USERLIST SIZE");
        return list.size();

    }

    function getUserAddress(bytes32 username) constant returns (address) {
        registerActionEvent("GET USER ADDRESS");
        return list.value(username);
    }

    function getUserTaskAtIndex(address userAddr, uint idx) returns (address, uint) {
        return User(userAddr).getUserTaskAtIndex(idx);
    }
}

import "SequenceList.sol";
import "User.sol";

contract UserManager {
    SequenceList list = new SequenceList();

    /* TODO extend with eventObject if possible; `bytes32[]`? */
    event ActionEvent(address indexed userAddr, bytes32 actionType);
    function registerActionEvent(bytes32 actionType) {
      ActionEvent(msg.sender, actionType);
    }

    function addUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _password
        )
        returns (address)
        {
            registerActionEvent("ADD USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;
            User u = new User(_id, _username, _email, _name, _password);

            bool isOverwrite = list.exists(key);
            // if this would be an overwrite -> return null address
            if (isOverwrite) {
                return 0x0;
            } else {
                list.insert(key, u);
                return u;
            }
    }

    function updateUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _password
        )
        returns (bool success)
        {
            registerActionEvent("UPDATE USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;
            User u = new User(_id, _username, _email, _name, _password);

            bool exists = list.exists(key);
            // if record does not exist -> return null address
            if (!exists) {
                return false;
            } else {
                bool isOverwrite = list.insert(key, u);
                return isOverwrite;
            }
    }

    function isUsernameTaken(bytes32 _username) constant returns (bool) {
        registerActionEvent("IS USERNAME TAKEN");
        return list.exists(_username);
    }

    function getUserListSize() constant returns (uint) {
        registerActionEvent("GET USERLIST SIZE");
        return list.size();

    }

    function getUserAddress(bytes32 username) constant returns (address) {
        registerActionEvent("GET USER ADDRESS");
        return list.value(username);
    }

    function getUserTaskAtIndex(address userAddr, uint idx) returns (address, uint) {
        return User(userAddr).getUserTaskAtIndex(idx);
    }
}


contracts/KetherNFTRenderV2.sol: New renderer with background

//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import '@openzeppelin/contracts/utils/Strings.sol';

import "./IKetherHomepage.sol";

import "base64-sol/base64.sol";

interface ITokenRenderer {
    function tokenURI(IKetherHomepage instance, uint256 tokenId) external view returns (string memory);
}

contract KetherNFTRenderV2 is ITokenRenderer {
  using Strings for uint;

  string bgURI;

  constructor(string memory _bgURI) {
    bgURI = _bgURI;
  }

  function renderImage(IKetherHomepage instance, uint256 tokenId) public view returns (string memory) {
    (,uint x, uint y, uint width, uint height,,,,,) = instance.ads(tokenId);

    return Base64.encode(abi.encodePacked(
      '<svg width="1000" height="1100" viewBox="0 0 1000 1110" xmlns="http://www.w3.org/2000/svg" style="background:#4a90e2">',
        '<style>text { font: bold 30px sans-serif; fill: rgba(255,255,255,0.8); }</style>',
        '<text x="5" y="34">Thousand Ether Homepage</text>',
        '<text x="1000" y="34" text-anchor="end">#', tokenId.toString(),'</text>',
        _renderGrid(bgURI, x, y, width, height),
        '<text x="5" y="1085">Size ',width.toString(),'x',height.toString(),'</text>',
        '<text x="1000" y="1085" text-anchor="end">Position [',x.toString(),',',y.toString(),']</text>',
      '</svg>'));
  }

  function _renderGrid(string memory _bgURI, uint x, uint y, uint width, uint height) internal pure returns (bytes memory) {
    // Workaround for underflow
    string memory xOffset = "-1";
    if (x > 0) xOffset = (x-1).toString();
    string memory yOffset = "-1";
    if (y > 0) yOffset = (y-1).toString();

    return abi.encodePacked(
      '<svg y="50" width="1000" height="1000" viewBox="0 0 100 100">',
        '<rect width="100" height="100" fill="white"></rect>',
        '<image width="100" height="100" href="', _bgURI,'" opacity="0.2" />',
        '<rect x="',xOffset,'" y="',yOffset,'" width="',(width+2).toString(),'" height="',(height+2).toString(),'" fill="rgba(255,255,255,0.5)" rx="1" stroke="rgba(66,185,131,0.1)" />',
        '<rect x="',x.toString(),'" y="',y.toString(),'" width="',width.toString(),'" height="',height.toString(),'" fill="rgb(66,185,131)"></rect>',
      '</svg>');
  }

  // Thanks to @townsendsam for giving us this reference https://gist.github.com/townsendsam/df2c420accb5ae786e856c97d13a2de6
  function _generateAttributes(uint x, uint y, uint width, uint height, bool NSFW, bool forceNSFW) internal pure returns (string memory) {
    string memory filter = '';

    if (NSFW || forceNSFW) {
      filter = ',{"trait_type": "Filter", "value": "NSFW"}';
    }

    string memory adminOverride = '';

    if (forceNSFW) {
      adminOverride = ',{"trait_type": "Admin Override", "value": "Forced NSFW"}';
    }

    return string(abi.encodePacked(
      '[',
         '{',
            '"trait_type": "X",',
            '"value": ', x.toString(),
          '},',
          '{',
              '"trait_type": "Y",',
              '"value": ', y.toString(),
          '},',
          '{',
              '"trait_type": "Width",',
              '"value": ', width.toString(),
          '},',
          '{',
              '"trait_type": "Height",',
              '"value": ', height.toString(),
          '},',
          '{',
              '"trait_type": "Pixels",',
              '"value": ', (height * width).toString(),
          '}',
          filter,
          adminOverride,
      ']'
    ));
  }

  function _boolToString(bool val) internal pure returns (string memory) {
      return val ? "true" : "false";
  }

  function tokenURI(IKetherHomepage instance, uint256 tokenId) public view override(ITokenRenderer) returns (string memory) {
    (,uint x,uint y,uint width,uint height,,,,bool NSFW,bool forceNSFW) = instance.ads(tokenId);

    // Units are 1/10
    x *= 10;
    y *= 10;
    width *= 10;
    height *= 10;

    return string(
      abi.encodePacked(
        'data:application/json;base64,',
        Base64.encode(bytes(abi.encodePacked(
              '{"name":"Ad #', tokenId.toString(), ': ', width.toString(), 'x', height.toString(), ' at [', x.toString(), ',', y.toString(), ']"',
              ',"description":"This NFT represents an ad unit on thousandetherhomepage.com, the owner of the NFT controls the content of this ad unit."',
              ',"external_url":"https://thousandetherhomepage.com"',
              ',"image":"data:image/svg+xml;base64,', renderImage(instance, tokenId), '"',
              ',"attributes":', _generateAttributes(x, y, width, height, NSFW, forceNSFW),
              '}'
        )))
      )
    );
  }
}

error: pathspec 'contracts/KetherNFTRenderV2.sol' did not match any file(s) known to git


Added documentation about hardcoded values in fixedExp

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Possibly support dynamic precision in the future
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint8 constant PRECISION = 32;  // fractional bits
    uint256 constant FIXED_ONE = uint256(1) << PRECISION; // 0x100000000
    uint256 constant FIXED_TWO = uint256(2) << PRECISION; // 0x200000000

    string public version = '0.1';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        var resN = power(baseN, _reserveBalance, _reserveRatio, 100);

        temp = safeMul(_supply, resN) / FIXED_ONE;

        var result =  safeSub(temp, _supply);
        //From the result, we deduct the minimal increment, which is a
        // function of S and precision.
        return safeSub(result, _supply/0x100000000);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseN = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseN);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        var resN = power(_supply, baseN, 100, _reserveRatio);

        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, FIXED_ONE);

        var result = safeSub(temp1, temp2) / resN;

        //From the result, we deduct the minimal increment, which is a
        // function of R and precision.
        return safeSub(result, _reserveBalance/0x100000000);
    }

    /**
        @dev Calculate (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by PRECISION

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) constant returns (uint256 resN) {
        uint256 logbase = ln(_baseN, _baseD);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        resN = fixedExp(safeMul(logbase, _expN) / _expD);
        return resN;
	}

    /**
        input range:
            - numerator: [1, uint256_max >> PRECISION]
            - denominator: [1, uint256_max >> PRECISION]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function ln(uint256 _numerator, uint256 _denominator) constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper 32 bits are scaled off by PRECISION
        assert(_numerator & 0xffffffff00000000000000000000000000000000000000000000000000000000 == 0);
        assert(_denominator & 0xffffffff00000000000000000000000000000000000000000000000000000000 == 0);

        return fixedLoge( (_numerator * FIXED_ONE) / _denominator);
    }

    /**
        input range:
            [0x100000000,uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function fixedLoge(uint256 _x) constant returns (uint256 logE) {
        /*
        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)

        */
        //Cannot represent negative numbers (below 1)
        assert(_x >= FIXED_ONE);

        uint256 log2 = fixedLog2(_x);
        logE = (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000,uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x) constant returns (uint256) {
        // Numbers below 1 are negative.
        assert( _x >= FIXED_ONE);

        uint256 hi = 0;
        while (_x >= FIXED_TWO) {
            _x >>= 1;
            hi += FIXED_ONE;
        }

        for (uint8 i = 0; i < PRECISION; ++i) {
            _x = (_x * _x) / FIXED_ONE;
            if (_x >= FIXED_TWO) {
                _x >>= 1;
                hi += uint256(1) << (PRECISION - 1 - i);
            }
        }

        return hi;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which
        asserts instead of overflows
    */
    function fixedExp(uint256 _x) constant returns (uint256) {
        assert(_x <= 0x386bfdba29);
        return fixedExpUnsafe(_x);
    }

    /**
        fixedExp
        Calculates e^x according to maclauren summation:

        e^x = 1+x+x^2/2!...+x^n/n!

        and returns e^(x>>32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.

        The values in this method been generated via the following python snippet:

        def calculateFactorials():
            """Method to print out the factorials for fixedExp"""

            ni = []
            ni.append( 295232799039604140847618609643520000000) # 34!
            ITERATIONS = 34
            for n in range( 1,  ITERATIONS,1 ) :
                ni.append(math.floor(ni[n - 1] / n))
            print( "\n        ".join(["xi = (xi * _x) >> PRECISION;\n        res += xi * %s;" % hex(int(x)) for x in ni]))

    */
    function fixedExpUnsafe(uint256 _x) constant returns (uint256) {

        uint256 xi = FIXED_ONE;
        uint256 res = 0xde1bc4d19efcac82445da75b00000000 * xi;

        xi = (xi * _x) >> PRECISION;
        res += xi * 0xde1bc4d19efcb0000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x6f0de268cf7e58000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x2504a0cd9a7f72000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9412833669fdc800000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1d9d4d714865f500000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x4ef8ce836bba8c0000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xb481d807d1aa68000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x16903b00fa354d000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x281cdaac677b3400000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x402e2aad725eb80000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x5d5a6c9f31fe24000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x7c7890d442a83000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9931ed540345280000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaf147cf24ce150000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867d000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867d00000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xafc441338061b8000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9c3cabbc0056e000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x839168328705c80000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x694120286c04a0000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x50319e98b3d2c400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x3a52a1e36b82020;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x289286e0fce002;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x650139600;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x8c40;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x462;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }
}

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Possibly support dynamic precision in the future
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint8 constant PRECISION = 32;  // fractional bits
    uint256 constant FIXED_ONE = uint256(1) << PRECISION; // 0x100000000
    uint256 constant FIXED_TWO = uint256(2) << PRECISION; // 0x200000000

    string public version = '0.1';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        var resN = power(baseN, _reserveBalance, _reserveRatio, 100);

        temp = safeMul(_supply, resN) / FIXED_ONE;

        var result =  safeSub(temp, _supply);
        //From the result, we deduct the minimal increment, which is a
        // function of S and precision.
        return safeSub(result, _supply/0x100000000);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseN = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseN);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        var resN = power(_supply, baseN, 100, _reserveRatio);

        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, FIXED_ONE);

        var result = safeSub(temp1, temp2) / resN;

        //From the result, we deduct the minimal increment, which is a
        // function of R and precision.
        return safeSub(result, _reserveBalance/0x100000000);
    }

    /**
        @dev Calculate (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by PRECISION

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) constant returns (uint256 resN) {
        uint256 logbase = ln(_baseN, _baseD);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        resN = fixedExp(safeMul(logbase, _expN) / _expD);
        return resN;
	}

    /**
        input range:
            - numerator: [1, uint256_max >> PRECISION]
            - denominator: [1, uint256_max >> PRECISION]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function ln(uint256 _numerator, uint256 _denominator) constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper 32 bits are scaled off by PRECISION
        assert(_numerator & 0xffffffff00000000000000000000000000000000000000000000000000000000 == 0);
        assert(_denominator & 0xffffffff00000000000000000000000000000000000000000000000000000000 == 0);

        return fixedLoge( (_numerator * FIXED_ONE) / _denominator);
    }

    /**
        input range:
            [0x100000000,uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function fixedLoge(uint256 _x) constant returns (uint256 logE) {
        /*
        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)

        */
        //Cannot represent negative numbers (below 1)
        assert(_x >= FIXED_ONE);

        uint256 log2 = fixedLog2(_x);
        logE = (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000,uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x) constant returns (uint256) {
        // Numbers below 1 are negative.
        assert( _x >= FIXED_ONE);

        uint256 hi = 0;
        while (_x >= FIXED_TWO) {
            _x >>= 1;
            hi += FIXED_ONE;
        }

        for (uint8 i = 0; i < PRECISION; ++i) {
            _x = (_x * _x) / FIXED_ONE;
            if (_x >= FIXED_TWO) {
                _x >>= 1;
                hi += uint256(1) << (PRECISION - 1 - i);
            }
        }

        return hi;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which
        asserts instead of overflows
    */
    function fixedExp(uint256 _x) constant returns (uint256) {
        assert(_x <= 0x386bfdba29);
        return fixedExpUnsafe(_x);
    }

    /**
        fixedExp
        Calculates e^x according to maclauren summation:

        e^x = 1+x+x^2/2!...+x^n/n!

        and returns e^(x>>32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.
    */
    function fixedExpUnsafe(uint256 _x) constant returns (uint256) {

        uint256 xi = FIXED_ONE;
        uint256 res = 0xde1bc4d19efcac82445da75b00000000 * xi;

        xi = (xi * _x) >> PRECISION;
        res += xi * 0xde1bc4d19efcb0000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x6f0de268cf7e58000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x2504a0cd9a7f72000000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9412833669fdc800000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1d9d4d714865f500000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x4ef8ce836bba8c0000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xb481d807d1aa68000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x16903b00fa354d000000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x281cdaac677b3400000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x402e2aad725eb80000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x5d5a6c9f31fe24000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x7c7890d442a83000000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9931ed540345280000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaf147cf24ce150000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867d000000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867d00000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xafc441338061b8000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9c3cabbc0056e000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x839168328705c80000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x694120286c04a0000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x50319e98b3d2c400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x3a52a1e36b82020;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x289286e0fce002;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x650139600;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x8c40;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x462;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }
}


Made constant functions constant

Made constant functions constant

pragma solidity ^0.4.0;
contract ItemTracking {

    struct Item {
        uint id;
        address owner;
        uint[] components;
        bool exists;
        bool created;
    }

    mapping(uint => Item) items;

    modifier itemCreated(uint id) {
        if (items[id].created == false) {
            throw;
        }
        _;
    }

    modifier itemNotCreated(uint id) {
        if (items[id].created) {
            throw;
        }
        _;
    }

    modifier itemExists(uint id) {
        if (items[id].exists == false) {
            throw;
        }
        _;
    }

    modifier itemsExist(uint[] ids) {
        for (uint i = 0; i < ids.length; i++) {
            if (items[ids[i]].exists == false) {
                throw;
            }
        }
        _;
    }

    modifier itemOwnedBySender(uint id) {
        if (items[id].owner != msg.sender) {
            throw;
        }
        _;
    }

    modifier itemsOwnedBySender(uint[] ids) {
        for (uint i = 0; i < ids.length; i++) {
            if (items[ids[i]].owner != msg.sender) {
                throw;
            }
        }
        _;
    }

    modifier itemIsCombined(uint id) {
        if (items[id].components.length < 2) {
            throw;
        }
        _;
    }

    modifier itemContainsComponents(uint id, uint[] componentIds) {

        for (uint i = 0; i < componentIds.length; i++) {
            bool componentFound = false;

            for (uint j = 0; j < items[id].components.length; j++) {
                if (items[id].components[j] == componentIds[i]) {
                    componentFound = true;
                    break;
                }
            }

            if (!componentFound) {
                throw;
            }
        }
        _;
    }

    // Create a new item
    function create(uint id)
    itemNotCreated(id) {
        items[id].id = id;
        items[id].exists = true;
        items[id].created = true;
        items[id].owner = msg.sender;
    }

    // Combine items to create a single new one
    function combine(uint[] srcIds, uint resultId)
    itemsExist(srcIds)
    itemsOwnedBySender(srcIds) {
        // Verify that at least 2 components are being combined
        if (srcIds.length < 2) {
            throw;
        }

        for (uint i = 0; i < srcIds.length; i++) {
            items[srcIds[i]].exists = false;
        }
        create(resultId);
        items[resultId].components = srcIds;
    }

    // Split a combined item into its components
    function split(uint srcId)
    itemExists(srcId)
    itemOwnedBySender(srcId)
    itemIsCombined(srcId) {
        items[srcId].exists = false;
        for (uint i = 0; i < items[srcId].components.length; i++) {
            uint componentId = items[srcId].components[i];
            items[componentId].exists = true;
            items[componentId].owner = items[srcId].owner;
        }
    }

    // A private helper function for removing a component from the components
    // array of an item. Doesn't handle error cases (e.g. invalid IDs or
    // componentId not a component of itemID). The caller should make sure that
    // input is valid.
    function removeComponent(uint itemId, uint componentId) private {
        // Find out what the components index is in parent item's component
        // listing.
        uint componentIndex = 0;
        for (uint j = 0; j < items[itemId].components.length; j++) {
            if (componentId == items[itemId].components[j]) {
                componentIndex = j;
                break;
            }
        }

        // Remove item from componentIndex. To not bloat the array, let's do
        // this by copying value from the last index to componentIndex and
        // then remove the last index.
        uint lastIndex = items[itemId].components.length - 1;
        items[itemId].components[componentIndex] = items[itemId].components[lastIndex];
        delete items[itemId].components[lastIndex];
        items[itemId].components.length--;
    }

    // Extract the sub-components listed in the parameter. Leave the rest of the
    // components in the parent item. Parent item maintains its old ID.
    // If less than 2 components would remain in the parent component, then
    // extract behaves exactly like split.
    function extract(uint srcId, uint[] toBeExtractedIds)
    itemExists(srcId)
    itemOwnedBySender(srcId)
    itemIsCombined(srcId)
    itemContainsComponents(srcId, toBeExtractedIds) {
        // If less than 2 components would remain in the parent item after
        // the extraction, perform split.
        if (items[srcId].components.length - toBeExtractedIds.length < 2) {
            split(srcId);
            return;
        }

        // Make extracted components exist and grant ownership to owner of
        // parent item. Remove extracted components from parent item's component
        // listing
        for (uint i = 0; i < toBeExtractedIds.length; i++) {
            uint componentId = toBeExtractedIds[i];
            items[componentId].exists = true;
            items[componentId].owner = items[srcId].owner;

            removeComponent(srcId, componentId);
        }
    }

    // Handover ownership of the item
    function handover(uint id, address receiver)
    itemExists(id)
    itemOwnedBySender(id) {
        items[id].owner = receiver;
    }

    // Return number of components for a given item
    function getComponentCount(uint id)
    itemCreated(id)
    constant returns (uint) {
        return items[id].components.length;
    }

    // Return ID of a component of a given parent item at given index.
    function getComponentId(uint parentId, uint componentIndex)
    itemCreated(parentId)
    itemIsCombined(parentId)
    constant returns (uint) {
        if (componentIndex >= items[parentId].components.length) {
            throw;
        }
        return items[parentId].components[componentIndex];
    }

    // Return owner of a given item
    function getOwner(uint id) itemCreated(id) constant returns (address) {
        return items[id].owner;
    }

    // Return exists status of a given item
    function getExistsStatus(uint id) itemCreated(id) constant returns (bool) {
        return items[id].exists;
    }

    // Return created status of a given item
    function getCreatedStatus(uint id) constant returns (bool) {
        return items[id].created;
    }

}

pragma solidity ^0.4.0;
contract ItemTracking {

    struct Item {
        uint id;
        address owner;
        uint[] components;
        bool exists;
        bool created;
    }

    mapping(uint => Item) items;

    modifier itemCreated(uint id) {
        if (items[id].created == false) {
            throw;
        }
        _;
    }

    modifier itemNotCreated(uint id) {
        if (items[id].created) {
            throw;
        }
        _;
    }

    modifier itemExists(uint id) {
        if (items[id].exists == false) {
            throw;
        }
        _;
    }

    modifier itemsExist(uint[] ids) {
        for (uint i = 0; i < ids.length; i++) {
            if (items[ids[i]].exists == false) {
                throw;
            }
        }
        _;
    }

    modifier itemOwnedBySender(uint id) {
        if (items[id].owner != msg.sender) {
            throw;
        }
        _;
    }

    modifier itemsOwnedBySender(uint[] ids) {
        for (uint i = 0; i < ids.length; i++) {
            if (items[ids[i]].owner != msg.sender) {
                throw;
            }
        }
        _;
    }

    modifier itemIsCombined(uint id) {
        if (items[id].components.length < 2) {
            throw;
        }
        _;
    }

    modifier itemContainsComponents(uint id, uint[] componentIds) {

        for (uint i = 0; i < componentIds.length; i++) {
            bool componentFound = false;

            for (uint j = 0; j < items[id].components.length; j++) {
                if (items[id].components[j] == componentIds[i]) {
                    componentFound = true;
                    break;
                }
            }

            if (!componentFound) {
                throw;
            }
        }
        _;
    }

    // Create a new item
    function create(uint id)
    itemNotCreated(id) {
        items[id].id = id;
        items[id].exists = true;
        items[id].created = true;
        items[id].owner = msg.sender;
    }

    // Combine items to create a single new one
    function combine(uint[] srcIds, uint resultId)
    itemsExist(srcIds)
    itemsOwnedBySender(srcIds) {
        // Verify that at least 2 components are being combined
        if (srcIds.length < 2) {
            throw;
        }

        for (uint i = 0; i < srcIds.length; i++) {
            items[srcIds[i]].exists = false;
        }
        create(resultId);
        items[resultId].components = srcIds;
    }

    // Split a combined item into its components
    function split(uint srcId)
    itemExists(srcId)
    itemOwnedBySender(srcId)
    itemIsCombined(srcId) {
        items[srcId].exists = false;
        for (uint i = 0; i < items[srcId].components.length; i++) {
            uint componentId = items[srcId].components[i];
            items[componentId].exists = true;
            items[componentId].owner = items[srcId].owner;
        }
    }

    // A private helper function for removing a component from the components
    // array of an item. Doesn't handle error cases (e.g. invalid IDs or
    // componentId not a component of itemID). The caller should make sure that
    // input is valid.
    function removeComponent(uint itemId, uint componentId) private {
        // Find out what the components index is in parent item's component
        // listing.
        uint componentIndex = 0;
        for (uint j = 0; j < items[itemId].components.length; j++) {
            if (componentId == items[itemId].components[j]) {
                componentIndex = j;
                break;
            }
        }

        // Remove item from componentIndex. To not bloat the array, let's do
        // this by copying value from the last index to componentIndex and
        // then remove the last index.
        uint lastIndex = items[itemId].components.length - 1;
        items[itemId].components[componentIndex] = items[itemId].components[lastIndex];
        delete items[itemId].components[lastIndex];
        items[itemId].components.length--;
    }

    // Extract the sub-components listed in the parameter. Leave the rest of the
    // components in the parent item. Parent item maintains its old ID.
    // If less than 2 components would remain in the parent component, then
    // extract behaves exactly like split.
    function extract(uint srcId, uint[] toBeExtractedIds)
    itemExists(srcId)
    itemOwnedBySender(srcId)
    itemIsCombined(srcId)
    itemContainsComponents(srcId, toBeExtractedIds) {
        // If less than 2 components would remain in the parent item after
        // the extraction, perform split.
        if (items[srcId].components.length - toBeExtractedIds.length < 2) {
            split(srcId);
            return;
        }

        // Make extracted components exist and grant ownership to owner of
        // parent item. Remove extracted components from parent item's component
        // listing
        for (uint i = 0; i < toBeExtractedIds.length; i++) {
            uint componentId = toBeExtractedIds[i];
            items[componentId].exists = true;
            items[componentId].owner = items[srcId].owner;

            removeComponent(srcId, componentId);
        }
    }

    // Handover ownership of the item
    function handover(uint id, address receiver)
    itemExists(id)
    itemOwnedBySender(id) {
        items[id].owner = receiver;
    }

    // Return number of components for a given item
    function getComponentCount(uint id) itemCreated(id) returns (uint) {
        return items[id].components.length;
    }

    // Return ID of a component of a given parent item at given index.
    function getComponentId(uint parentId, uint componentIndex)
    itemCreated(parentId)
    itemIsCombined(parentId)
    returns (uint) {
        if (componentIndex >= items[parentId].components.length) {
            throw;
        }
        return items[parentId].components[componentIndex];
    }

    // Return owner of a given item
    function getOwner(uint id) itemCreated(id) returns (address) {
        return items[id].owner;
    }

    // Return exists status of a given item
    function getExistsStatus(uint id) itemCreated(id) returns (bool) {
        return items[id].exists;
    }

    // Return created status of a given item
    function getCreatedStatus(uint id) returns (bool) {
        return items[id].created;
    }

}


Pack revision block numbers.

Pack revision block numbers.

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // Can the blob be updated? Cannot be enabled after creation.
        bool forceNewRevisions;     // When updating always make a new revision. Cannot be disabled after creation.
        bool retractable;           // Can the blob be retracted? Cannot be enabled after creation.
        bool disownable;            // Can the blob be disowned? Cannot be enabled after creation.
        uint32 blockNumber;         // Which block has revision 0 of this blob.
        uint32 numRevisions;        // Number of additional revisions.
        address owner;              // Who created this blob.
    }

    mapping (bytes32 => BlobInfo) idBlobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) idPackedRevisionBlockNumbers;

    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);
    event logRetract(bytes32 indexed id);
    event logDisown(bytes32 indexed id);
    event logSetNotUpdatable(bytes32 indexed id);
    event logSetForceNewRevisions(bytes32 indexed id);
    event logSetNotRetractable(bytes32 indexed id);
    event logSetNotDisownable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 constant public contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    modifier isOwner(bytes32 id) {
        if (idBlobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    modifier isUpdatable(bytes32 id) {
        if (!idBlobInfo[id].updatable) {
            throw;
        }
        _
    }

    modifier isRetractable(bytes32 id) {
        if (!idBlobInfo[id].retractable) {
            throw;
        }
        _
    }

    modifier isDisownable(bytes32 id) {
        if (!idBlobInfo[id].disownable) {
            throw;
        }
        _
    }

    function setPackedRevisionBlockNumber(bytes32 id, uint revisionId) {
        bytes32 slot = idPackedRevisionBlockNumbers[id][(revisionId - 1) / 8];
        uint multiplier = 2 ** (((revisionId - 1) % 8) * 32);
        slot &= ~bytes32(uint32(-1) * multiplier);
        slot |= bytes32(uint32(block.number) * multiplier);
        idPackedRevisionBlockNumbers[id][(revisionId - 1) / 8] = slot;
    }

    function getPackedRevisionBlockNumber(bytes32 id, uint revisionId) returns (uint blockNumber) {
        bytes32 slot = idPackedRevisionBlockNumbers[id][(revisionId - 1) / 8];
        uint offset = ((revisionId - 1) % 8) * 32;
        blockNumber = uint32(uint256(slot) / 2 ** offset);
    }

    /**
     * @dev Stores a blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @return hash Hash of sender and blob.
     */
    function store(bytes blob, bytes32 nonce, bool updatable, bool forceNewRevisions, bool retractable, bool disownable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (idBlobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        idBlobInfo[id] = BlobInfo({
            updatable: updatable,
            forceNewRevisions: forceNewRevisions,
            retractable: retractable,
            disownable: disownable,
            numRevisions: 0,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    function update(bytes32 id, bytes blob, bool newRevision) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        BlobInfo blobInfo = idBlobInfo[id];
        if (newRevision || blobInfo.forceNewRevisions) {
            setPackedRevisionBlockNumber(id, ++blobInfo.numRevisions);
        }
        else {
            if (blobInfo.numRevisions == 0) {
                blobInfo.blockNumber = uint32(block.number);
            }
            else {
                setPackedRevisionBlockNumber(id, blobInfo.numRevisions);
            }
        }
        revisionId = blobInfo.numRevisions;
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        uint numSlots = (idBlobInfo[id].numRevisions + 7) / 8;
        for (uint i = 0; i < numSlots; i++) {
            delete idPackedRevisionBlockNumbers[id][i];
        }
        // Mark this blob as retracted.
        idBlobInfo[id] = BlobInfo({
            updatable: false,
            forceNewRevisions: false,
            retractable: false,
            disownable: false,
            numRevisions: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    function disown(bytes32 id) noValue isOwner(id) isDisownable(id) external {
        // Remove the owner from the blob's state.
        delete idBlobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    function setNotUpdatable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not updatable.
        idBlobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    function setForceNewTransactions(bytes32 id) noValue isOwner(id) {
        // Record in state that all changes to this blob must be new revisions.
        idBlobInfo[id].forceNewRevisions = true;
        // Log that the blob now forces new revisions.
        logSetForceNewRevisions(id);
    }

    function setNotRetractable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not retractable.
        idBlobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    function setNotDisownable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not disownable.
        idBlobInfo[id].disownable = false;
        // Log that the blob is not disownable.
        logSetNotDisownable(id);
    }

    function getInfo(bytes32 id) noValue constant external returns (address owner, bool updatable, bool forceNewRevisions, bool retractable, bool disownable, uint numRevisions, uint latestBlockNumber) {
        owner = idBlobInfo[id].owner;
        updatable = idBlobInfo[id].updatable;
        forceNewRevisions = idBlobInfo[id].forceNewRevisions;
        retractable = idBlobInfo[id].retractable;
        disownable = idBlobInfo[id].disownable;
        numRevisions = idBlobInfo[id].numRevisions;
        latestBlockNumber = getRevisionBlockNumber(id, numRevisions);
    }

    function getOwner(bytes32 id) noValue constant external returns (address owner) {
        owner = idBlobInfo[id].owner;
    }

    function getUpdatable(bytes32 id) noValue constant external returns (bool updatable) {
        updatable = idBlobInfo[id].updatable;
    }

    function getForceNewRevisions(bytes32 id) noValue constant external returns (bool forceNewRevisions) {
        forceNewRevisions = idBlobInfo[id].forceNewRevisions;
    }

    function getRetractable(bytes32 id) noValue constant external returns (bool retractable) {
        retractable = idBlobInfo[id].retractable;
    }

    function getDisownable(bytes32 id) noValue constant external returns (bool disownable) {
        disownable = idBlobInfo[id].disownable;
    }

    function numRevisions(bytes32 id) noValue constant external returns (uint32 numRevisions) {
        numRevisions = idBlobInfo[id].numRevisions;
    }

    function getRevisionBlockNumber(bytes32 id, uint revisionId) noValue constant returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = idBlobInfo[id].blockNumber;
        }
        else {
            blockNumber = getPackedRevisionBlockNumber(id, revisionId);
        }
    }

    function() {
        throw;      // Do not maintain a balance.
    }

}

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // Can the blob be updated? Cannot be enabled after creation.
        bool forceNewRevisions;     // When updating always make a new revision. Cannot be disabled after creation.
        bool retractable;           // Can the blob be retracted? Cannot be enabled after creation.
        bool disownable;            // Can the blob be disowned? Cannot be enabled after creation.
        uint32 blockNumber;         // Which block has revision 0 of this blob.
        uint32 numRevisions;        // Number of additional revisions.
        address owner;              // Who created this blob.
    }

    mapping (bytes32 => BlobInfo) idBlobInfo;
    mapping (bytes32 => mapping (uint => uint32)) idRevisionIdBlockNumber;  // Not packed - need better compiler / evm.

    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);
    event logRetract(bytes32 indexed id);
    event logDisown(bytes32 indexed id);
    event logSetNotUpdatable(bytes32 indexed id);
    event logSetForceNewRevisions(bytes32 indexed id);
    event logSetNotRetractable(bytes32 indexed id);
    event logSetNotDisownable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 constant public contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    modifier isOwner(bytes32 id) {
        if (idBlobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    modifier isUpdatable(bytes32 id) {
        if (!idBlobInfo[id].updatable) {
            throw;
        }
        _
    }

    modifier isRetractable(bytes32 id) {
        if (!idBlobInfo[id].retractable) {
            throw;
        }
        _
    }

    modifier isDisownable(bytes32 id) {
        if (!idBlobInfo[id].disownable) {
            throw;
        }
        _
    }

    /**
     * @dev Stores a blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @return hash Hash of sender and blob.
     */
    function store(bytes blob, bytes32 nonce, bool updatable, bool forceNewRevisions, bool retractable, bool disownable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (idBlobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        idBlobInfo[id] = BlobInfo({
            updatable: updatable,
            forceNewRevisions: forceNewRevisions,
            retractable: retractable,
            disownable: disownable,
            numRevisions: 0,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    function update(bytes32 id, bytes blob, bool newRevision) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        BlobInfo blobInfo = idBlobInfo[id];
        if (newRevision || blobInfo.forceNewRevisions) {
            idRevisionIdBlockNumber[id][++blobInfo.numRevisions] = uint32(block.number);
        }
        else {
            if (blobInfo.numRevisions == 0) {
                blobInfo.blockNumber = uint32(block.number);
            }
            else {
                idRevisionIdBlockNumber[id][blobInfo.numRevisions] = uint32(block.number);
            }
        }
        revisionId = blobInfo.numRevisions;
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the revision block numbers.
        uint numRevisions = idBlobInfo[id].numRevisions;
        for (uint i = 1; i <= numRevisions; i++) {
            delete idRevisionIdBlockNumber[id][i];
        }
        // Mark this blob as retracted.
        idBlobInfo[id] = BlobInfo({
            updatable: false,
            forceNewRevisions: false,
            retractable: false,
            disownable: false,
            numRevisions: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    function disown(bytes32 id) noValue isOwner(id) isDisownable(id) external {
        // Remove the owner from the blob's state.
        delete idBlobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    function setNotUpdatable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not updatable.
        idBlobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    function setForceNewTransactions(bytes32 id) noValue isOwner(id) {
        // Record in state that all changes to this blob must be new revisions.
        idBlobInfo[id].forceNewRevisions = true;
        // Log that the blob now forces new revisions.
        logSetForceNewRevisions(id);
    }

    function setNotRetractable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not retractable.
        idBlobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    function setNotDisownable(bytes32 id) noValue isOwner(id) {
        // Record in state that the blob is not disownable.
        idBlobInfo[id].disownable = false;
        // Log that the blob is not disownable.
        logSetNotDisownable(id);
    }

    function getInfo(bytes32 id) noValue constant external returns (address owner, bool updatable, bool forceNewRevisions, bool retractable, bool disownable, uint numRevisions, uint latestBlockNumber) {
        owner = idBlobInfo[id].owner;
        updatable = idBlobInfo[id].updatable;
        forceNewRevisions = idBlobInfo[id].forceNewRevisions;
        retractable = idBlobInfo[id].retractable;
        disownable = idBlobInfo[id].disownable;
        numRevisions = idBlobInfo[id].numRevisions;
        latestBlockNumber = getRevisionBlockNumber(id, numRevisions);
    }

    function getOwner(bytes32 id) noValue constant external returns (address owner) {
        owner = idBlobInfo[id].owner;
    }

    function getUpdatable(bytes32 id) noValue constant external returns (bool updatable) {
        updatable = idBlobInfo[id].updatable;
    }

    function getForceNewRevisions(bytes32 id) noValue constant external returns (bool forceNewRevisions) {
        forceNewRevisions = idBlobInfo[id].forceNewRevisions;
    }

    function getRetractable(bytes32 id) noValue constant external returns (bool retractable) {
        retractable = idBlobInfo[id].retractable;
    }

    function getDisownable(bytes32 id) noValue constant external returns (bool disownable) {
        disownable = idBlobInfo[id].disownable;
    }

    function numRevisions(bytes32 id) noValue constant external returns (uint32 numRevisions) {
        numRevisions = idBlobInfo[id].numRevisions;
    }

    function getRevisionBlockNumber(bytes32 id, uint revisionId) noValue constant returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = idBlobInfo[id].blockNumber;
        }
        else {
            blockNumber = idRevisionIdBlockNumber[id][revisionId];
        }
    }

    function() {
        throw;      // Do not maintain a balance.
    }

}


remove unnecessary non-zero validation

remove unnecessary non-zero validation

pragma solidity ^0.4.4;

import "zeppelin-solidity/contracts/math/SafeMath.sol";

// Defines a fund raising asset contract

contract InvestmentAsset {

    using SafeMath for uint256;

    // Reference to the investment offer
    address public offerAddress;
    // Asset owner
    address public owner;
    // Asset currency
    string public currency;
    // Asset fixed value
    uint256 public fixedValue;
    // Asset buyer
    address public investor;
    // Protocol version
    string public protocolVersion;
    // The hash of agreement terms
    bytes public agreementTermsHash;

    // possible stages of an asset
    enum Status {
        AVAILABLE,
        PENDING_OWNER_AGREEMENT,
        INVESTED
    }
    Status public status;

    event Transferred(
        string _id,
        address _from,
        address _to,
        uint256 _value
    );

    event Canceled(
        string _id,
        address _owner,
        address _investor,
        uint256 _value
    );

    event Agreements(
        string _id,
        address _owner,
        address _investor,
        uint256 _value,
        bytes _terms
    );

    event Disagreements(
        string _id,
        address _owner,
        address _investor,
        uint256 _value
    );

    // Checks the current asset's status
    modifier hasStatus(Status _status) {
        require(status == _status);
        _;
    }

    // Checks if the owner is the caller
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    // Checks if the investor is the caller
    modifier onlyInvestor() {
        require(msg.sender == investor);
        _;
    }

    function InvestmentAsset(address _owner, string _protocolVersion, address _offerAddress, string _currency, uint256 _fixedValue) {
        owner = _owner;
        protocolVersion = _protocolVersion;
        offerAddress = _offerAddress;
        currency = _currency;
        fixedValue = _fixedValue;
        status = Status.AVAILABLE;
    }

    function makeAvailable()
        private
        returns(address, uint256)
    {
        uint256 investedValue = this.balance;
        investor.transfer(invested);
        address currentInvestor = investor;
        investor = address(0);
        status = Status.AVAILABLE;
        return (currentInvestor, investedValue);
    }

    // Add investment interest in this asset and retain the funds within the smart contract
    function invest(string _id, bytes _agreementTermsHash) payable
         hasStatus(Status.AVAILABLE)
         returns(bool)
    {
        investor = msg.sender;
        agreementTermsHash = _agreementTermsHash;
        status = Status.PENDING_OWNER_AGREEMENT;
        Transferred(_id, investor, owner, this.balance);
        return true;
    }

    // Cancel the pending investment and refund the investor
    function cancelInvestment(string _id)
        onlyInvestor
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        var (currentInvestor, investedValue) = makeAvailable();
        Canceled(_id, owner, currentInvestor, investedValue);
        return true;
    }

    // Agree the investor as the asset buyer and withdraw funds
    function agreeInvestment(string _id, bytes _agreementTermsHash)
        onlyOwner
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        // compare the document signed by the offer owner and investor
        if (sha3(agreementTermsHash) == sha3(_agreementTermsHash)) {
            // @todo check how to transfer all the funds
            owner.transfer();
            status = Status.INVESTED;
            Agreements(_id, owner, investor, agreementTermsHash);
            return true;
        }
    }

    // Disagree the pending investment and refund the investor
    function disagreeInvestment(string _id)
        onlyOwner
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        var (currentInvestor, investedValue) = makeAvailable();
        Disagreements(_id, owner, currentInvestor, investedValue);
        return true;
    }

}

pragma solidity ^0.4.4;

import "zeppelin-solidity/contracts/math/SafeMath.sol";

// Defines a fund raising asset contract

contract InvestmentAsset {

    using SafeMath for uint256;

    // Reference to the investment offer
    address public offerAddress;
    // Asset owner
    address public owner;
    // Asset currency
    string public currency;
    // Asset fixed value
    uint256 public fixedValue;
    // Asset buyer
    address public investor;
    // Protocol version
    string public protocolVersion;
    // The hash of agreement terms
    bytes public agreementTermsHash;

    // possible stages of an asset
    enum Status {
        AVAILABLE,
        PENDING_OWNER_AGREEMENT,
        INVESTED
    }
    Status public status;

    event Transferred(
        string _id,
        address _from,
        address _to,
        uint256 _value
    );

    event Canceled(
        string _id,
        address _owner,
        address _investor,
        uint256 _value
    );

    event Agreements(
        string _id,
        address _owner,
        address _investor,
        uint256 _value,
        bytes _terms
    );

    event Disagreements(
        string _id,
        address _owner,
        address _investor,
        uint256 _value
    );

    // Checks the current asset's status
    modifier hasStatus(Status _status) {
        require(status == _status);
        _;
    }

    // Checks if the owner is the caller
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    // Checks if the investor is the caller
    modifier onlyInvestor() {
        require(msg.sender == investor);
        _;
    }

    // Checks if the value is valid
    modifier isValidValue() {
        require(msg.value != 0);
        _;
    }

    function InvestmentAsset(address _owner, string _protocolVersion, address _offerAddress, string _currency, uint256 _fixedValue) {
        owner = _owner;
        protocolVersion = _protocolVersion;
        offerAddress = _offerAddress;
        currency = _currency;
        fixedValue = _fixedValue;
        status = Status.AVAILABLE;
    }

    function makeAvailable()
        private
        returns(address, uint256)
    {
        uint256 investedValue = this.balance;
        investor.transfer(invested);
        address currentInvestor = investor;
        investor = address(0);
        status = Status.AVAILABLE;
        return (currentInvestor, investedValue);
    }

    // Add investment interest in this asset and retain the funds within the smart contract
    function invest(string _id, bytes _agreementTermsHash) payable
         hasStatus(Status.AVAILABLE)
         returns(bool)
    {
        investor = msg.sender;
        agreementTermsHash = _agreementTermsHash;
        status = Status.PENDING_OWNER_AGREEMENT;
        Transferred(_id, investor, owner, this.balance);
        return true;
    }

    function cancelInvestment(string _id)
        onlyInvestor
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        var (currentInvestor, investedValue) = makeAvailable();
        Canceled(_id, owner, currentInvestor, investedValue);
        return true;
    }

    // Agree the investor as the asset buyer and withdraw funds
    function agreeInvestment(string _id, bytes _agreementTermsHash)
        onlyOwner
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        // compare the document signed by the offer owner and investor
        if (sha3(agreementTermsHash) == sha3(_agreementTermsHash)) {
            // @todo check how to transfer all the funds
            owner.transfer();
            status = Status.INVESTED;
            Agreements(_id, owner, investor, agreementTermsHash);
            return true;
        }
    }

    // Disagree the pending investment and refund the investor
    function disagreeInvestment(string _id)
        onlyOwner
        hasStatus(Status.PENDING_OWNER_AGREEMENT)
        returns(bool)
    {
        var (currentInvestor, investedValue) = makeAvailable();
        Disagreements(_id, owner, currentInvestor, investedValue);
        return true;
    }

}