rm uneeded require calls, subtract will enforce correct balances.

/*
    Copyright 2017 Phillip A. Elsasser

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

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

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

pragma solidity 0.4.18;

import "./libraries/MathLib.sol";
import "./tokens/MarketToken.sol";
import "./Linkable.sol";
import "./MarketContract.sol";

import "zeppelin-solidity/contracts/token/SafeERC20.sol";
import "zeppelin-solidity/contracts/token/ERC20.sol";

/// @title MarketCollateralPool is a contract controlled by a specific Market Contract.  It holds collateral balances
/// as well as user balances and open positions.  It should be instantiated and then linked by a MarketContract.
/// @author Phil Elsasser <phil@marketprotcol.io>
contract MarketCollateralPool is Linkable {
    using MathLib for uint;
    using MathLib for int;
    using SafeERC20 for ERC20;

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

    struct Position {
        uint price;
        int qty;
    }

    uint public collateralPoolBalance;                                 // current balance of all collateral committed
    mapping(address => UserNetPosition) addressToUserPosition;
    mapping(address => uint) public userAddressToAccountBalance;       // stores account balances allowed to be allocated to orders
    address public MKT_TOKEN_ADDRESS;
    MarketToken MKT_TOKEN;
    MarketContract MKT_CONTRACT;

    event UpdatedUserBalance(address indexed user, uint balance);
    event UpdatedPoolBalance(uint balance);

    /// @dev instantiates a collateral pool that is unique to the supplied address of a MarketContract. This pairing
    /// is 1:1
    /// @param marketContractAddress deployed address of a MarketContract
    function MarketCollateralPool(address marketContractAddress) Linkable(marketContractAddress) public {
        MKT_CONTRACT = MarketContract(marketContractAddress);
        MKT_TOKEN_ADDRESS = MKT_CONTRACT.MKT_TOKEN_ADDRESS();
        MKT_TOKEN = MarketToken(MKT_TOKEN_ADDRESS);
    }

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

    /// @param userAddress address of user
    /// @return the users currently unallocated token balance
    function getUserAccountBalance(address userAddress) external view returns (uint) {
        return userAddressToAccountBalance[userAddress];
    }

    /*
    // EXTERNAL METHODS
    */

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

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

    /// @dev called by our linked MarketContract when a trade occurs to update both maker and takers positions.
    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(
        address maker,
        address taker,
        int qty,
        uint price
    ) external onlyLinked
    {
        updatePosition(
            maker,
            qty,
            price
        );
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(
            taker,
            qty * -1,
            price
        );
    }

    /*
    // PUBLIC METHODS
    */

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

    /*
    // PRIVATE METHODS
    */

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

    /// @notice withdraws collateral from pool to a user account upon exit or trade settlement
    /// @param toAddress address of user
    /// @param collateralAmount amount to transfer from pool to user.
    function withdrawCollateralFromPool(
        address toAddress,
        uint collateralAmount
    ) private
    {
        require(MKT_TOKEN.isUserEnabledForContract(MKT_CONTRACT, msg.sender));
        // require(collateralPoolBalance >= collateralAmount); subtract call below will enforce this!
        uint newBalance = userAddressToAccountBalance[toAddress].add(collateralAmount);
        userAddressToAccountBalance[toAddress] = newBalance;
        collateralPoolBalance = collateralPoolBalance.subtract(collateralAmount);
        UpdatedUserBalance(toAddress, newBalance);
        UpdatedPoolBalance(collateralPoolBalance);
    }

    /// @dev handles all needed internal accounting when a user enters into a new trade
    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(
        address userAddress,
        int qty,
        uint price
    ) private
    {
        UserNetPosition storage userNetPosition = addressToUserPosition[userAddress];
        if (userNetPosition.netPosition == 0 || userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos
            addUserNetPosition(
                userNetPosition,
                userAddress,
                qty,
                price
            );
        } else {  // opposite side from open position, reduce, flattened, or flipped.
            if (userNetPosition.netPosition >= qty * -1) { // pos is reduced or flattened
                reduceUserNetPosition(
                    userNetPosition,
                    userAddress,
                    qty,
                    price
                );
            } else {    // pos is flipped, reduce and then create new open pos!

                reduceUserNetPosition(
                    userNetPosition,
                    userAddress,
                    userNetPosition.netPosition * -1,
                    price
                ); // flatten completely

                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                addUserNetPosition(
                    userNetPosition,
                    userAddress,
                    newNetPos,
                    price
                );
            }
        }
        userNetPosition.netPosition = userNetPosition.netPosition.add(qty);   // keep track of total net pos across all prices for user.
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account and creates the needed Position struct to record the new position.
    /// @param userNetPosition current positions held by user
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(
        UserNetPosition storage userNetPosition,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint neededCollateral = MathLib.calculateNeededCollateral(
            MKT_CONTRACT.PRICE_FLOOR(),
            MKT_CONTRACT.PRICE_CAP(),
            MKT_CONTRACT.QTY_DECIMAL_PLACES(),
            qty,
            price
        );
        commitCollateralToPool(userAddress, neededCollateral);
        userNetPosition.positions.push(Position(price, qty));   // append array with new position
    }

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

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

/*
    Copyright 2017 Phillip A. Elsasser

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

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

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

pragma solidity 0.4.18;

import "./libraries/MathLib.sol";
import "./tokens/MarketToken.sol";
import "./Linkable.sol";
import "./MarketContract.sol";

import "zeppelin-solidity/contracts/token/SafeERC20.sol";
import "zeppelin-solidity/contracts/token/ERC20.sol";

/// @title MarketCollateralPool is a contract controlled by a specific Market Contract.  It holds collateral balances
/// as well as user balances and open positions.  It should be instantiated and then linked by a MarketContract.
/// @author Phil Elsasser <phil@marketprotcol.io>
contract MarketCollateralPool is Linkable {
    using MathLib for uint;
    using MathLib for int;
    using SafeERC20 for ERC20;

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

    struct Position {
        uint price;
        int qty;
    }

    uint public collateralPoolBalance;                                 // current balance of all collateral committed
    mapping(address => UserNetPosition) addressToUserPosition;
    mapping(address => uint) public userAddressToAccountBalance;       // stores account balances allowed to be allocated to orders
    address public MKT_TOKEN_ADDRESS;
    MarketToken MKT_TOKEN;
    MarketContract MKT_CONTRACT;

    event UpdatedUserBalance(address indexed user, uint balance);
    event UpdatedPoolBalance(uint balance);

    /// @dev instantiates a collateral pool that is unique to the supplied address of a MarketContract. This pairing
    /// is 1:1
    /// @param marketContractAddress deployed address of a MarketContract
    function MarketCollateralPool(address marketContractAddress) Linkable(marketContractAddress) public {
        MKT_CONTRACT = MarketContract(marketContractAddress);
        MKT_TOKEN_ADDRESS = MKT_CONTRACT.MKT_TOKEN_ADDRESS();
        MKT_TOKEN = MarketToken(MKT_TOKEN_ADDRESS);
    }

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

    /// @param userAddress address of user
    /// @return the users currently unallocated token balance
    function getUserAccountBalance(address userAddress) external view returns (uint) {
        return userAddressToAccountBalance[userAddress];
    }

    /*
    // EXTERNAL METHODS
    */

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

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

    /// @dev called by our linked MarketContract when a trade occurs to update both maker and takers positions.
    /// @param maker address of the maker in the trade
    /// @param taker address of the taker in the trade
    /// @param qty quantity transacted between parties
    /// @param price agreed price of the matched trade.
    function updatePositions(
        address maker,
        address taker,
        int qty,
        uint price
    ) external onlyLinked
    {
        updatePosition(
            maker,
            qty,
            price
        );
        // continue process for taker, but qty is opposite sign for taker
        updatePosition(
            taker,
            qty * -1,
            price
        );
    }

    /*
    // PUBLIC METHODS
    */

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

    /*
    // PRIVATE METHODS
    */

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

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

    /// @dev handles all needed internal accounting when a user enters into a new trade
    /// @param userAddress storage struct containing position information for this user
    /// @param qty signed quantity this users position is changing by, + for buy and - for sell
    /// @param price transacted price of the new position / trade
    function updatePosition(
        address userAddress,
        int qty,
        uint price
    ) private
    {
        UserNetPosition storage userNetPosition = addressToUserPosition[userAddress];
        if (userNetPosition.netPosition == 0 || userNetPosition.netPosition.isSameSign(qty)) {
            // new position or adding to open pos
            addUserNetPosition(
                userNetPosition,
                userAddress,
                qty,
                price
            );
        } else {  // opposite side from open position, reduce, flattened, or flipped.
            if (userNetPosition.netPosition >= qty * -1) { // pos is reduced or flattened
                reduceUserNetPosition(
                    userNetPosition,
                    userAddress,
                    qty,
                    price
                );
            } else {    // pos is flipped, reduce and then create new open pos!

                reduceUserNetPosition(
                    userNetPosition,
                    userAddress,
                    userNetPosition.netPosition * -1,
                    price
                ); // flatten completely

                int newNetPos = userNetPosition.netPosition + qty;            // the portion remaining after flattening
                addUserNetPosition(
                    userNetPosition,
                    userAddress,
                    newNetPos,
                    price
                );
            }
        }
        userNetPosition.netPosition = userNetPosition.netPosition.add(qty);   // keep track of total net pos across all prices for user.
    }

    /// @dev calculates the needed collateral for a new position and commits it to the pool removing it from the
    /// users account and creates the needed Position struct to record the new position.
    /// @param userNetPosition current positions held by user
    /// @param userAddress address of user entering into the position
    /// @param qty signed quantity of the trade
    /// @param price agreed price of trade
    function addUserNetPosition(
        UserNetPosition storage userNetPosition,
        address userAddress,
        int qty,
        uint price
    ) private
    {
        uint neededCollateral = MathLib.calculateNeededCollateral(
            MKT_CONTRACT.PRICE_FLOOR(),
            MKT_CONTRACT.PRICE_CAP(),
            MKT_CONTRACT.QTY_DECIMAL_PLACES(),
            qty,
            price
        );
        commitCollateralToPool(userAddress, neededCollateral);
        userNetPosition.positions.push(Position(price, qty));   // append array with new position
    }

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

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


Remove misleading SafeMath comment

Remove misleading SafeMath comment

pragma solidity ^0.6.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

pragma solidity ^0.6.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}


Certificate - omit public

Certificate - omit public

import {User} from "./User.sol";
import {Participant} from "./Participant.sol";
import {ParticipantAuthority} from "./ParticipantAuthority.sol";
import {UserState} from "./UserState.sol";

contract Certificate {

	address public owner;

	enum State {
		/*
		Pending: certificate has been created, but awaiting signatures from issuer and either importer or exporter
		Issued: all signatures received, certificate is valid.
		Completed: shipment validated upon border crossing
		Expired: shipment has expired without receiving a 'completed' Event
		*/
		Pending, Issued, Expired
	}
	State private state = State.Pending;

	struct Dates {
		//date the certificate is created + requested
		uint creation;

		//date the certificate is signed by all parties and is officially issued, becoming valid
		uint issue;

		//date the shipment is certified by the importing authority
		uint completion;

		//default expiration date of the certificate, exercised only if shipment never verified by importing authority
		uint expiration;
	}
	Dates public dates = Dates(now, 0, 0, 0);

	//Participants in the KP: member countries of source and destination
	struct Participants {
		address[] origins; //the declared origin of the goods
		address source; //the country we are exporting from
		address destination; //the country we are importing to
	}
	Participants private participants;

	//Authorities: issuing and importing
	struct Agents {
		address exporter;
		address importer;
	}
	Agents public agents;

	//the parties to the transaction: importer and exporter
	struct Parties {
		address exporter;
		address importer;
	}
	Parties public parties;

    struct Signature {
        uint date;
        address owner;
    }

    struct Signatures {
        Signature exporter;
        Signature importer;
        Signature exporterAuthority;
        Signature importerAuthority;
    }
    Signatures private signatures;

	struct Parsel {
		string carats;
		string value;
		address[] origins;
	}
	Parsel[] public parsels;

	event Requested(address indexed certificate);
	event Issued(address indexed certificate);
	event Expired(address indexed certificate);
	event Exported(address indexed certificate);
	event Imported(address indexed certificate);
    event Signed(address from, string name);

    uint public numberOfSignatures;

	/*
	Certificates should be created by the exporter: the party in possession of the goods.
	params:
	- importer - importing Party
	- exporter - exporting Party
	- participantOrigin - KPCS Participant (member country) the goods were sourced _from_ ... likely the country of geological origin
	- participantSource - KPCS Participant (member country) the goods are being sent from
	- participantDestination - KPCS Participant (member country) the goods are being sent to
	*/
    function Certificate(address _exporter,
    	address _importer,
    	address[] _participantOrigin,
    	address _participantSource,
    	address _participantDestination) {
    		owner = msg.sender;
    		parties = Parties(_exporter, _importer);
    		participants = Participants(_participantOrigin, _participantSource, _participantDestination);
    		owner = msg.sender;
            signatures = Signatures(
                Signature(now, _exporter),
                Signature(0,0x0),
                Signature(0,0x0),
                Signature(0,0x0));
            numberOfSignatures = 1;
    }

    function getNumberOfParticipantsOrigins() constant returns (uint) {
        return participants.origins.length;
    }

    function getParticipantOriginWithIndex(uint index) constant returns (address) {
        return participants.origins[index];
    }

    function getParticipantSource() constant returns (address) {
        return participants.source;
    }

    function getParticipantDestination() constant returns (address) {
        return participants.destination;
    }

    function getParticipants() constant returns (address[]) {
        address[] memory allParticipants = new address[](participants.origins.length + 2);
        allParticipants[0] = (participants.source);
        allParticipants[1] = participants.destination;
        uint origins = participants.origins.length;
        for(uint i = 0; i<origins; i++) {
            allParticipants[i + 2] = participants.origins[i];
        }
        return allParticipants;
    }

    function addParsel(string carats, string value, address[] origins) returns (bool) {
    	if(msg.sender != owner) {
    		return false;
    	}
    	parsels.push(Parsel(carats, value, origins));
    	return true;
    }

    function getImportingParty() returns (address) {
        return User(parties.importer);
    }

    function getExportingParty() returns (address) {
        return User(parties.exporter);
    }

    function getSignatures() returns (uint[4]) {
        return [signatures.exporter.date,
            signatures.importer.date,
            signatures.exporterAuthority.date,
            signatures.importerAuthority.date
        ];
    }

    function canSign() returns (bool) {
        if(ParticipantAuthority(Participant(participants.source).getExportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.exporterAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.source).getState() != UserState.Accepted()) {
                return false;
            }
            return true;
        } else if(ParticipantAuthority(Participant(participants.destination).getImportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.importerAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.destination).getState() != UserState.Accepted()) {
                return false;
            }
            return true;
        } else if(msg.sender == User(parties.importer).owner()) {
            if(signatures.importer.date > 0) {
                return false;
            }
            return true;
        }
        return false;
    }

    function sign() returns (bool) {
        if(ParticipantAuthority(Participant(participants.source).getExportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.exporterAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.source).getState() != UserState.Accepted()) {
                return false;
            }
            Signed(msg.sender, "Exporting Authority");
            signatures.exporterAuthority = Signature(now, msg.sender);
        } else if(ParticipantAuthority(Participant(participants.destination).getImportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.importerAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.destination).getState() != UserState.Accepted()) {
                return false;
            }
            Signed(msg.sender, "Importing Authority");
            signatures.importerAuthority = Signature(now, msg.sender);
        } else if(msg.sender == User(parties.importer).owner()) {
            if(signatures.importer.date > 0) {
                return false;
            }
            Signed(msg.sender, "Importing Party");
            signatures.importer = Signature(now, msg.sender);
        } else {
            return false;
        }

        numberOfSignatures++;

        if(hasRequiredSignatures()) {
            state = State.Issued;
            Issued(this);
        }
        return true;
    }

    function hasRequiredSignatures() returns (bool isComplete) {
        return (signatures.importerAuthority.date > 0 && signatures.exporterAuthority.date > 0 && signatures.importer.date > 0 && signatures.exporter.date > 0);
    }

    function isValid() returns (bool) {
    	return (state == State.Issued);
    }
}

import {User} from "./User.sol";
import {Participant} from "./Participant.sol";
import {ParticipantAuthority} from "./ParticipantAuthority.sol";
import {UserState} from "./UserState.sol";

contract Certificate {

	address public owner;

	enum State {
		/*
		Pending: certificate has been created, but awaiting signatures from issuer and either importer or exporter
		Issued: all signatures received, certificate is valid.
		Completed: shipment validated upon border crossing
		Expired: shipment has expired without receiving a 'completed' Event
		*/
		Pending, Issued, Expired
	}
	State private state = State.Pending;

	struct Dates {
		//date the certificate is created + requested
		uint creation;

		//date the certificate is signed by all parties and is officially issued, becoming valid
		uint issue;

		//date the shipment is certified by the importing authority
		uint completion;

		//default expiration date of the certificate, exercised only if shipment never verified by importing authority
		uint expiration;
	}
	Dates public dates = Dates(now, 0, 0, 0);

	//Participants in the KP: member countries of source and destination
	struct Participants {
		address[] origins; //the declared origin of the goods
		address source; //the country we are exporting from
		address destination; //the country we are importing to
	}
	Participants private participants;

	//Authorities: issuing and importing
	struct Agents {
		address exporter;
		address importer;
	}
	Agents public agents;

	//the parties to the transaction: importer and exporter
	struct Parties {
		address exporter;
		address importer;
	}
	Parties public parties;

    struct Signature {
        uint date;
        address owner;
    }

    struct Signatures {
        Signature exporter;
        Signature importer;
        Signature exporterAuthority;
        Signature importerAuthority;
    }
    Signatures private signatures;

	struct Parsel {
		string carats;
		string value;
		address[] origins;
	}
	Parsel[] public parsels;

	event Requested(address indexed certificate);
	event Issued(address indexed certificate);
	event Expired(address indexed certificate);
	event Exported(address indexed certificate);
	event Imported(address indexed certificate);
    event Signed(address from, string name);

    uint public numberOfSignatures;

	/*
	Certificates should be created by the exporter: the party in possession of the goods.
	params:
	- importer - importing Party
	- exporter - exporting Party
	- participantOrigin - KPCS Participant (member country) the goods were sourced _from_ ... likely the country of geological origin
	- participantSource - KPCS Participant (member country) the goods are being sent from
	- participantDestination - KPCS Participant (member country) the goods are being sent to
	*/
    function Certificate(address _exporter,
    	address _importer,
    	address[] _participantOrigin,
    	address _participantSource,
    	address _participantDestination) {
    		owner = msg.sender;
    		parties = Parties(_exporter, _importer);
    		participants = Participants(_participantOrigin, _participantSource, _participantDestination);
    		owner = msg.sender;
            signatures = Signatures(
                Signature(now, _exporter),
                Signature(0,0x0),
                Signature(0,0x0),
                Signature(0,0x0));
            numberOfSignatures = 1;
    }

    function getNumberOfParticipantsOrigins() public constant returns (uint) {
        return participants.origins.length;
    }

    function getParticipantOriginWithIndex(uint index) public constant returns (address) {
        return participants.origins[index];
    }

    function getParticipantSource() public constant returns (address) {
        return participants.source;
    }

    function getParticipantDestination() public constant returns (address) {
        return participants.destination;
    }

    function getParticipants() public constant returns (address[]) {
        address[] memory allParticipants = new address[](participants.origins.length + 2);
        allParticipants[0] = (participants.source);
        allParticipants[1] = participants.destination;
        uint origins = participants.origins.length;
        for(uint i = 0; i<origins; i++) {
            allParticipants[i + 2] = participants.origins[i];
        }
        return allParticipants;
    }

    function addParsel(string carats, string value, address[] origins) returns (bool) {
    	if(msg.sender != owner) {
    		return false;
    	}
    	parsels.push(Parsel(carats, value, origins));
    	return true;
    }

    function getImportingParty() public returns (address) {
        return User(parties.importer);
    }

    function getExportingParty() public returns (address) {
        return User(parties.exporter);
    }

    function getSignatures() public returns (uint[4]) {
        return [signatures.exporter.date,
            signatures.importer.date,
            signatures.exporterAuthority.date,
            signatures.importerAuthority.date
        ];
    }

    function canSign() public returns (bool) {
        if(ParticipantAuthority(Participant(participants.source).getExportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.exporterAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.source).getState() != UserState.Accepted()) {
                return false;
            }
            return true;
        } else if(ParticipantAuthority(Participant(participants.destination).getImportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.importerAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.destination).getState() != UserState.Accepted()) {
                return false;
            }
            return true;
        } else if(msg.sender == User(parties.importer).owner()) {
            if(signatures.importer.date > 0) {
                return false;
            }
            return true;
        }
        return false;
    }

    function sign() returns (bool) {
        if(ParticipantAuthority(Participant(participants.source).getExportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.exporterAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.source).getState() != UserState.Accepted()) {
                return false;
            }
            Signed(msg.sender, "Exporting Authority");
            signatures.exporterAuthority = Signature(now, msg.sender);
        } else if(ParticipantAuthority(Participant(participants.destination).getImportingAuthority()).isSenderRegisteredAgent(msg.sender)) {
            if(signatures.importerAuthority.date > 0) {
                return false;
            }
            if(Participant(participants.destination).getState() != UserState.Accepted()) {
                return false;
            }
            Signed(msg.sender, "Importing Authority");
            signatures.importerAuthority = Signature(now, msg.sender);
        } else if(msg.sender == User(parties.importer).owner()) {
            if(signatures.importer.date > 0) {
                return false;
            }
            Signed(msg.sender, "Importing Party");
            signatures.importer = Signature(now, msg.sender);
        } else {
            return false;
        }

        numberOfSignatures++;

        if(hasRequiredSignatures()) {
            state = State.Issued;
            Issued(this);
        }
        return true;
    }

    function hasRequiredSignatures() returns (bool isComplete) {
        return (signatures.importerAuthority.date > 0 && signatures.exporterAuthority.date > 0 && signatures.importer.date > 0 && signatures.exporter.date > 0);
    }

    function isValid() returns (bool) {
    	return (state == State.Issued);
    }
}


retailerList, insuranceList and insurance status

pragma solidity ^0.4.4;

contract owned {
    address owner;

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

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

contract mortal is owned {
    function kill() {
        if (msg.sender == owner) selfdestruct(owner);
    }
}

contract Insurechain is mortal {
    enum RetailerStatus {Undefined, Requested, Accepted, Rejected, Terminated}
    enum InsuranceStatus {Undefined, Requested, Active, Terminated}

    struct PartnerRelations {
        RetailerStatus status;
        uint sales /*the total amount of policies sold by retailer*/;
        uint payments /*the total amount paid by retailer*/;
    }

    struct Insurance {
        string name;
        InsuranceStatus status;
    }

    struct Retailer {
        string companyName;
        mapping (address=>PartnerRelations) partnerRelations /*the mapping holds the relation of the partner with each insurance company*/;
    }

    mapping (address=>Retailer) retailers;
    mapping (uint=>address) retailerList;
    uint public retailerCount;

    mapping (address => Insurance) insurances;
    mapping (uint=>address) insuranceList;
    uint public insuranceCount;

    event RetailerRequest(
        string indexed companyName,
        address retailerAddress,
        address indexed insurance
    );

    event RetailerStatusChanged(
        address indexed retailer,
        address indexed insurance,
        RetailerStatus status
    );

    event InsuranceStatusChanged(
        address indexed insurance,
        InsuranceStatus status
    );

    modifier insuranceOnly {
        if(insurances[msg.sender].status == InsuranceStatus.Undefined) throw;
        _;
    }

    modifier registeredRetailerOnly(address insurance) {
        if(retailers[msg.sender].partnerRelations[insurance].status != RetailerStatus.Accepted) throw;
        _;
    }

    function createInsurance(string name) {
        Insurance insurance = insurances[msg.sender];
        if(insurance.status != InsuranceStatus.Undefined) throw;

        insurance.status = InsuranceStatus.Active;

        InsuranceStatusChanged(msg.sender, InsuranceStatus.Requested);
    }

    function setInsuranceState(address insuranceAddress, InsuranceStatus status) ownerOnly {
        Insurance insurance = insurances[insuranceAddress];
        if(insurance.status == InsuranceStatus.Undefined) throw;

        insurance.status = status;
    }

    /**
    the retailer send a transaction to request registration with an insurer
    */
    function requestRegistration(string companyName, address insurance) {
        Retailer retailer = retailers[msg.sender];
        retailer.companyName = companyName;
        /*make sure the insurance company exists*/
        if(insurances[insurance].status != InsuranceStatus.Active) {
            throw;
        }
        /*make sure no previous request was made*/
        if(retailers[msg.sender].partnerRelations[insurance].status != RetailerStatus.Undefined){
            throw;
        }

        retailerList[retailerCount++] = msg.sender;
        retailer.partnerRelations[insurance].status = RetailerStatus.Requested;
        retailers[msg.sender] = retailer;
        //RetailerRequest(companyName, msg.sender, insurance);
    }

    function getRequestState(address retailer, address insurance) constant returns (RetailerStatus) {
        return retailers[retailer].partnerRelations[insurance].status;
    }

    /**
    sets the status of a retailer's request.
    only the insurance to which the request was made can do this
    */
    function setRequestState(address retailer, RetailerStatus status) insuranceOnly {
        retailers[retailer].partnerRelations[msg.sender].status = status;
        RetailerStatusChanged(retailer, msg.sender, status);
    }

    /**
    get the nth retailer in the list
    for removed retailers, the name will be "removed" in that case an exception
    */
    function getRetailer(uint index) constant returns (address, string) {
        return (retailerList[index], retailers[retailerList[index]].companyName);
    }

}

pragma solidity ^0.4.4;

contract owned {
    address owner;

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

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

contract mortal is owned {
    function kill() {
        if (msg.sender == owner) selfdestruct(owner);
    }
}

contract Insurechain is mortal {
    enum RetailerStatus {Undefined, Requested, Accepted, Rejected, Terminated}
    enum InsuranceStatus {Undefined, Active, Terminated}

    struct PartnerRelations {
        RetailerStatus status;
        uint sales /*the total amount of policies sold by retailer*/;
        uint payments /*the total amount paid by retailer*/;
    }

    struct Insurance {
        string name;
        InsuranceStatus status;
    }

    struct Retailer {
        string companyName;
        mapping (address=>PartnerRelations) partnerRelations /*the mapping holds the relation of the partner with each insurance company*/;
    }

    mapping (address=>Retailer) retailers;
    mapping (address => Insurance) insurances;

    event RetailerRequest(
        string indexed companyName,
        address retailerAddress,
        address indexed insurance
    );

    event RetailerStatusChanged(
        address indexed retailer,
        address indexed insurance,
        RetailerStatus status
    );

    event InsuranceStatusChanged(
        address indexed insurance,
        InsuranceStatus status
    );

    modifier insuranceOnly {
        if(insurances[msg.sender] == InsuranceStatus.Undefined) throw;
        _;
    }

    modifier registeredRetailerOnly(address insurance) {
        if(retailers[msg.sender].partnerRelations[insurance] != RetailerStatus.Accepted) throw;
        _;
    }

    function createInsurance(string name, address insuranceAddress) {
        Insurance insurance = insurances[insuranceAddress];
        if(insurance.status != InsuranceStatus.Undefined) throw;

        insurance.status = InsuranceStatus.Active;

        InsuranceStatusChanged(insuranceAddress, InsuranceStatus.Active);
    }

    /**
    the retailer send a transaction to request registration with an insurer
    */
    function requestRegistration(string companyName, address insurance) {
        Retailer retailer = retailers[msg.sender];
        retailer.companyName = companyName;
        retailer.partnerRelations[insurance].status = RetailerStatus.Requested;
        retailers[msg.sender] = retailer;
        RetailerRequest(companyName, msg.sender, insurance);
    }

    function getRequestState(address retailer, address insurance) constant returns (RetailerStatus) {
        return retailers[retailer].partnerRelations[insurance].status;
    }

    /**
    sets the status of a retailer's request.
    only the insurance to which the request was made can do this
    */
    function setRequestState(address retailer, RetailerStatus status) insuranceOnly {
        retailers[retailer].partnerRelations[msg.sender].status = status;
        RetailerStatusChanged(retailer, msg.sender, status);
    }

}


Implements the disapproval methods

Implements the disapproval methods

pragma solidity ^0.4.2;

contract EtherCred {
    struct Citizen {
        address[] approvals;
        address[] disapprovals;
    }

    mapping(address => Citizen) citizens;

    function approve(address _target) {
        citizens[msg.sender].approvals.push(_target);
    }

    function unapprove(uint _index) {
        if(_index < citizens[msg.sender].approvals.length) {
            delete citizens[msg.sender].approvals[_index];
        }
    }

    function getApprovalsFor(address _target) constant returns (address[]) {
        return citizens[_target].approvals;
    }

    function disapprove(address _target) {
        citizens[msg.sender].disapprovals.push(_target);
    }

    function undisapprove(uint _index) {
        if(_index < citizens[msg.sender].disapprovals.length) {
            delete citizens[msg.sender].disapprovals[_index];
        }
    }

    function getDisapprovalsFor(address _target) constant returns (address[]) {
        return citizens[_target].disapprovals;
    }
}

pragma solidity ^0.4.2;

contract EtherCred {
    struct Citizen {
        address[] approvals;
    }

    mapping(address => Citizen) citizens;

    function approve(address _target) {
        citizens[msg.sender].approvals.push(_target);
    }

    function unapprove(uint _index) {
        if(_index < citizens[msg.sender].approvals.length) {
            delete citizens[msg.sender].approvals[_index];
        }
    }

    function getApprovalsFor(address _target) constant returns (address[]) {
        return citizens[_target].approvals;
    }
}


Add a link to the minime token

Add a link to the minime token

pragma solidity ^0.5.2;

import "../math/SafeMath.sol";
import "../utils/Arrays.sol";
import "../drafts/Counters.sol";
import "../token/ERC20/ERC20.sol";

/**
 * @title ERC20 token with snapshots.
 * Inspired by Jordi Baylina's MiniMeToken to record historical balances:
 * https://github.com/Giveth/minime/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol
 * Snapshots store a value at the time a snapshot is taken (and a new snapshot id created), and the corresponding
 * snapshot id. Each account has individual snapshots taken on demand, as does the token's total supply.
 * @author Validity Labs AG <info@validitylabs.org>
 */
contract ERC20Snapshot is ERC20 {
    using SafeMath for uint256;
    using Arrays for uint256[];
    using Counters for Counters.Counter;

    // Snapshoted values have arrays of ids and the value corresponding to that id. These could be an array of a
    // Snapshot struct, but that would impede usage of functions that work on an array.
    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping (address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnaphots;

    // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
    Counters.Counter private _currentSnapshotId;

    event Snapshot(uint256 id);

    // Creates a new snapshot id. Balances are only stored in snapshots on demand: unless a snapshot was taken, a
    // balance change will not be recorded. This means the extra added cost of storing snapshotted balances is only paid
    // when required, but is also flexible enough that it allows for e.g. daily snapshots.
    function snapshot() public returns (uint256) {
        _currentSnapshotId.increment();

        uint256 currentId = _currentSnapshotId.current();
        emit Snapshot(currentId);
        return currentId;
    }

    function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : balanceOf(account);
    }

    function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots);

        return snapshotted ? value : totalSupply();
    }

    // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the
    // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value.
    // The same is true for the total supply and _mint and _burn.
    function _transfer(address from, address to, uint256 value) internal {
        _updateAccountSnapshot(from);
        _updateAccountSnapshot(to);

        super._transfer(from, to, value);
    }

    function _mint(address account, uint256 value) internal {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._mint(account, value);
    }

    function _burn(address account, uint256 value) internal {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._burn(account, value);
    }

    // When a valid snapshot is queried, there are three possibilities:
    //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
    //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
    //  to this id is the current one.
    //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
    //  requested id, and its value is the one to return.
    //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
    //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
    //  larger than the requested one.
    //
    // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
    // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
    // exactly this.
    function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
        private view returns (bool, uint256)
    {
        require(snapshotId > 0);
        require(snapshotId <= _currentSnapshotId.current());

        uint256 index = snapshots.ids.findUpperBound(snapshotId);

        if (index == snapshots.ids.length) {
            return (false, 0);
        } else {
            return (true, snapshots.values[index]);
        }
    }

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnaphots, totalSupply());
    }

    function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
        uint256 currentId = _currentSnapshotId.current();
        if (_lastSnapshotId(snapshots.ids) < currentId) {
            snapshots.ids.push(currentId);
            snapshots.values.push(currentValue);
        }
    }

    function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
        if (ids.length == 0) {
            return 0;
        } else {
            return ids[ids.length - 1];
        }
    }
}

pragma solidity ^0.5.2;

import "../math/SafeMath.sol";
import "../utils/Arrays.sol";
import "../drafts/Counters.sol";
import "../token/ERC20/ERC20.sol";

/**
 * @title ERC20 token with snapshots.
 * inspired by Jordi Baylina's MiniMeToken to record historical balances
 * Snapshots store a value at the time a snapshot is taken (and a new snapshot id created), and the corresponding
 * snapshot id. Each account has individual snapshots taken on demand, as does the token's total supply.
 * @author Validity Labs AG <info@validitylabs.org>
 */
contract ERC20Snapshot is ERC20 {
    using SafeMath for uint256;
    using Arrays for uint256[];
    using Counters for Counters.Counter;

    // Snapshoted values have arrays of ids and the value corresponding to that id. These could be an array of a
    // Snapshot struct, but that would impede usage of functions that work on an array.
    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping (address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnaphots;

    // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
    Counters.Counter private _currentSnapshotId;

    event Snapshot(uint256 id);

    // Creates a new snapshot id. Balances are only stored in snapshots on demand: unless a snapshot was taken, a
    // balance change will not be recorded. This means the extra added cost of storing snapshotted balances is only paid
    // when required, but is also flexible enough that it allows for e.g. daily snapshots.
    function snapshot() public returns (uint256) {
        _currentSnapshotId.increment();

        uint256 currentId = _currentSnapshotId.current();
        emit Snapshot(currentId);
        return currentId;
    }

    function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : balanceOf(account);
    }

    function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots);

        return snapshotted ? value : totalSupply();
    }

    // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the
    // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value.
    // The same is true for the total supply and _mint and _burn.
    function _transfer(address from, address to, uint256 value) internal {
        _updateAccountSnapshot(from);
        _updateAccountSnapshot(to);

        super._transfer(from, to, value);
    }

    function _mint(address account, uint256 value) internal {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._mint(account, value);
    }

    function _burn(address account, uint256 value) internal {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._burn(account, value);
    }

    // When a valid snapshot is queried, there are three possibilities:
    //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
    //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
    //  to this id is the current one.
    //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
    //  requested id, and its value is the one to return.
    //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
    //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
    //  larger than the requested one.
    //
    // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
    // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
    // exactly this.
    function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
        private view returns (bool, uint256)
    {
        require(snapshotId > 0);
        require(snapshotId <= _currentSnapshotId.current());

        uint256 index = snapshots.ids.findUpperBound(snapshotId);

        if (index == snapshots.ids.length) {
            return (false, 0);
        } else {
            return (true, snapshots.values[index]);
        }
    }

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnaphots, totalSupply());
    }

    function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
        uint256 currentId = _currentSnapshotId.current();
        if (_lastSnapshotId(snapshots.ids) < currentId) {
            snapshots.ids.push(currentId);
            snapshots.values.push(currentValue);
        }
    }

    function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
        if (ids.length == 0) {
            return 0;
        } else {
            return ids[ids.length - 1];
        }
    }
}


Changed pragma version and constructor syntax

pragma solidity ^0.4.23;

contract SimpleStorage {
  uint public storedData;

  constructor(uint initialValue) public {
    storedData = initialValue;
  }

  function set(uint x) public {
    storedData = x;
  }

  function get() public view returns (uint retVal) {
    return storedData;
  }

}

pragma solidity ^0.4.7;
contract SimpleStorage {
  uint public storedData;

  function SimpleStorage(uint initialValue) public {
    storedData = initialValue;
  }

  function set(uint x) public {
    storedData = x;
  }

  function get() public view returns (uint retVal) {
    return storedData;
  }

}


Robot liability cost guard bug fix

Robot liability cost guard bug fix

pragma solidity ^0.4.24;

import 'openzeppelin-solidity/contracts/ECRecovery.sol';
import './RobotLiabilityABI.sol';
import './RobotLiabilityAPI.sol';

contract RobotLiabilityLib is RobotLiabilityABI
                            , RobotLiabilityAPI {
    using ECRecovery for bytes32;

    function ask(
        bytes   _model,
        bytes   _objective,

        ERC20   _token,
        uint256 _cost,

        address _validator,
        uint256 _validator_fee,

        uint256 _deadline,
        bytes32 _nonce,
        bytes   _signature
    )
        external
        returns (bool)
    {
        require(msg.sender == address(factory));
        require(block.number < _deadline);

        model        = _model;
        objective    = _objective;
        token        = _token;
        cost         = _cost;
        validator    = _validator;
        validatorFee = _validator_fee;

        askHash = keccak256(abi.encodePacked(
            _model
          , _objective
          , _token
          , _cost
          , _validator
          , _validator_fee
          , _deadline
          , _nonce
        ));

        promisee = askHash
            .toEthSignedMessageHash()
            .recover(_signature);
        return true;
    }

    function bid(
        bytes   _model,
        bytes   _objective,

        ERC20   _token,
        uint256 _cost,

        uint256 _lighthouse_fee,

        uint256 _deadline,
        bytes32 _nonce,
        bytes   _signature
    )
        external
        returns (bool)
    {
        require(msg.sender == address(factory));
        require(block.number < _deadline);
        require(keccak256(abi.encodePacked(model, objective))
                == keccak256(abi.encodePacked(_model, _objective)));
        require(_token == token);
        require(_cost == cost);

        lighthouseFee = _lighthouse_fee;

        bidHash = keccak256(abi.encodePacked(
            _model
          , _objective
          , _token
          , _cost
          , _lighthouse_fee
          , _deadline
          , _nonce
        ));

        promisor = bidHash
            .toEthSignedMessageHash()
            .recover(_signature);
        return true;
    }

    /**
     * @dev Finalize this liability
     * @param _result Result data hash
     * @param _agree Validation network confirmation
     * @param _signature Result sender signature
     */
    function finalize(
        bytes _result,
        bytes _signature,
        bool  _agree
    )
        external
        returns (bool)
    {
        uint256 gasinit = gasleft();
        require(!isFinalized);

        address resultSender = keccak256(abi.encodePacked(this, _result))
            .toEthSignedMessageHash()
            .recover(_signature);
        require(resultSender == promisor);

        if (validator == 0) {
            require(factory.isLighthouse(msg.sender));
            require(token.transfer(promisor, cost));
        } else {
            require(msg.sender == validator);

            isConfirmed = _agree;
            if (isConfirmed)
                require(token.transfer(promisor, cost));
            else
                require(token.transfer(promisee, cost));

            if (validatorFee > 0)
                require(factory.xrt().transfer(validator, validatorFee));
        }

        result = _result;
        isFinalized = true;

        require(factory.liabilityFinalized(gasinit));
        return true;
    }
}

pragma solidity ^0.4.24;

import 'openzeppelin-solidity/contracts/ECRecovery.sol';
import './RobotLiabilityABI.sol';
import './RobotLiabilityAPI.sol';

contract RobotLiabilityLib is RobotLiabilityABI
                            , RobotLiabilityAPI {
    using ECRecovery for bytes32;

    function ask(
        bytes   _model,
        bytes   _objective,

        ERC20   _token,
        uint256 _cost,

        address _validator,
        uint256 _validator_fee,

        uint256 _deadline,
        bytes32 _nonce,
        bytes   _signature
    )
        external
        returns (bool)
    {
        require(msg.sender == address(factory));
        require(block.number < _deadline);

        model        = _model;
        objective    = _objective;
        token        = _token;
        cost         = _cost;
        validator    = _validator;
        validatorFee = _validator_fee;

        askHash = keccak256(abi.encodePacked(
            _model
          , _objective
          , _token
          , _cost
          , _validator
          , _validator_fee
          , _deadline
          , _nonce
        ));

        promisee = askHash
            .toEthSignedMessageHash()
            .recover(_signature);
        return true;
    }

    function bid(
        bytes   _model,
        bytes   _objective,

        ERC20   _token,
        uint256 _cost,

        uint256 _lighthouse_fee,

        uint256 _deadline,
        bytes32 _nonce,
        bytes   _signature
    )
        external
        returns (bool)
    {
        require(msg.sender == address(factory));
        require(block.number < _deadline);
        require(keccak256(abi.encodePacked(model, objective))
                == keccak256(abi.encodePacked(_model, _objective)));
        require(_token == token);
        require(_cost == _cost);

        lighthouseFee = _lighthouse_fee;

        bidHash = keccak256(abi.encodePacked(
            _model
          , _objective
          , _token
          , _cost
          , _lighthouse_fee
          , _deadline
          , _nonce
        ));

        promisor = bidHash
            .toEthSignedMessageHash()
            .recover(_signature);
        return true;
    }

    /**
     * @dev Finalize this liability
     * @param _result Result data hash
     * @param _agree Validation network confirmation
     * @param _signature Result sender signature
     */
    function finalize(
        bytes _result,
        bytes _signature,
        bool  _agree
    )
        external
        returns (bool)
    {
        uint256 gasinit = gasleft();

        require(!isFinalized);

        address resultSender = keccak256(abi.encodePacked(this, _result))
            .toEthSignedMessageHash()
            .recover(_signature);
        require(resultSender == promisor);

        if (validator == 0) {
            require(factory.isLighthouse(msg.sender));
            require(token.transfer(promisor, cost));
        } else {
            require(msg.sender == validator);

            isConfirmed = _agree;
            if (isConfirmed)
                require(token.transfer(promisor, cost));
            else
                require(token.transfer(promisee, cost));

            if (validatorFee > 0)
                require(factory.xrt().transfer(validator, validatorFee));
        }

        result = _result;
        isFinalized = true;

        require(factory.liabilityFinalized(gasinit));
        return true;
    }
}


Create WeiHash_Beta_Launch.sol

Create WeiHash_Beta_Launch.sol

contract WeiFund {
    /// @notice New Campaign; create a new crowdfunding campaign
    /// @dev This method starts a new crowdfunding campaign and calles the campaigns configuration contract if stated
    /// @param _name The campaign name
    /// @param _beneficiary The address of the beneficiary for this campaign
    /// @param _fundingGoal The funding goal of the campaign. If this goal is not met by the timelimit, all ether will be refunded to the respective contributers
    /// @param _expiry When the campaign will expire and contributions can no longer be made
    /// @param _config The configuration address
    function newCampaign(string _name, address _beneficiary, uint _fundingGoal, uint _expiry, address _config) {}

    /// @notice Contribute (the campaign ID); contribute ether to a WeiFund campaign
    /// @dev This method will contribute an amount of ether to the campaign at ID _cid. All contribution data will be stored so that the issuance of digital assets can be made out to the contributor address
    /// @param _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    /// @param _beneficiary (Contribute As Address) This allows a user to contribute on behalf of another address, if left empty, the from sender address is used as the primary Funder address
    function contribute(uint _campaignID, address _beneficiary) {}

    /// @notice Refund (the campaign ID); refund your contribution of a failed or expired crowdfunding campaign.
    /// @dev This method will refund the amount you contributed to a WeiFund campaign, if that campaign has failed to meet it's funding goal or has expired.
    /// @param _campaignID (Campaign ID) The ID number of the crowdfunding campaign to be refunded
    function refund(uint _campaignID) {}

    /// @notice Payout (the campaign ID); this will payout a successfull crowdfunding campaign to the benificiary address
    /// @dev This method will payout a successfull WeiFund crowdfunding campaign to the benificiary address specified. Any person can trigger the payout by calling this method.
    /// @param _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    function payout(uint _campaignID) {}

    /// @notice User Campaign ID (the address of the user, the user campaign ID); get the campaign ID of one of the users crowdfunding campaigns.
    /// @dev This method will get the campaign ID of one of the users crowdfunding campaigns, by looking up the campaign with a user campaign ID. All campaign owners and their campaigns are stored with WeiFund.
    /// @param _user The address of the campaign operator.
    /// @param _userCampaignID The user campaign ID
    /// @return _campaignID The campaign ID
    function userCampaignID(address _user, uint _userCampaignID) constant returns (uint _campaignID) {}

    /// @notice Total Number of Campaigns Started for a Given User
    /// @dev This method will get the campaign ID of one of the users crowdfunding campaigns, by looking up the campaign with a user campaign ID. All campaign owners and their campaigns are stored with WeiFund.
    /// @param _user The user's address
    /// @return _numCampaigns The number of campaigns
    function totalUserCampaigns(address _user) constant returns (uint _numCampaigns) {}

    /// @notice The total number of campaigns on WeiFund
    /// @dev This method returns the total number of campaigns on WeiFund as an unsigned integer
    /// @return _numCampaigns The number of campaigns
    function totalCampaigns() constant returns (uint _numCampaigns) {}

    /// @notice Contributor At ID;
    /// @dev For retrieving the contributor data at a specific contributor ID
    /// @param _campaignID The address of the campaign operator.
    /// @param _contributorID The user campaign ID
    /// @return _contributor, _beneficiary, _amountContributed, _refunded
    function contributorAt(uint _campaignID, uint _contributorID) constant returns (address _contributor,
                                                                                address _beneficiary,
                                                                                uint _amountContributed,
                                                                                bool _refunded){}
    function createdAt(uint _campaignID) public constant returns (uint){}
    function contributorID(uint _campaignID, address _contributor) constant returns (uint) {}
    function ownerOf(uint _campaignID) constant returns (address){}
    function beneficiaryOf(uint _campaignID) constant returns (address){}
    function configOf(uint _campaignID) constant returns (address){}
    function amountRaisedBy(uint _campaignID) constant returns (uint){}
    function fundingGoalOf(uint _campaignID) constant returns (uint){}
    function expiryOf(uint _campaignID) constant returns (uint){}
    function totalContributors(uint _campaignID) constant returns (uint){}

    function isContributor(uint _campaignID, address _contributor) constant returns (bool) {}
    function isOwner(uint _campaignID, address _owner) constant returns (bool){}
    function hasFailed(uint _campaignID) constant returns (bool){}
    function isSuccess(uint _campaignID) constant returns (bool){}
    function isPaidOut(uint _campaignID) constant returns (bool){}
    function totalRefunded(uint _campaignID) constant returns (uint){}
    function isRefunded(uint _campaignID) constant returns (bool){}

    event CampaignCreated(address indexed _owner, uint indexed _campaignID);
    event Contributed(address indexed _contributor, uint indexed _campaignID, uint _amountContributed);
    event PaidOut(address indexed _beneficiary, uint indexed _campaignID, uint _amountPaid);
    event Refunded(address indexed _contributor, uint indexed _campaignID, uint _amountRefunded);
}

contract WeiHashInterface {
    function register(uint _campaignID, bytes _hash){}
    function unregister(uint _campaignID){}
	  function hashOf(uint _campaignID) constant returns (bytes) {}

	  event HashRegistered(uint indexed _campaignID, address _owner);
	  event HashDeregistered(uint indexed _campaignID, address _owner);
}

contract WeiHash is WeiHashInterface {
    mapping(uint => bytes) public hashes;
    address public weifundAddr;
	  uint public version;

    function WeiHash(address _weifundAddr) {
        weifundAddr = _weifundAddr;
		    version = 1;
    }

    function register(uint _campaignID, bytes _hash){
        if(!WeiFund(weifundAddr).isOwner(_campaignID, msg.sender))
			    throw;

        hashes[_campaignID] = _hash;
		    HashRegistered(_campaignID, msg.sender);
    }

    function unregister(uint _campaignID, bytes _hash){
        if(!WeiFund(weifundAddr).isOwner(_campaignID, msg.sender))
			    throw;

        hashes[_campaignID] = _hash;
		    HashDeregistered(_campaignID, msg.sender);
    }

	function hashOf(uint _campaignID) public constant returns (bytes){
		return hashes[_campaignID];
	}
}

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