fix merge

fix merge

pragma solidity ^0.4.23;

import "./investment/InvestmentAsset.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @title Swapy Exchange Protocol
 * @dev Allows the creation of fundraising offers and many actions with them
 */
contract SwapyExchange {
    /**
     * Add safety checks for uint operations
     */
    using SafeMath for uint256;

    /**
     * Constants
     */
    bytes8 public latestVersion;

    /**
     * Storage
     */
    mapping(bytes8 => address) libraries;
    address public owner;
    address public token;

    /**
     * Events
     */
    event LogOffers(address indexed _from, bytes8 _protocolVersion, address[] _assets);
    event LogInvestments(address indexed _investor, address[] _assets, uint256 _value);
    event LogForSale(address indexed _investor, address _asset, uint256 _value);
    event LogBought(address indexed _buyer, address _asset, uint256 _value);
    event LogVersioning(bytes8 _version, address _library);
    event LogReturned(address indexed _from, address[] _assets, uint256[] _values, uint256 _value);

    /**
     * Modifiers
     */
    modifier notEmpty(address[] _assets){
        require(_assets.length > 0, "Empty list of assets");
        _;
    }

    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

    /**
     * @param _token Address of Swapy Token
     */
    constructor(address _token, bytes8 _version, address _library)
        public
    {
        token = _token;
        owner = msg.sender;
        setLibrary(_version, _library);
    }

    /**
     * @dev add a new protocol library - internal
     * @param _version Version
     * @param _library Library's address.
     */
    function setLibrary(
        bytes8 _version,
        address _library)
        private
    {
        require(_version != bytes8(0), "Invalid version");
        require(_library != address(0), "Invalid library address");
        require(libraries[_version] == address(0), "Library version already added");
        latestVersion = _version;
        libraries[_version] = _library;
        emit LogVersioning(_version, _library);
    }

    /**
     * @dev retrieve library address of a version
     * @param _version Version
     * @return Address of library
     */
    function getLibrary(bytes8 _version) view public returns(address) {
        require(libraries[_version] != address(0));
        return libraries[_version];
    }
    /**
     * @dev add a new protocol library
     * @param _version Version
     * @param _library Library's address.
     * @return Success
     */
    function addLibrary(
        bytes8 _version,
        address _library)
        onlyOwner
        external
        returns(bool)
    {
        setLibrary(_version, _library);
        return true;
    }

    /**
     * @dev create a fundraising offer
     * @param _paybackDays Period in days until the return of investment
     * @param _grossReturn Gross return on investment
     * @param _currency Fundraising base currency, i.e, USD
     * @param _assets Asset's values.
     * @return Success
     */
    function createOffer(
        bytes8 _version,
        uint256 _paybackDays,
        uint256 _grossReturn,
        bytes5 _currency,
        uint256[] _assets)
        external
        returns(address[] newAssets)
    {
        bytes8 version = _version == bytes8(0) ? latestVersion : _version;
        require(libraries[version] != address(0), "Library version doesn't exists");
        newAssets = createOfferAssets(_assets, _currency, _paybackDays, _grossReturn, version);
        emit LogOffers(msg.sender, _version, newAssets);
    }

    /**
     * @dev Create fundraising assets
     * @param _assets Asset's values. The length will determine the number of assets composes the fundraising
     * @param _currency Fundraising base currency, i.e, USD
     * @param _paybackDays Period in days until the return of investment
     * @param _grossReturn Gross return on investment
     * @return Address of assets created
     */
    function createOfferAssets(
        uint256[] _assets,
        bytes5 _currency,
        uint _paybackDays,
        uint _grossReturn,
        bytes8 _version)
        internal
        returns (address[])
    {
        address[] memory newAssets = new address[](_assets.length);
        for (uint index = 0; index < _assets.length; index++) {
            newAssets[index] = new InvestmentAsset(
                libraries[_version],
                this,
                msg.sender,
                _version,
                _currency,
                _assets[index],
                _paybackDays,
                _grossReturn,
                token
            );
        }
        return newAssets;
    }
    /**
     * @dev Invest in fundraising assets
     * @param _assets Asset addresses
     * @param value Asset unit value, i.e, _assets.length = 5 and msg.value = 5 ETH, then _value must be equal 1 ETH
     * @return Success
     */
    function invest(address[] _assets, uint256 value) payable
        notEmpty(_assets)
        external
        returns(bool)
    {
        require(
            (value.mul(_assets.length) == msg.value) && value > 0,
            "The value transfered doesn't match with the unit value times the number of assets"
        );
        for (uint index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(address(asset).call.value(value)(abi.encodeWithSignature("invest(address)",address(msg.sender))), "An error ocurred when investing");
        }
        emit LogInvestments(msg.sender, _assets, msg.value);
        return true;
    }

    /**
     * @dev Withdraw investments
     * @param _assets Asset addresses
     * @return Success
     */
    function withdrawFunds(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++){
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.owner(), "The user isn't asset's owner");
            require(address(asset).call(abi.encodeWithSignature("withdrawFunds()")), "An error ocurred when withdrawing asset's funds");
        }
        return true;
    }

    /**
     * @dev Refuse investments
     * @param _assets Asset addresses
     * @return Success
     */
    function refuseInvestment(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++){
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.owner(), "The user isn't asset's owner");
            require(address(asset).call(abi.encodeWithSignature("refuseInvestment()")), "An error ocurred when refusing investment");
        }
        return true;
    }

    /**
     * @dev Cancel investments made
     * @param _assets Asset addresses
     * @return Success
     */
    function cancelInvestment(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++){
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("cancelInvestment()")), "An error ocurred when canceling investment");
        }
        return true;
    }

    /**
     * @dev Put invested assets for sale.
     * @param _assets Asset addresses
     * @param _values Sale values. _assets[0] => _values[0], ..., _assets[n] => _values[n]
     * @return Success
     */
    function sellAssets(address[] _assets, uint256[] _values)
        notEmpty(_assets)
        external
        returns(bool)
    {
        require(_assets.length == _values.length, "All the assets should have a value on sale");
        for(uint index = 0; index < _assets.length; index++){
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("sell(uint256)",_values[index])), "An error ocurred when puting the asset on sale");
            emit LogForSale(msg.sender, _assets[index], _values[index]);
        }
        return true;
    }

    /**
     * @dev Remove available assets from market place
     * @param _assets Asset addresses
     * @return Success
     */
    function cancelSellOrder(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++){
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("cancelSellOrder()")), "An error ocurred when removing the asset from market place");
        }
        return true;
    }

    /**
     * @dev Buy an available asset on market place
     * @param _asset Asset address
     * @return Success
     */
    function buyAsset(address _asset) payable
        external
        returns(bool)
    {
        uint256 assetValue = msg.value;
        InvestmentAsset asset = InvestmentAsset(_asset);
        require(address(asset).call.value(assetValue)(abi.encodeWithSignature("buy(address)",msg.sender)), "An error ocurred when buying the asset");
        emit LogBought(msg.sender, _asset, msg.value);
        return true;
    }

    /**
     * @dev Accept purchases on market place
     * @param _assets Asset addresses
     * @return Success
     */
    function acceptSale(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("acceptSale()")), "An error ocurred when accepting sale");
        }
        return true;
    }

    /**
     * @dev Refuse purchases on market place
     * @param _assets Asset addresses
     * @return Success
     */
    function refuseSale(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("refuseSale()")), "An error ocurred when refusing sale");
        }
        return true;
    }

    /**
     * @dev Cancel purchases made
     * @param _assets Asset addresses
     * @return Success
     */
    function cancelSale(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            address buyer;
            (,buyer) = asset.sellData();
            require(msg.sender == buyer, "The user isn't asset's buyer");
            require(address(asset).call(abi.encodeWithSignature("cancelSale()")), "An error ocurred when canceling sale");
        }
        return true;
    }

    /**
     * @dev Require collateral of investments made
     * @param _assets Asset addresses
     * @return Success
     */
    function requireTokenFuel(address[] _assets)
        notEmpty(_assets)
        external
        returns(bool)
    {
        for(uint index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.investor(), "The user isn't asset's investor");
            require(address(asset).call(abi.encodeWithSignature("requireTokenFuel()")), "An error ocurred when requiring asset's collateral");
        }
        return true;
    }

    /**
     * @dev Return of investments
     * @param _assets Asset addresses
     * @param _values Asset's return values
     * @return Success
     */
    function returnInvestment(address[] _assets, uint256[] _values) payable
        notEmpty(_assets)
        external
        returns(bool)
    {
        uint256 total;
        for (uint index = 0; index < _values.length; index++) {
            total = total.add(_values[index]);
        }
        require((total == msg.value) && total > 0);
        for (index = 0; index < _assets.length; index++) {
            InvestmentAsset asset = InvestmentAsset(_assets[index]);
            require(msg.sender == asset.owner());
            require(
                address(asset).call.value(_values[index])(abi.encodeWithSignature("returnInvestment()")),
                "An error ocurred when returning investment"
            );
        }
        emit LogReturned(msg.sender, _assets, _values, msg.value);
        return true;
    }

}


change to require statement

change to require statement

/*
    Copyright 2017-2018 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.24;

import "./Creatable.sol";
import "./libraries/MathLib.sol";
import "./tokens/PositionToken.sol";

/// @title MarketContract base contract implement all needed functionality for trading.
/// @notice this is the abstract base contract that all contracts should inherit from to
/// implement different oracle solutions.
/// @author Phil Elsasser <phil@marketprotocol.io>
contract MarketContract is Creatable {

    string public CONTRACT_NAME;
    address public COLLATERAL_TOKEN_ADDRESS;
    address public COLLATERAL_POOL_ADDRESS;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public QTY_MULTIPLIER;         // multiplier corresponding to the value of 1 increment in price to token base units
    uint public COLLATERAL_PER_UNIT;    // required collateral amount for the full range of outcome tokens
    uint public EXPIRATION;
    address public LONG_POSITION_TOKEN;
    address public SHORT_POSITION_TOKEN;

    // state variables
    uint public lastPrice;
    uint public settlementPrice;
    bool public isSettled = false;

    // events
    event UpdatedLastPrice(uint256 price);
    event ContractSettled(uint settlePrice);

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param baseAddresses array of 2 addresses needed for our contract including:
    ///     creatorAddress                  address of the person creating the contract
    ///     collateralTokenAddress          address of the ERC20 token that will be used for collateral and pricing
    ///     collateralPoolAddress           address of our collateral pool contract
    /// @param contractSpecs array of unsigned integers including:
    ///     floorPrice          minimum tradeable price of this contract, contract enters settlement if breached
    ///     capPrice            maximum tradeable price of this contract, contract enters settlement if breached
    ///     priceDecimalPlaces  number of decimal places to convert our queried price from a floating point to
    ///                         an integer
    ///     qtyMultiplier       multiply traded qty by this value from base units of collateral token.
    ///     expirationTimeStamp seconds from epoch that this contract expires and enters settlement
    constructor(
        string contractName,
        address[3] baseAddresses,
        uint[5] contractSpecs
    ) public
    {
        PRICE_FLOOR = contractSpecs[0];
        PRICE_CAP = contractSpecs[1];
        require(PRICE_CAP > PRICE_FLOOR);

        PRICE_DECIMAL_PLACES = contractSpecs[2];
        QTY_MULTIPLIER = contractSpecs[3];
        EXPIRATION = contractSpecs[4];
        require(EXPIRATION > now);

        CONTRACT_NAME = contractName;
        creator = baseAddresses[0];
        COLLATERAL_TOKEN_ADDRESS = baseAddresses[1];
        COLLATERAL_POOL_ADDRESS = baseAddresses[2];
        COLLATERAL_PER_UNIT = MathLib.calculateTotalCollateral(PRICE_FLOOR, PRICE_CAP, QTY_MULTIPLIER);

        // create long and short tokens  // TODO: fix names!
        PositionToken longPosToken = new PositionToken("Long Position Token", "LONG", 0);
        PositionToken shortPosToken = new PositionToken("Short Position Token", "SHRT", 1);
        LONG_POSITION_TOKEN = address(longPosToken);
        SHORT_POSITION_TOKEN = address(shortPosToken);
    }

    /*
    // EXTERNAL - onlyCollateralPool METHODS
    */

    /// @notice called only by our collateral pool to create long and short position tokens
    /// @param qtyToMint    qty in base units of how many short and long tokens to mint
    /// @param minter       address of minter to receive tokens
    function mintPositionTokens(
        uint256 qtyToMint,
        address minter
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(LONG_POSITION_TOKEN).mintAndSendToken(qtyToMint, minter);
        PositionToken(SHORT_POSITION_TOKEN).mintAndSendToken(qtyToMint, minter);
    }

    /// @notice called only by our collateral pool to redeem long position tokens
    /// @param qtyToRedeem  qty in base units of how many tokens to redeem
    /// @param redeemer     address of person redeeming tokens
    function redeemLongToken(
        uint256 qtyToRedeem,
        address redeemer
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(LONG_POSITION_TOKEN).redeemToken(qtyToRedeem, redeemer);
    }

    /// @notice called only by our collateral pool to redeem short position tokens
    /// @param qtyToRedeem  qty in base units of how many tokens to redeem
    /// @param redeemer     address of person redeeming tokens
    function redeemShortToken(
        uint256 qtyToRedeem,
        address redeemer
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(SHORT_POSITION_TOKEN).redeemToken(qtyToRedeem, redeemer);
    }

    /*
    // PRIVATE METHODS
    */

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

        uint newSettlementPrice;
        if (now > EXPIRATION) {  // note: miners can cheat this by small increments of time (minutes, not hours)
            isSettled = true;                   // time based expiration has occurred.
            newSettlementPrice = lastPrice;
        } else if (lastPrice >= PRICE_CAP) {    // price is greater or equal to our cap, settle to CAP price
            isSettled = true;
            newSettlementPrice = PRICE_CAP;
        } else if (lastPrice <= PRICE_FLOOR) {  // price is lesser or equal to our floor, settle to FLOOR price
            isSettled = true;
            newSettlementPrice = PRICE_FLOOR;
        }

        if (isSettled) {
            settleContract(newSettlementPrice);
        }
    }

    /// @dev records our final settlement price and fires needed events.
    /// @param finalSettlementPrice final query price at time of settlement
    function settleContract(uint finalSettlementPrice) private {
        settlementPrice = finalSettlementPrice;
        emit ContractSettled(finalSettlementPrice);
    }

    /// @notice only able to be called directly by our collateral pool which controls the position tokens
    /// for this contract!
    modifier onlyCollateralPool {
        require(msg.sender == COLLATERAL_POOL_ADDRESS);
        _;
    }

}

/*
    Copyright 2017-2018 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.24;

import "./Creatable.sol";
import "./libraries/MathLib.sol";
import "./tokens/PositionToken.sol";

/// @title MarketContract base contract implement all needed functionality for trading.
/// @notice this is the abstract base contract that all contracts should inherit from to
/// implement different oracle solutions.
/// @author Phil Elsasser <phil@marketprotocol.io>
contract MarketContract is Creatable {

    string public CONTRACT_NAME;
    address public COLLATERAL_TOKEN_ADDRESS;
    address public COLLATERAL_POOL_ADDRESS;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public QTY_MULTIPLIER;         // multiplier corresponding to the value of 1 increment in price to token base units
    uint public COLLATERAL_PER_UNIT;    // required collateral amount for the full range of outcome tokens
    uint public EXPIRATION;
    address public LONG_POSITION_TOKEN;
    address public SHORT_POSITION_TOKEN;

    // state variables
    uint public lastPrice;
    uint public settlementPrice;
    bool public isSettled = false;

    // events
    event UpdatedLastPrice(uint256 price);
    event ContractSettled(uint settlePrice);

    /// @param contractName viewable name of this contract (BTC/ETH, LTC/ETH, etc)
    /// @param baseAddresses array of 2 addresses needed for our contract including:
    ///     creatorAddress                  address of the person creating the contract
    ///     collateralTokenAddress          address of the ERC20 token that will be used for collateral and pricing
    ///     collateralPoolAddress           address of our collateral pool contract
    /// @param contractSpecs array of unsigned integers including:
    ///     floorPrice          minimum tradeable price of this contract, contract enters settlement if breached
    ///     capPrice            maximum tradeable price of this contract, contract enters settlement if breached
    ///     priceDecimalPlaces  number of decimal places to convert our queried price from a floating point to
    ///                         an integer
    ///     qtyMultiplier       multiply traded qty by this value from base units of collateral token.
    ///     expirationTimeStamp seconds from epoch that this contract expires and enters settlement
    constructor(
        string contractName,
        address[3] baseAddresses,
        uint[5] contractSpecs
    ) public
    {
        PRICE_FLOOR = contractSpecs[0];
        PRICE_CAP = contractSpecs[1];
        require(PRICE_CAP > PRICE_FLOOR);

        PRICE_DECIMAL_PLACES = contractSpecs[2];
        QTY_MULTIPLIER = contractSpecs[3];
        EXPIRATION = contractSpecs[4];
        require(EXPIRATION > now);

        CONTRACT_NAME = contractName;
        creator = baseAddresses[0];
        COLLATERAL_TOKEN_ADDRESS = baseAddresses[1];
        COLLATERAL_POOL_ADDRESS = baseAddresses[2];
        COLLATERAL_PER_UNIT = MathLib.calculateTotalCollateral(PRICE_FLOOR, PRICE_CAP, QTY_MULTIPLIER);

        // create long and short tokens  // TODO: fix names!
        PositionToken longPosToken = new PositionToken("Long Position Token", "LONG", 0);
        PositionToken shortPosToken = new PositionToken("Short Position Token", "SHRT", 1);
        LONG_POSITION_TOKEN = address(longPosToken);
        SHORT_POSITION_TOKEN = address(shortPosToken);
    }

    /*
    // EXTERNAL - onlyCollateralPool METHODS
    */

    /// @notice called only by our collateral pool to create long and short position tokens
    /// @param qtyToMint    qty in base units of how many short and long tokens to mint
    /// @param minter       address of minter to receive tokens
    function mintPositionTokens(
        uint256 qtyToMint,
        address minter
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(LONG_POSITION_TOKEN).mintAndSendToken(qtyToMint, minter);
        PositionToken(SHORT_POSITION_TOKEN).mintAndSendToken(qtyToMint, minter);
    }

    /// @notice called only by our collateral pool to redeem long position tokens
    /// @param qtyToRedeem  qty in base units of how many tokens to redeem
    /// @param redeemer     address of person redeeming tokens
    function redeemLongToken(
        uint256 qtyToRedeem,
        address redeemer
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(LONG_POSITION_TOKEN).redeemToken(qtyToRedeem, redeemer);
    }

    /// @notice called only by our collateral pool to redeem short position tokens
    /// @param qtyToRedeem  qty in base units of how many tokens to redeem
    /// @param redeemer     address of person redeeming tokens
    function redeemShortToken(
        uint256 qtyToRedeem,
        address redeemer
    ) external onlyCollateralPool {
        // mint and distribute short and long position tokens to our caller
        PositionToken(SHORT_POSITION_TOKEN).redeemToken(qtyToRedeem, redeemer);
    }

    /*
    // PRIVATE METHODS
    */

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

        uint newSettlementPrice;
        if (now > EXPIRATION) {  // note: miners can cheat this by small increments of time (minutes, not hours)
            isSettled = true;                   // time based expiration has occurred.
            newSettlementPrice = lastPrice;
        } else if (lastPrice >= PRICE_CAP) {    // price is greater or equal to our cap, settle to CAP price
            isSettled = true;
            newSettlementPrice = PRICE_CAP;
        } else if (lastPrice <= PRICE_FLOOR) {  // price is lesser or equal to our floor, settle to FLOOR price
            isSettled = true;
            newSettlementPrice = PRICE_FLOOR;
        }

        if (isSettled) {
            settleContract(newSettlementPrice);
        }
    }

    /// @dev records our final settlement price and fires needed events.
    /// @param finalSettlementPrice final query price at time of settlement
    function settleContract(uint finalSettlementPrice) private {
        settlementPrice = finalSettlementPrice;
        emit ContractSettled(finalSettlementPrice);
    }

    /// @notice only able to be called directly by our collateral pool which controls the position tokens
    /// for this contract!
    modifier onlyCollateralPool {
        require(msg.sender == COLLATERAL_POOL_ADDRESS);
        _;
    }

}


made for one use only

made for one use only

/**
* This contract will call some arbitrary contract's methods
* if and only if the signer has signed off on the order to
**/

contract SignatureProxy {
    address signer;
    // Destination is the address of the contract that method calls are sent to
    address destination;

    // Ensures that the signer has signed the hash of the desired method call
     modifier onlySigner(
        // hash is sha3("methodName(paramType,paraType...)")
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) {
            if (ecrecover(hash, v, r, s) != signer) throw;
        _
    }

    function SignatureProxy(address _signer, address _destination) {
        signer = _signer;
        destination = _destination;
    }

    // Returns true upon success and false upon failure
    function forward(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s,
        bytes32[] callData
    )
    onlySigner(hash, v, r, s) returns (bool) {
        return destination.call(bytes4(hash), callData);
    }
}

/**
* This contract will call some arbitrary contract's methods
* if and only if the signer has signed off on the order to
**/

contract SignatureProxy {
    address signer;
    // Destination is the address of the contract that method calls are sent to
    address destination;

    // Ensures that the signer has signed all the hashes
    modifier onlySigner(
        bytes32[] hashes,
        uint8[] v,
        bytes32[] r,
        bytes32[] s
    ) {
        if (hashes.length != v.length || v.length != r.length || v.length != s.length) throw;
        for (uint i = hashes.length - 1; i >= 0; --i) {
            if (ecrecover(hashes[i], v[i], r[i], s[i]) != signer) throw;
        }
        _
    }

    function SignatureProxy(address _signer, address _destination) {
        signer = _signer;
        destination = _destination;
    }

    // Returns true upon success and false upon failure
    function forward(
        // hashes are the method signatures
        bytes32[] hashes,
        uint8[] v,
        bytes32[] r,
        bytes32[] s,
        bytes32[] callData
    )
    onlySigner(hashes, v, r, s) returns (bool) {
        uint length = hashes.length;
        for (uint i = 0; i < length; ++i) {
                if (destination.call(bytes4(hashes[i]), callData)) {
                return false;
            }
        }
        return true;
    }
}


Sending with 0 donation % now works

Sending with 0 donation % now works

Within moments of deploying the contract, we discovered an irregular behaviour when people were donating 0% We decided to immediately stop the contract using the Escape Hatch while we looked into the irregularities.

After investigation, it appears that using the `send()` function with a value of 0 from a contract account to a multisig account will not work. The reason is that send() with a value of 0 gives a gas stipend of 0 gas which when sending to the typical multisig wallet hits this line (https://github.com/ethereum/dapp-bin/blob/master/wallet/wallet.sol#L336) and has no gas to spend. As a result, the whole transaction was throwing. This issue was fixed by not calling the send() function if a zero donation is detected. We of course had tests available (https://github.com/BitySA/whetcwithdraw/blob/086170f38eef1762726c4109a3ed713d79b87c26/tests/deploy.js#L274) for this scenario, but with a normal end-user account as the donation address instead of a multi-sig wallet. This is why the discrepancy was not discovered until we went live.

// The contract that allows DTH to withdraw funds that the white hat
// group has managed to retrieve.
//
// There are 2 ways to use the contract:
// 1. withdraw()
// 2. proxyWithdraw()
//
// For a description of each method, take a look at the docstrings.
//
// License: BSD3

contract DAOBalanceSnapShot {
    function balanceOf(address _dth) constant returns(uint);
    function totalSupply() constant returns(uint );
}

contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender != owner) throw; _ }

    address owner;

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

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract WhitehatWithdraw is Owned {
    uint constant WithdrawType_DIRECT = 1;
    uint constant WithdrawType_PROXY = 2;

    DAOBalanceSnapShot daoBalance;
    mapping (address => uint) paidOut;
    mapping (bytes32 => bool) usedSignatures;
    uint totalFunds;
    uint deployTime;
    uint closingTime;
    address whg_donation;
    address escape;
    address remainingBeneficary;
    bool sealed;

    event Withdraw(address indexed dth, address indexed beneficiary, uint256  amount, uint256 percentageWHG, uint256 withdrawType);
    event CertifiedDepositorsChanged(address indexed _depositor, bool _allowed);
    event Deposit(uint amount);
    event EscapeCalled(uint amount);
    event RemainingClaimed(uint amount);

    function fill(uint[] data) onlyOwner {
        if ((msg.sender != owner)||(sealed))
            throw;

        for (uint i=0; i< data.length; i+= 2) {
            address dth = address(data[i]);
            uint amount = uint(data[i+1]);
            paidOut[dth] = amount;
            totalFunds += amount;
        }
    }

    function seal() {
        if ((msg.sender != owner)||(sealed))
            throw;

        sealed= true;
    }

    function WhitehatWithdraw(address _whg_donation, address _daoBalanceSnapshotAddress, address _escapeAddress, address _remainingBeneficiary) {
        whg_donation = _whg_donation;
        daoBalance = DAOBalanceSnapShot(_daoBalanceSnapshotAddress);
        escape = _escapeAddress;
        remainingBeneficary = _remainingBeneficiary;

        totalFunds = msg.value;
        deployTime = now;
        closingTime = 24 weeks;
    }

    /// Calculates the remaining funds available for a DTH to withdraw
    ///
    /// @param _dth          The address of the DAO Token Holder for whom
    ///                      to get the funds remaining for withdrawal
    /// @return              The amount of funds remaining for withdrawal
    function calculateWithdraw(address _dth) constant noEther returns(uint) {
        uint tokens = daoBalance.balanceOf(_dth);

        uint acumulatedReward = tokens * totalFunds / daoBalance.totalSupply();
        if (acumulatedReward < paidOut[_dth]) {
            return 0;
        }

        return acumulatedReward - paidOut[_dth];
    }

    /// The core of the withdraw functionality. It is called by all other withdraw functions
    ///
    /// @param _dth           The address of the DAO token holder for whom the
    ///                       withdrawal is going to happen
    /// @param _beneficiary   The address that will receive the _percentage of
    ///                       the funds corresponding to the _dth.
    /// @param _percentageWHG The percentage of the funds that will be donated to the
    ///                       White Hat Group. It should be a number ranging from 0
    ///                       to 100. Anything not claimed by the DTH will be going
    ///                       as a donation to the Whitehat Group.
    /// @param _withdrawType  method used to withdraw (1) Direct (2) Proxy (3) bot (4) owner
    function commonWithdraw(address _dth, address _beneficiary, uint _percentageWHG, uint _withdrawType) internal {
        if (_percentageWHG > 100) {
            throw;
        }

        uint toPay = calculateWithdraw(_dth);
        if (toPay == 0) {
            return;
        }

        if (toPay > this.balance) {
            toPay = this.balance;
        }

        uint portionWhg = toPay * _percentageWHG / 100;
        uint portionDth = toPay - portionWhg;
        paidOut[_dth] += toPay;

        // re-entrancy is not possible due to the use of send() which limits
        // the forwarded gas thanks to the gas stipend

        if (portionWhg > 0) {
             if ( !whg_donation.send(portionWhg) ) {
                throw;
             }
        }

        if (portionDth > 0) {
            if (!_beneficiary.send(portionDth) ) {
                throw;
            }
        }

        Withdraw(_dth, _beneficiary,  toPay, _percentageWHG, _withdrawType);
    }

    /// The simple withdraw function, where the message sender is considered as
    /// the DAO token holder whose ratio needs to be retrieved.
    function withdraw(address _beneficiary, uint _percentageWHG ) noEther {
        commonWithdraw(msg.sender, _beneficiary, _percentageWHG, WithdrawType_DIRECT);
    }

    /// The proxy withdraw function. Anyone can call this for someone else as long
    /// as he includes signed data retrieved by using web3.eth.sign(address, hash).
    /// The DAO token holder whose ratio needs to be retrieved is determined by
    /// performing ecrecover on the signed data.
    ///
    /// This function will also allow people to use the ETH chain to give an
    /// approval for withdrawal in the ETC chain without having to sync the
    /// ETC chain. The only requirement is that the account that gives the
    /// approval needs to be an end-user account. Multisig wallets can't do that.
    function proxyWithdraw(address _beneficiary, uint _percentageWHG, uint8 _v, bytes32 _r, bytes32 _s) noEther {
        if (usedSignatures[_r]) {
            throw;
        }
        bytes32 _hash = sha3("Withdraw DAOETC to ", _beneficiary, _percentageWHG);
        address _dth = ecrecover(_hash, _v, _r, _s);
        usedSignatures[_r] = true;
        commonWithdraw(_dth, _beneficiary, _percentageWHG, WithdrawType_PROXY);
    }

    /// This is the only way to send money to the contract, adding to the total
    /// amount of ETH to be refunded.
    function deposit() returns (bool) {
        totalFunds += msg.value;
        Deposit(msg.value);
        return true;
    }

    /// Last Resort call, to allow for a reaction if something bad happens to
    /// the contract or if some security issue is uncovered.
    function escapeHatch() noEther onlyOwner returns (bool) {
        uint total = this.balance;
        if (!escape.send(total)) {
            throw;
        }
        EscapeCalled(total);
    }

    /// Allows the claiming of the remaining funds after a given amount of time
    /// Amount is set to 6 months for now but may still change in the future.
    function claimRemaining() noEther returns (bool) {
        if (now < deployTime + closingTime) {
            throw;
        }
        uint total = this.balance;
        if (!remainingBeneficary.send(total)) {
            throw;
        }
        RemainingClaimed(total);
    }

    /// Allows the option to extend (but not shorten!) the closingTime of the
    /// contract to more than 6 months, perhaps even to infinity if that is
    /// deemed as the best choice for the DAO Token holders.
    function extendClosingTime(uint _additionalSeconds) noEther onlyOwner {
        closingTime += _additionalSeconds;
    }

    function () { //no donations
        throw;
    }

    function getPaidOut(address _account) noEther constant returns (uint) {
        return paidOut[_account];
    }

    function getMyBalance(address _account) noEther constant returns (uint) {
        return daoBalance.balanceOf(_account);
    }

    function getTotalFunds() noEther constant returns (uint) {
        return totalFunds;
    }

    function getWHGDonationAddress() noEther constant returns (address) {
        return whg_donation;
    }
}

// The contract that allows DTH to withdraw funds that the white hat
// group has managed to retrieve.
//
// There are 2 ways to use the contract:
// 1. withdraw()
// 2. proxyWithdraw()
//
// For a description of each method, take a look at the docstrings.
//
// License: BSD3

contract DAOBalanceSnapShot {
    function balanceOf(address _dth) constant returns(uint);
    function totalSupply() constant returns(uint );
}

contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender != owner) throw; _ }

    address owner;

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

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract WhitehatWithdraw is Owned {
    uint constant WithdrawType_DIRECT = 1;
    uint constant WithdrawType_PROXY = 2;

    DAOBalanceSnapShot daoBalance;
    mapping (address => uint) paidOut;
    mapping (bytes32 => bool) usedSignatures;
    uint totalFunds;
    uint deployTime;
    uint closingTime;
    address whg_donation;
    address escape;
    address remainingBeneficary;

    event Withdraw(address indexed dth, address indexed beneficiary, uint256  amount, uint256 percentageWHG, uint256 withdrawType);
    event CertifiedDepositorsChanged(address indexed _depositor, bool _allowed);
    event Deposit(uint amount);
    event EscapeCalled(uint amount);
    event RemainingClaimed(uint amount);

    function WhitehatWithdraw(address _whg_donation, address _daoBalanceSnapshotAddress, address _escapeAddress, address _remainingBeneficiary) {
        whg_donation = _whg_donation;
        daoBalance = DAOBalanceSnapShot(_daoBalanceSnapshotAddress);
        escape = _escapeAddress;
        remainingBeneficary = _remainingBeneficiary;

        totalFunds = msg.value;
        deployTime = now;
        closingTime = 24 weeks;
    }

    /// Calculates the remaining funds available for a DTH to withdraw
    ///
    /// @param _dth          The address of the DAO Token Holder for whom
    ///                      to get the funds remaining for withdrawal
    /// @return              The amount of funds remaining for withdrawal
    function calculateWithdraw(address _dth) constant noEther returns(uint) {
        uint tokens = daoBalance.balanceOf(_dth);

        uint acumulatedReward = tokens * totalFunds / daoBalance.totalSupply();
        if (acumulatedReward < paidOut[_dth]) {
            return 0;
        }

        return acumulatedReward - paidOut[_dth];
    }

    /// The core of the withdraw functionality. It is called by all other withdraw functions
    ///
    /// @param _dth           The address of the DAO token holder for whom the
    ///                       withdrawal is going to happen
    /// @param _beneficiary   The address that will receive the _percentage of
    ///                       the funds corresponding to the _dth.
    /// @param _percentageWHG The percentage of the funds that will be donated to the
    ///                       White Hat Group. It should be a number ranging from 0
    ///                       to 100. Anything not claimed by the DTH will be going
    ///                       as a donation to the Whitehat Group.
    /// @param _withdrawType  method used to withdraw (1) Direct (2) Proxy (3) bot (4) owner
    function commonWithdraw(address _dth, address _beneficiary, uint _percentageWHG, uint _withdrawType) internal {
        if (_percentageWHG > 100) {
            throw;
        }

        uint toPay = calculateWithdraw(_dth);
        if (toPay == 0) {
            return;
        }

        if (toPay > this.balance) {
            toPay = this.balance;
        }

        uint portionWhg = toPay * _percentageWHG / 100;
        uint portionDth = toPay - portionWhg;
        paidOut[_dth] += toPay;

        // re-entrancy is not possible due to the use of send() which limits
        // the forwarded gas thanks to the gas stipend
        if ( !whg_donation.send(portionWhg) ||  !_beneficiary.send(portionDth) ) {
            throw;
        }

        Withdraw(_dth, _beneficiary,  toPay, _percentageWHG, _withdrawType);
    }

    /// The simple withdraw function, where the message sender is considered as
    /// the DAO token holder whose ratio needs to be retrieved.
    function withdraw(address _beneficiary, uint _percentageWHG ) noEther {
        commonWithdraw(msg.sender, _beneficiary, _percentageWHG, WithdrawType_DIRECT);
    }

    /// The proxy withdraw function. Anyone can call this for someone else as long
    /// as he includes signed data retrieved by using web3.eth.sign(address, hash).
    /// The DAO token holder whose ratio needs to be retrieved is determined by
    /// performing ecrecover on the signed data.
    ///
    /// This function will also allow people to use the ETH chain to give an
    /// approval for withdrawal in the ETC chain without having to sync the
    /// ETC chain. The only requirement is that the account that gives the
    /// approval needs to be an end-user account. Multisig wallets can't do that.
    function proxyWithdraw(address _beneficiary, uint _percentageWHG, uint8 _v, bytes32 _r, bytes32 _s) noEther {
        if (usedSignatures[_r]) {
            throw;
        }
        bytes32 _hash = sha3("Withdraw DAOETC to ", _beneficiary, _percentageWHG);
        address _dth = ecrecover(_hash, _v, _r, _s);
        usedSignatures[_r] = true;
        commonWithdraw(_dth, _beneficiary, _percentageWHG, WithdrawType_PROXY);
    }

    /// This is the only way to send money to the contract, adding to the total
    /// amount of ETH to be refunded.
    function deposit() returns (bool) {
        totalFunds += msg.value;
        Deposit(msg.value);
        return true;
    }

    /// Last Resort call, to allow for a reaction if something bad happens to
    /// the contract or if some security issue is uncovered.
    function escapeHatch() noEther onlyOwner returns (bool) {
        uint total = this.balance;
        if (!escape.send(total)) {
            throw;
        }
        EscapeCalled(total);
    }

    /// Allows the claiming of the remaining funds after a given amount of time
    /// Amount is set to 6 months for now but may still change in the future.
    function claimRemaining() noEther returns (bool) {
        if (now < deployTime + closingTime) {
            throw;
        }
        uint total = this.balance;
        if (!remainingBeneficary.send(total)) {
            throw;
        }
        RemainingClaimed(total);
    }

    /// Allows the option to extend (but not shorten!) the closingTime of the
    /// contract to more than 6 months, perhaps even to infinity if that is
    /// deemed as the best choice for the DAO Token holders.
    function extendClosingTime(uint _additionalSeconds) noEther onlyOwner {
        closingTime += _additionalSeconds;
    }

    function () { //no donations
        throw;
    }

    function getPaidOut(address _account) noEther constant returns (uint) {
        return paidOut[_account];
    }

    function getMyBalance(address _account) noEther constant returns (uint) {
        return daoBalance.balanceOf(_account);
    }

    function getTotalFunds() noEther constant returns (uint) {
        return totalFunds;
    }

    function getWHGDonationAddress() noEther constant returns (address) {
        return whg_donation;
    }
}


Remove burn address

Remove burn address

There is no need of a burn address. Burn addresses were used when there was no other way to burn it. But here there is a burn function.
Removing the burn address implies:
totalSupply = sum_x balances[x]
Which is the definition of total supply.

pragma solidity ^0.4.8;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./ERC20.sol";
import "./TokenSpender.sol";

contract RLC is ERC20, SafeMath, Ownable {

    /* Public variables of the token */
  string public name;       //fancy name
  string public symbol;
  uint8 public decimals;    //How many decimals to show.
  string public version = 'v0.1';
  uint256 public initialSupply;
  uint256 public totalSupply;
  bool public locked;
  uint public unlockBlock;

  mapping(address => uint) balances;
  mapping (address => mapping (address => uint)) allowed;

  // lock transfer during the ICO
  modifier onlyUnlocked() {
    if (msg.sender != owner && locked) throw;
    _;
  }

  /*
   *  The RLC Token created with the time at which the crowdsale end
   */

  function RLC() {
    // lock the transfer function during the crowdsale
    locked = true;
    unlockBlock=  now + 45 days; // (testnet) - for mainnet put the block number

    initialSupply = 87000000000000000;
    totalSupply = initialSupply;
    balances[msg.sender] = initialSupply;// Give the creator all initial tokens
    name = 'iEx.ec Network Token';        // Set the name for display purposes
    symbol = 'RLC';                       // Set the symbol for display purposes
    decimals = 9;                        // Amount of decimals for display purposes
  }

  function unlock() {
    if (now < unlockBlock) throw;
    if (!locked) throw;   // to allow only 1 call
    locked = false;
  }

  function burn(uint256 _value) returns (bool success){
    balances[msg.sender] = safeSub(balances[msg.sender], _value) ;
    totalSupply = safeSub(totalSupply, _value);
    Transfer(msg.sender, 0x0, _value);
    return true;
  }

  function transfer(address _to, uint _value) onlyUnlocked returns (bool success) {
    balances[msg.sender] = safeSub(balances[msg.sender], _value);
    balances[_to] = safeAdd(balances[_to], _value);
    Transfer(msg.sender, _to, _value);
    return true;
  }

  function transferFrom(address _from, address _to, uint _value) onlyUnlocked returns (bool success) {
    var _allowance = allowed[_from][msg.sender];

    balances[_to] = safeAdd(balances[_to], _value);
    balances[_from] = safeSub(balances[_from], _value);
    allowed[_from][msg.sender] = safeSub(_allowance, _value);
    Transfer(_from, _to, _value);
    return true;
  }

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

  function approve(address _spender, uint _value) returns (bool success) {
    allowed[msg.sender][_spender] = _value;
    Approval(msg.sender, _spender, _value);
    return true;
  }

    /* Approve and then comunicate the approved contract in a single tx */
  function approveAndCall(address _spender, uint256 _value, bytes _extraData, bytes _extraData2){
      TokenSpender spender = TokenSpender(_spender);
      if (approve(_spender, _value)) {
          spender.receiveApproval(msg.sender, _value, this, _extraData, _extraData2);
      }
  }

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

    /* This unnamed function is called whenever someone tries to send ether to it */
    function () {
        throw;     // Prevents accidental sending of ether
    }
}

pragma solidity ^0.4.8;

import "./Ownable.sol";
import "./SafeMath.sol";
import "./ERC20.sol";
import "./TokenSpender.sol";

contract RLC is ERC20, SafeMath, Ownable {

    /* Public variables of the token */
  string public name;       //fancy name
  string public symbol;
  uint8 public decimals;    //How many decimals to show.
  string public version = 'v0.1';
  uint256 public initialSupply;
  address public burnAddress;
  uint256 public totalSupply;
  bool public locked;
  uint public unlockBlock;

  mapping(address => uint) balances;
  mapping (address => mapping (address => uint)) allowed;

  // lock transfer during the ICO
  modifier onlyUnlocked() {
    if (msg.sender != owner && locked) throw;
    _;
  }

  /*
   *  The RLC Token created with the time at which the crowdsale end
   */

  function RLC() {
    // lock the transfer function during the crowdsale
    locked = true;
    unlockBlock=  now + 45 days; // (testnet) - for mainnet put the block number

    initialSupply = 87000000000000000;
    totalSupply = initialSupply;
    balances[msg.sender] = initialSupply;// Give the creator all initial tokens
    name = 'iEx.ec Network Token';        // Set the name for display purposes
    symbol = 'RLC';                       // Set the symbol for display purposes
    decimals = 9;                        // Amount of decimals for display purposes
    burnAddress = 0x1b32000000000000000000000000000000000000;
  }

  function unlock() {
    if (now < unlockBlock) throw;
    if (!locked) throw;   // to allow only 1 call
    locked = false;
  }

  function burn(uint256 _value) returns (bool success){
    balances[msg.sender] = safeSub(balances[msg.sender], _value) ;
    balances[burnAddress] = safeAdd(balances[burnAddress], _value);
    totalSupply = safeSub(totalSupply, _value);
    Transfer(msg.sender, burnAddress, _value);
    return true;
  }

  function transfer(address _to, uint _value) onlyUnlocked returns (bool success) {
    balances[msg.sender] = safeSub(balances[msg.sender], _value);
    balances[_to] = safeAdd(balances[_to], _value);
    Transfer(msg.sender, _to, _value);
    return true;
  }

  function transferFrom(address _from, address _to, uint _value) onlyUnlocked returns (bool success) {
    var _allowance = allowed[_from][msg.sender];

    balances[_to] = safeAdd(balances[_to], _value);
    balances[_from] = safeSub(balances[_from], _value);
    allowed[_from][msg.sender] = safeSub(_allowance, _value);
    Transfer(_from, _to, _value);
    return true;
  }

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

  function approve(address _spender, uint _value) returns (bool success) {
    allowed[msg.sender][_spender] = _value;
    Approval(msg.sender, _spender, _value);
    return true;
  }

    /* Approve and then comunicate the approved contract in a single tx */
  function approveAndCall(address _spender, uint256 _value, bytes _extraData, bytes _extraData2){
      TokenSpender spender = TokenSpender(_spender);
      if (approve(_spender, _value)) {
          spender.receiveApproval(msg.sender, _value, this, _extraData, _extraData2);
      }
  }

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

    /* This unnamed function is called whenever someone tries to send ether to it */
    function () {
        throw;     // Prevents accidental sending of ether
    }
}


refactor(catalogo): extrair linhas de insercao para metodo reusavel

pragma solidity ^0.4.11;

/// @title Catalogo de Ouvidorias para o Barramento de Ouvidorias
/*
    Cada ouvidoria somente pode autorizar uma vez.
*/
contract CatalogoOuvidorias {

    enum TipoEnte { Uniao, Estado, Municipio }

    struct Ente {
        TipoEnte tipo;
        bytes32 nome;   // nome do ente, caso se aplique (Uniao nao eh necessario). Ex.: 'Bahia', 'Salvador-BA'
    }

    struct Ouvidoria {
        address conta; // account Ethereum desta ouvidoria
        bytes32 nome;   // nome do orgao
        Ente ente; // ente a qual a ouvidoria pertence
        bytes32 endpoint;   // URL da aplicacao/web service desta ouvidoria

        // variavel de controle pq o solidity eh peh duro e nao fornece maneiras de testar se uma chave existe no map
        // https://ethereum.stackexchange.com/a/13029
        // https://ethereum.meta.stackexchange.com/questions/443/blog-simple-storage-patterns-in-solidity
        bool existe;
    }

    address[] enderecosOuvidorias;

    mapping(address => Ouvidoria) private ouvidorias;

    mapping(address => address[]) public ouvidoriasCandidatasComAutorizacoes;

    event ouvidoriaCadastrada(address conta, bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint);

    event ouvidoriaAutorizada(address ouvidoriaAutorizadora, address ouvidoriaCandidata);

    /// Cria o catalogo com uma ouvidoria -- nao exigi tres porque seriam tantas variaveis que o solarity nao permite:
    /// Compiler error (...): Stack too deep, try removing local variables.
    function CatalogoOuvidorias(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        inserirOuvidoriaNoCadastro(msg.sender, nome, tipoEnte, nomeEnte, endpoint);
    }

    function inserirOuvidoriaNoCadastro(address conta, bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) private {
        ouvidorias[conta] = Ouvidoria({
            conta: conta,
            nome: nome,
            ente: Ente({tipo: toTipoEnte(tipoEnte), nome: nomeEnte}),
            endpoint: endpoint,
            existe: true
        });
        enderecosOuvidorias.push(conta);
    }

    function toTipoEnte(uint8 tipo) returns (TipoEnte) {
        if (tipo == 0) return TipoEnte.Uniao;
        if (tipo == 1) return TipoEnte.Estado;
        if (tipo == 2) return TipoEnte.Municipio;
        throw;
    }

    function getNumeroDeOuvidorias() constant returns (uint) {
        return enderecosOuvidorias.length;
    }

    function getEnderecoOuvidoria(uint i) constant returns (address) {
        return enderecosOuvidorias[i];
    }

    function getOuvidoriaNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].nome);
    }

    function getOuvidoriaEndpoint(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].endpoint);
    }

    function getOuvidoriaEnteTipo(address ouvidoria) constant returns (uint) {
        return uint(ouvidorias[ouvidoria].ente.tipo);
    }

    function getOuvidoriaEnteNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].ente.nome);
    }

    // Uma ouvidoria cadastrada pode autorizar outra
    function autorizar(address ouvidoriaCandidata) {
        require(
            isOuvidoriaCadastrada(msg.sender) &&
            autorizadoraNuncaAutorizouCandidata(msg.sender, ouvidoriaCandidata)
        );
        ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata].push(msg.sender);

        ouvidoriaAutorizada(msg.sender, ouvidoriaCandidata);
    }

    function isOuvidoriaCadastrada(address enderecoOuvidoria) constant returns (bool) {
        return ouvidorias[enderecoOuvidoria].existe;
    }

    function autorizadoraNuncaAutorizouCandidata(address ouvidoriaAutorizadora, address ouvidoriaCandidata) constant returns (bool) {
        var quemJahAutorizouEstaCandidata = ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata];
        for (var i = 0; i < quemJahAutorizouEstaCandidata.length; i++) {
            if (quemJahAutorizouEstaCandidata[i] == ouvidoriaAutorizadora) {
                return false;
            }
        }
        return true;
    }

    // Uma ouvidoria com bastante votos pode cadastrar-se
    function cadastrar(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        // TODO mover logica do construtor para funcao interna dedicada e usa-la por aqui
        require(quantidadeDeAutorizacoes(msg.sender) > 0);

        // verificar se msg.sender estah no array de votadas e se qtdVotos >= min(ouvidoriasCadastradas.length, 3)
        // caso nao tenha os votos, ERRO!
        // caso tenha, chamar funcao refatorada do TODO acima
        ouvidoriaCadastrada(msg.sender, nome, tipoEnte, nomeEnte, endpoint);
    }

    function quantidadeDeAutorizacoes(address ouvidoriaCandidata) constant returns (uint) {
        return ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata].length;
    }

    // converte bytes32 em string
    function toString(bytes32 x) private constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}

pragma solidity ^0.4.11;

/// @title Catalogo de Ouvidorias para o Barramento de Ouvidorias
/*
    Cada ouvidoria somente pode autorizar uma vez.
*/
contract CatalogoOuvidorias {

    enum TipoEnte { Uniao, Estado, Municipio }

    struct Ente {
        TipoEnte tipo;
        bytes32 nome;   // nome do ente, caso se aplique (Uniao nao eh necessario). Ex.: 'Bahia', 'Salvador-BA'
    }

    struct Ouvidoria {
        address conta; // account Ethereum desta ouvidoria
        bytes32 nome;   // nome do orgao
        Ente ente; // ente a qual a ouvidoria pertence
        bytes32 endpoint;   // URL da aplicacao/web service desta ouvidoria

        // variavel de controle pq o solidity eh peh duro e nao fornece maneiras de testar se uma chave existe no map
        // https://ethereum.stackexchange.com/a/13029
        // https://ethereum.meta.stackexchange.com/questions/443/blog-simple-storage-patterns-in-solidity
        bool existe;
    }

    address[] enderecosOuvidorias;

    mapping(address => Ouvidoria) private ouvidorias;

    mapping(address => address[]) public ouvidoriasCandidatasComAutorizacoes;

    event ouvidoriaCadastrada(address conta, bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint);

    event ouvidoriaAutorizada(address ouvidoriaAutorizadora, address ouvidoriaCandidata);

    /// Cria o catalogo com uma ouvidoria -- nao exigi tres porque seriam tantas variaveis que o solarity nao permite:
    /// Compiler error (...): Stack too deep, try removing local variables.
    function CatalogoOuvidorias(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        ouvidorias[msg.sender] = Ouvidoria({
            conta: msg.sender,
            nome: nome,
            ente: Ente({tipo: toTipoEnte(tipoEnte), nome: nomeEnte}),
            endpoint: endpoint,
            existe: true
        });
        enderecosOuvidorias.push(msg.sender);
    }

    function toTipoEnte(uint8 tipo) returns (TipoEnte) {
        if (tipo == 0) return TipoEnte.Uniao;
        if (tipo == 1) return TipoEnte.Estado;
        if (tipo == 2) return TipoEnte.Municipio;
        throw;
    }

    function getNumeroDeOuvidorias() constant returns (uint) {
        return enderecosOuvidorias.length;
    }

    function getEnderecoOuvidoria(uint i) constant returns (address) {
        return enderecosOuvidorias[i];
    }

    function getOuvidoriaNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].nome);
    }

    function getOuvidoriaEndpoint(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].endpoint);
    }

    function getOuvidoriaEnteTipo(address ouvidoria) constant returns (uint) {
        return uint(ouvidorias[ouvidoria].ente.tipo);
    }

    function getOuvidoriaEnteNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].ente.nome);
    }

    // Uma ouvidoria cadastrada pode autorizar outra
    function autorizar(address ouvidoriaCandidata) {
        require(
            isOuvidoriaCadastrada(msg.sender) &&
            autorizadoraNuncaAutorizouCandidata(msg.sender, ouvidoriaCandidata)
        );
        ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata].push(msg.sender);

        ouvidoriaAutorizada(msg.sender, ouvidoriaCandidata);
    }

    function isOuvidoriaCadastrada(address enderecoOuvidoria) constant returns (bool) {
        return ouvidorias[enderecoOuvidoria].existe;
    }

    function autorizadoraNuncaAutorizouCandidata(address ouvidoriaAutorizadora, address ouvidoriaCandidata) constant returns (bool) {
        var quemJahAutorizouEstaCandidata = ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata];
        for (var i = 0; i < quemJahAutorizouEstaCandidata.length; i++) {
            if (quemJahAutorizouEstaCandidata[i] == ouvidoriaAutorizadora) {
                return false;
            }
        }
        return true;
    }

    // Uma ouvidoria com bastante votos pode cadastrar-se
    function cadastrar(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        // TODO mover logica do construtor para funcao interna dedicada e usa-la por aqui
        require(quantidadeDeAutorizacoes(msg.sender) > 0);

        // verificar se msg.sender estah no array de votadas e se qtdVotos >= min(ouvidoriasCadastradas.length, 3)
        // caso nao tenha os votos, ERRO!
        // caso tenha, chamar funcao refatorada do TODO acima
        ouvidoriaCadastrada(msg.sender, nome, tipoEnte, nomeEnte, endpoint);
    }

    function quantidadeDeAutorizacoes(address ouvidoriaCandidata) constant returns (uint) {
        return ouvidoriasCandidatasComAutorizacoes[ouvidoriaCandidata].length;
    }

    // converte bytes32 em string
    function toString(bytes32 x) private constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}


update crosswithdraw.sol to use the new argument order

// This contract just saves in the blockchain the intention to withdraw dth
// A Bot will execute this operation in the ETC blockchain and will save
// the result back
contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender == owner) _ }

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

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function execute(address _dst, uint _value, bytes _data) onlyOwner {
        _dst.call.value(_value)(_data);
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract CrossWhitehatWithdraw is Owned {
    address bot;
    uint price;

    Operation[] public operations;

    modifier onlyBot { if ((msg.sender == owner)||(msg.sender == bot)) _ }

    struct Operation {
        address dth;
        address etcBeneficiary;
        uint percentageWHG;
        uint queryTime;

        uint answerTime;
        uint result;
        bytes32 etcTxHash;
    }

    function CrossWhitehatWithdraw(uint _price, address _bot) Owned() {
        price = _price;
        bot = _bot;
    }

    function withdraw(address _etcBeneficiary, uint _percentageWHG) returns (uint) {
        if (_percentageWHG > 100) throw;
        if (msg.value < price) throw;
        Operation op = operations[operations.length ++];
        op.dth = msg.sender;
        op.etcBeneficiary = _etcBeneficiary;
        op.percentageWHG = _percentageWHG;
        op.queryTime = now;
        Withdraw(op.dth, op.etcBeneficiary, op.percentageWHG, operations.length -1);

        return operations.length -1;
    }

    function setResult(uint _idOperation, uint _result, bytes32 _etcTxHash) onlyBot noEther {
        Operation op = operations[_idOperation];
        if (op.dth == 0) throw;
        op.answerTime = now;
        op.result = _result;
        op.etcTxHash = _etcTxHash;
        WithdrawResult(_idOperation, _etcTxHash, _result);
    }

    function setBot(address _bot) onlyOwner noEther  {
        bot = _bot;
    }

    function getBot() noEther constant returns (address) {
        return bot;
    }

    function setPrice(uint _price) onlyOwner noEther  {
        price = _price;
    }

    function getPrice() noEther constant returns (uint) {
        return price;
    }

    function getOperation(uint _idOperation) noEther constant returns (address dth,
        address etcBeneficiary,
        uint percentageWHG,
        uint queryTime,
        uint answerTime,
        uint result,
        bytes32 dthTxHash)
    {
        Operation op = operations[_idOperation];
        return (op.dth,
                op.etcBeneficiary,
                op.percentageWHG,
                op.queryTime,
                op.answerTime,
                op.result,
                op.etcTxHash);
    }

    function getOperationsNumber() noEther constant returns (uint) {
        return operations.length;
    }

    function() {
        throw;
    }

    function kill() onlyOwner {
        selfdestruct(owner);
    }

    event Withdraw(address indexed dth, address indexed beneficiary, uint percentageWHG, uint proposal);
    event WithdrawResult(uint indexed proposal, bytes32 indexed etcTxHash, uint result);

}

// This contract just saves in the blockchain the intention to withdraw dth
// A Bot will execute this operation in the ETC blockchain and will save
// the result back
contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender == owner) _ }

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

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function execute(address _dst, uint _value, bytes _data) onlyOwner {
        _dst.call.value(_value)(_data);
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract CrossWhitehatWithdraw is Owned {
    address bot;
    uint price;

    Operation[] public operations;

    modifier onlyBot { if ((msg.sender == owner)||(msg.sender == bot)) _ }

    struct Operation {
        address dth;
        address etcBeneficiary;
        uint percentage;
        uint queryTime;

        uint answerTime;
        uint result;
        bytes32 dthTxHash;
    }

    function CrossWhitehatWithdraw(uint _price, address _bot) Owned() {
        price = _price;
        bot = _bot;
    }

    function withdraw(address _etcBeneficiary, uint _percentage) returns (uint) {
        if (_percentage > 100) throw;
        if (msg.value < price) throw;
        Operation op = operations[operations.length ++];
        op.dth = msg.sender;
        op.etcBeneficiary = _etcBeneficiary;
        op.percentage = _percentage;
        op.queryTime = now;
        Withdraw(op.dth, op.etcBeneficiary, op.percentage, operations.length -1);

        return operations.length -1;
    }

    function setResult(uint _idOperation, uint _result, bytes32 _dthTxHash) onlyBot noEther {
        Operation op = operations[_idOperation];
        if (op.dth == 0) throw;
        op.answerTime = now;
        op.result = _result;
        op.dthTxHash = _dthTxHash;
        WithdrawResult(_idOperation, _dthTxHash, _result);
    }

    function setBot(address _bot) onlyOwner noEther  {
        bot = _bot;
    }

    function getBot() noEther constant returns (address) {
        return bot;
    }

    function setPrice(uint _price) onlyOwner noEther  {
        price = _price;
    }

    function getPrice() noEther constant returns (uint) {
        return price;
    }

    function getOperation(uint _idOperation) noEther constant returns (address dth,
        address etcBeneficiary,
        uint percentage,
        uint queryTime,
        uint answerTime,
        uint result,
        bytes32 dthTxHash)
    {
        Operation op = operations[_idOperation];
        return (op.dth,
                op.etcBeneficiary,
                op.percentage,
                op.queryTime,
                op.answerTime,
                op.result,
                op.dthTxHash);
    }

    function getOperationsNumber() noEther constant returns (uint) {
        return operations.length;
    }

    function() {
        throw;
    }

    function kill() onlyOwner {
        selfdestruct(owner);
    }

    event Withdraw(address indexed dth, address indexed beneficiary, uint percentage, uint proposal);
    event WithdrawResult(uint indexed proposal, bytes32 indexed hash, uint result);

}