Fix: Use transfer instead of send (#29)

Fix: Use transfer instead of send (#29)

pragma solidity 0.4.11;

import '../SafeMath.sol';
import "../ownership/Ownable.sol";
import "../controller/ControllerInterface.sol";

/**
 * @title PullPayment
 * @dev Base contract supporting async send for pull payments.
 */
contract PullPayment is Ownable {
  using SafeMath for uint256;

  struct Payment {
    uint256 value;  // TODO: use compact storage
    uint256 date;   //
  }

  uint public dailyLimit = 1000000000000000000000;  // 1 ETH
  uint public lastDay;
  uint public spentToday;

  mapping(address => Payment) internal payments;

  modifier whenNotPaused () {
    require(!ControllerInterface(owner).paused());
     _;
  }
  function balanceOf(address _owner) constant returns (uint256 value) {
    return payments[_owner].value;
  }

  function paymentOf(address _owner) constant returns (uint256 value, uint256 date) {
    value = payments[_owner].value;
    date = payments[_owner].date;
    return;
  }

  /// @dev Allows to change the daily limit. Transaction has to be sent by wallet.
  /// @param _dailyLimit Amount in wei.
  function changeDailyLimit(uint _dailyLimit) public onlyOwner {
      dailyLimit = _dailyLimit;
  }

  function changeWithdrawalDate(address _owner, uint256 _newDate)  public onlyOwner {
    // allow to withdraw immediately
    // move witdrawal date more days into future
    payments[_owner].date = _newDate;
  }

  function asyncSend(address _dest) public payable onlyOwner {
    require(msg.value > 0);
    uint256 newValue = payments[_dest].value.add(msg.value);
    uint256 newDate;
    if (isUnderLimit(msg.value)) {
      newDate = (payments[_dest].date > now) ? payments[_dest].date : now;
    } else {
      newDate = now.add(3 days);
    }
    spentToday = spentToday.add(msg.value);
    payments[_dest] = Payment(newValue, newDate);
  }

  function withdraw() public whenNotPaused {
    address untrustedRecipient = msg.sender;
    uint256 amountWei = payments[untrustedRecipient].value;

    require(amountWei != 0);
    require(now >= payments[untrustedRecipient].date);
    require(this.balance >= amountWei);

    payments[untrustedRecipient].value = 0;

    untrustedRecipient.transfer(amountWei);
  }

  /*
   * Internal functions
   */
  /// @dev Returns if amount is within daily limit and resets spentToday after one day.
  /// @param amount Amount to withdraw.
  /// @return Returns if amount is under daily limit.
  function isUnderLimit(uint amount) internal returns (bool) {
    if (now > lastDay.add(24 hours)) {
      lastDay = now;
      spentToday = 0;
    }
    // not using safe math because we don't want to throw;
    if (spentToday + amount > dailyLimit || spentToday + amount < spentToday) {
      return false;
    }
    return true;
  }

}

pragma solidity 0.4.11;

import '../SafeMath.sol';
import "../ownership/Ownable.sol";
import "../controller/ControllerInterface.sol";

/**
 * @title PullPayment
 * @dev Base contract supporting async send for pull payments.
 */
contract PullPayment is Ownable {
  using SafeMath for uint256;

  struct Payment {
    uint256 value;  // TODO: use compact storage
    uint256 date;   //
  }

  uint public dailyLimit = 1000000000000000000000;  // 1 ETH
  uint public lastDay;
  uint public spentToday;

  mapping(address => Payment) internal payments;

  modifier whenNotPaused () {
    require(!ControllerInterface(owner).paused());
     _;
  }
  function balanceOf(address _owner) constant returns (uint256 value) {
    return payments[_owner].value;
  }

  function paymentOf(address _owner) constant returns (uint256 value, uint256 date) {
    value = payments[_owner].value;
    date = payments[_owner].date;
    return;
  }

  /// @dev Allows to change the daily limit. Transaction has to be sent by wallet.
  /// @param _dailyLimit Amount in wei.
  function changeDailyLimit(uint _dailyLimit) public onlyOwner {
      dailyLimit = _dailyLimit;
  }

  function changeWithdrawalDate(address _owner, uint256 _newDate)  public onlyOwner {
    // allow to withdraw immediately
    // move witdrawal date more days into future
    payments[_owner].date = _newDate;
  }

  function asyncSend(address _dest) public payable onlyOwner {
    require(msg.value > 0);
    uint256 newValue = payments[_dest].value.add(msg.value);
    uint256 newDate;
    if (isUnderLimit(msg.value)) {
      newDate = (payments[_dest].date > now) ? payments[_dest].date : now;
    } else {
      newDate = now.add(3 days);
    }
    spentToday = spentToday.add(msg.value);
    payments[_dest] = Payment(newValue, newDate);
  }

  function withdraw() public whenNotPaused {
    address untrustedRecipient = msg.sender;
    uint256 amountWei = payments[untrustedRecipient].value;

    require(amountWei != 0);
    require(now >= payments[untrustedRecipient].date);
    require(this.balance >= amountWei);

    payments[untrustedRecipient].value = 0;

    assert(untrustedRecipient.send(amountWei));
  }

  /*
   * Internal functions
   */
  /// @dev Returns if amount is within daily limit and resets spentToday after one day.
  /// @param amount Amount to withdraw.
  /// @return Returns if amount is under daily limit.
  function isUnderLimit(uint amount) internal returns (bool) {
    if (now > lastDay.add(24 hours)) {
      lastDay = now;
      spentToday = 0;
    }
    // not using safe math because we don't want to throw;
    if (spentToday + amount > dailyLimit || spentToday + amount < spentToday) {
      return false;
    }
    return true;
  }

}


Delete TokenSellerFactory.sol

Delete TokenSellerFactory.sol

pragma solidity ^0.4.4;

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

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

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

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

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

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

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

contract TokenSeller is Owned {

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

    bool public sellsTokens;    // is contract selling

    event ActivatedEvent(bool sells);
    event MakerWithdrewAsset(uint256 tokens);
    event MakerWithdrewERC20Token(address tokenAddress, uint256 tokens);
    event MakerWithdrewEther(uint256 ethers);
    event TakerBoughtAsset(address indexed buyer, uint256 ethersSent,
        uint256 ethersReturned, uint256 tokensBought);

    // Constructor - only to be called by the TokenSellerFactory contract
    function TokenSeller (
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) internal {
        asset       = _asset;
        sellPrice   = _sellPrice;
        units       = _units;
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can activate or deactivate this contract's
    // selling status
    //
    // The ActivatedEvent() event is logged with the following
    // parameter:
    //   sellsTokens  this contract can sell asset tokens
    function activate (
        bool _sellsTokens
    ) onlyOwner {
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can withdraw asset tokens from this contract, with the
    // following parameter:
    //   tokens  is the number of asset tokens to be withdrawn
    //
    // The MakerWithdrewAsset() event is logged with the following
    // parameter:
    //   tokens  is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawAsset() in the old version
    function makerWithdrawAsset(uint256 tokens) onlyOwner returns (bool ok) {
        MakerWithdrewAsset(tokens);
        return ERC20Partial(asset).transfer(owner, tokens);
    }

    // Maker can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The MakerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawToken() in the old version
    function makerWithdrawERC20Token(
        address tokenAddress,
        uint256 tokens
    ) onlyOwner returns (bool ok) {
        MakerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

    // Maker withdraws ethers from this contract
    //
    // The MakerWithdrewEther() event is logged with the following parameter
    //   ethers  is the number of ethers withdrawn by the maker
    //
    // This method was called withdraw() in the old version
    function makerWithdrawEther(uint256 ethers) onlyOwner returns (bool ok) {
        if (this.balance >= ethers) {
            MakerWithdrewEther(ethers);
            return owner.send(ethers);
        }
    }

    // Taker buys asset tokens by sending ethers
    //
    // The TakerBoughtAsset() event is logged with the following parameters
    //   buyer           is the buyer's address
    //   ethersSent      is the number of ethers sent by the buyer
    //   ethersReturned  is the number of ethers sent back to the buyer as
    //                   change
    //   tokensBought    is the number of asset tokens sent to the buyer
    //
    // This method was called buy() in the old version
    function takerBuyAsset() payable {
        if (sellsTokens || msg.sender == owner) {
            uint order    = msg.value / sellPrice;
            uint can_sell = ERC20Partial(asset).balanceOf(address(this)) / units;
            uint256 change = 0;
            if (order > can_sell) {
                change = msg.value - (can_sell * sellPrice);
                order = can_sell;
                if (!msg.sender.send(change)) throw;
            }
            if (order > 0) {
                if(!ERC20Partial(asset).transfer(msg.sender, order * units)) throw;
            }
            TakerBoughtAsset(msg.sender, msg.value, order * units, change);
        }
        // Return user funds if the contract is not selling
        else if (!msg.sender.send(msg.value)) throw;
    }

    // Taker buys tokens by sending ethers
    function () payable {
        takerBuyAsset();
    }
}

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

    event TradeListing(address indexed ownerAddress, address indexed tokenSellerAddress,
        address indexed asset, uint256 sellPrice, uint256 units, bool sellsTokens);
    event OwnerWithdrewERC20Token(address indexed tokenAddress, uint256 tokens);

    mapping(address => bool) _verify;

    // Anyone can call this method to verify the settings of a
    // TokenSeller contract. The parameters are:
    //   tradeContract  is the address of a TokenSeller contract
    //
    // Return values:
    //   valid        did this TokenTraderFactory create the TokenTrader contract?
    //   owner        is the owner of the TokenTrader contract
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenTrader contract selling tokens?
    //
    function verify(address tradeContract) constant returns (
        bool    valid,
        address owner,
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) {
        valid = _verify[tradeContract];
        if (valid) {
            TokenSeller t = TokenSeller(tradeContract);
            owner         = t.owner();
            asset         = t.asset();
            sellPrice     = t.sellPrice();
            units         = t.units();
            sellsTokens   = t.sellsTokens();
        }
    }

    // Maker can call this method to create a new TokenSeller contract
    // with the maker being the owner of this new contract
    //
    // Parameters:
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenSeller contract selling tokens?
    //
    // For example, listing a TokenSeller contract on the GNT Golem Network Token
    // where the contract will sell GNT tokens at a rate of 170/100000 = 0.0017 ETH
    // per GNT token:
    //   asset        0xa74476443119a942de498590fe1f2454d7d4ac0d
    //   sellPrice    170
    //   units        100000
    //   sellsTokens  true
    //
    // The TradeListing() event is logged with the following parameters
    //   ownerAddress        is the Maker's address
    //   tokenSellerAddress  is the address of the newly created TokenSeller contract
    //   asset               is the ERC20 asset address
    //   sellPrice           is the sell price in ethers per `units` of asset tokens
    //   unit                is the number of units of asset tokens
    //   sellsTokens         is the TokenSeller contract selling tokens?
    //
    // This method was called createTradeContract() in the old version
    //
    function createSaleContract(
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) returns (address seller) {
        // Cannot set zero or negative price
        if (sellPrice <= 0) throw;
        // Cannot sell zero or negative units
        if (units <= 0) throw;
        seller = new TokenSeller(
            asset,
            sellPrice,
            units,
            sellsTokens);
        // Record that this factory created the trader
        _verify[seller] = true;
        // Set the owner to whoever called the function
        TokenSeller(seller).transferOwnership(msg.sender);
        TradeListing(msg.sender, seller, asset, sellPrice, units, sellsTokens);
    }

    // Factory owner can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The OwnerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    function ownerWithdrawERC20Token(address tokenAddress, uint256 tokens) onlyOwner returns (bool ok) {
        OwnerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

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


Chore of batch tx

Chore of batch tx

pragma solidity ^0.4.24;

/// @title Batch tx
/// @author ["Cryptape Technologies <contact@cryptape.com>"]
/// @dev TODO use native contract
contract BatchTx {

    /// @notice Proxy multiple transactions
    ///         The encoded transactions data: tuple(address,dataLen,data)
    ///         dataLen: uint32
    ///         address: uint160
    ///         Example:
    ///             address: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ///             datalen: 00000004
    ///                data: xxxxxxxx
    function multiTxs(bytes)
        external
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            // Ignore the function sig: 0x4
            //        the offset of bytes: 0x20
            //        the len of bytes: 0x20
            let offset := 0x44
            for { } lt(offset, calldatasize) { } {
                // 0xc bytes forward from the offset(0x20-0x14)
                // Use `and` instruction just for safe
                let to := and(calldataload(sub(offset, 0xc)), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)
                // 0x8 bytes forward from the offset(0x20-0x14-0x4)
                let dataLen := and(calldataload(sub(offset, 0x8)), 0x00000000000000000000000000000000000000000000000000000000ffffffff)
                let ptr := mload(0x40)
                // Jump the address and dataLen(0x14+0x4)
                calldatacopy(ptr, add(offset, 0x18), dataLen)
                switch call(gas, to, 0, ptr, dataLen, ptr, 0)
                case 0 { revert(0, 0) }
                offset := add(add(offset, 0x18), dataLen)
            }
        }
    }
}

pragma solidity ^0.4.24;

/// @title Batch tx
/// @author ["Cryptape Technologies <contact@cryptape.com>"]
/// @dev TODO use native contract
contract BatchTx {

    /// @notice Proxy multiple transactions
    ///         The encoded transactions data: tuple(address,dataLen,data)
    ///         dataLen: uint32
    ///         address: uint160
    ///         Example:
    ///             address: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ///             datalen: 00000004
    ///                data: xxxxxxxx
    function multiTxs(bytes)
        external
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            // Ignore the function sig: 0x4
            //        the offset of bytes: 0x20
            //        the len of bytes: 0x20
            let offset := 0x44
            for { } lt(offset, calldatasize) { } {
                let to := and(calldataload(sub(offset, 0xc)), 0x00000000000000000000000fffffffffffffffffffffffffffffffffffffffff)
                let dataLen := and(calldataload(sub(offset, 0x8)), 0x00000000000000000000000000000000000000000000000000000000ffffffff)
                let ptr := mload(0x40)
                calldatacopy(ptr, add(offset, 0x18), dataLen)
                switch call(gas, to, 0, ptr, dataLen, ptr, 0)
                case 0 { revert(0, 0) }
                offset := add(add(offset, 0x18), dataLen)
            }
        }
    }
}


fixed issues with flipped variables

fixed issues with flipped variables

/*
    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;

/// @title Math function library with overflow protection inspired by Open Zeppelin
library MathLib {

    int256 constant INT256_MIN = int256((uint256(1) << 255));
    int256 constant INT256_MAX = int256(~((uint256(1) << 255)));

    function multiply(uint256 a, uint256 b) pure internal returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function subtract(uint256 a, uint256 b) pure internal returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) pure internal returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }

    /// @notice safely adds two signed integers ensuring that no wrap occurs
    /// @param a value to add b to
    /// @param b value to add to a
    function add(int256 a, int256 b) pure internal returns (int256) {
        int256 c = a + b;
        if(!isSameSign(a, b)) { // result will always be smaller than current value, no wrap possible
            return c;
        }

        if(a >= 0) { // a is positive, b must be less than MAX - a to prevent wrap
            assert(b <= INT256_MAX - a);
        } else { // a is negative, b must be greater than MIN - a to prevent wrap
            assert(b >= INT256_MIN - a);
        }
        return c;
    }

    /// @notice safely subtracts two signed integers ensuring that no wrap occurs
    /// @param a value to subtract b from
    /// @param b value to subtract from a
    function subtract(int256 a, int256 b) pure internal returns (int256) {
        return add(a, -b); // use inverse add
    }

    /// @param a integer to determine sign of
    /// @return int8 sign of original value, either +1,0,-1
    function sign(int a) pure internal returns (int8) {
        if(a > 0) {
            return 1;
        } else if (a < 0) {
            return -1;
        }
        return 0;
    }

    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return bool true if a and b are the same sign (+/-)
    function isSameSign(int a, int b) pure internal returns (bool) {
        return ( a == b || a * b > 0);
    }

    /// @param a integer to determine absolute value of
    /// @return uint non signed representation of a
    function abs(int256 a) pure internal returns (uint256) {
        if(a < 0) {
            return uint(-a);
        }
        else {
            return uint(a);
        }
    }

    /// @notice finds the value closer to zero regardless of sign
    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return a if a is closer to zero than b - does not return abs value!
    function absMin(int256 a, int256 b) pure internal returns (int256) {
        return abs(a) < abs(b) ?  a : b;
    }

    /// @notice finds the value further from zero regardless of sign
    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return a if a is further to zero than b - does not return abs value!
    function absMax(int256 a, int256 b) pure internal returns (int256) {
        return abs(a) >= abs(b) ?  a : b;
    }

    /// @notice determines the amount of needed collateral for a given position (qty and price)
    /// @param priceFloor lowest price the contract is allowed to trade before expiration
    /// @param priceCap highest price the contract is allowed to trade before expiration
    /// @param qtyDecimalPlaces number of decimal places in traded quantity.
    /// @param qty signed integer corresponding to the traded quantity
    /// @param price of the trade
    function calculateNeededCollateral(
        uint priceFloor,
        uint priceCap,
        uint qtyDecimalPlaces,
        int qty,
        uint price
    ) pure internal returns (uint neededCollateral) {

        uint maxLoss;
        if(qty > 0) {   // this qty is long, calculate max loss from entry price to floor
            if(price <= priceFloor) {
                maxLoss = 0;
            }
            else {
                maxLoss = subtract(price, priceFloor);
            }
        } else {        // this qty is short, calculate max loss from entry price to ceiling;
            if(price >= priceCap){
                maxLoss = 0;
            } else {
                maxLoss = subtract(priceCap, price);
            }
        }
        neededCollateral = maxLoss * abs(qty) * qtyDecimalPlaces;
    }
}

/*
    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;

/// @title Math function library with overflow protection inspired by Open Zeppelin
library MathLib {

    int256 constant INT256_MIN = int256((uint256(1) << 255));
    int256 constant INT256_MAX = int256(~((uint256(1) << 255)));

    function multiply(uint256 a, uint256 b) pure internal returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function subtract(uint256 a, uint256 b) pure internal returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) pure internal returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }

    /// @notice safely adds two signed integers ensuring that no wrap occurs
    /// @param a value to add b to
    /// @param b value to add to a
    function add(int256 a, int256 b) pure internal returns (int256) {
        int256 c = a + b;
        if(!isSameSign(a, b)) { // result will always be smaller than current value, no wrap possible
            return c;
        }

        if(a >= 0) { // a is positive, b must be less than MAX - a to prevent wrap
            assert(b <= INT256_MAX - a);
        } else { // a is negative, b must be greater than MIN - a to prevent wrap
            assert(b >= INT256_MIN - a);
        }
        return c;
    }

    /// @notice safely subtracts two signed integers ensuring that no wrap occurs
    /// @param a value to subtract b from
    /// @param b value to subtract from a
    function subtract(int256 a, int256 b) pure internal returns (int256) {
        return add(a, -b); // use inverse add
    }

    /// @param a integer to determine sign of
    /// @return int8 sign of original value, either +1,0,-1
    function sign(int a) pure internal returns (int8) {
        if(a > 0) {
            return 1;
        } else if (a < 0) {
            return -1;
        }
        return 0;
    }

    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return bool true if a and b are the same sign (+/-)
    function isSameSign(int a, int b) pure internal returns (bool) {
        return ( a == b || a * b > 0);
    }

    /// @param a integer to determine absolute value of
    /// @return uint non signed representation of a
    function abs(int256 a) pure internal returns (uint256) {
        if(a < 0) {
            return uint(-a);
        }
        else {
            return uint(a);
        }
    }

    /// @notice finds the value closer to zero regardless of sign
    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return a if a is closer to zero than b - does not return abs value!
    function absMin(int256 a, int256 b) pure internal returns (int256) {
        return abs(a) < abs(b) ?  a : b;
    }

    /// @notice finds the value further from zero regardless of sign
    /// @param a integer to compare to b
    /// @param b integer to compare to a
    /// @return a if a is further to zero than b - does not return abs value!
    function absMax(int256 a, int256 b) pure internal returns (int256) {
        return abs(a) >= abs(b) ?  a : b;
    }

    /// @notice determines the amount of needed collateral for a given position (qty and price)
    /// @param priceFloor lowest price the contract is allowed to trade before expiration
    /// @param priceCap highest price the contract is allowed to trade before expiration
    /// @param qtyDecimalPlaces number of decimal places in traded quantity.
    /// @param qty signed integer corresponding to the traded quantity
    /// @param price of the trade
    function calculateNeededCollateral(
        uint priceFloor,
        uint priceCap,
        uint qtyDecimalPlaces,
        int qty,
        uint price
    ) pure internal returns (uint neededCollateral) {

        uint maxLoss;
        if(qty > 0) {   // this qty is long, calculate max loss from entry price to floor
            if(price <= priceFloor) {
                maxLoss = 0;
            }
            else {
                maxLoss = subtract(price, priceFloor);
            }
        } else {        // this qty is short, calculate max loss from entry price to ceiling;
            if(price >= priceCap){
                maxLoss = 0;
            } else {
                maxLoss = subtract(price, priceCap);
            }
        }
        neededCollateral = maxLoss * abs(qty) * qtyDecimalPlaces;
    }
}


Dynamic Precision

Dynamic Precision

Change the PRECISION constant to a dynamic value, passed to the 'power' function (and all other functions in the calling tree).

Method:
- Given base and exponent, we need to calculate base^exponent.
- Instead, we calculate e^(ln(base)*exponent).
- The value of ln(base) is represented with an integer slightly smaller than ln(base)*2^PRECISION.
- The larger PRECISION is, the more accurately this value represents the real value.
- However, function fixedExpUnsafe(x), which calculates e^x, is limited to a maximum value of x.
- The limit depends PRECISION (e.g, for PRECISION=32, the maximum value of x is 0x386bfdba29).
- Hence before calling the 'power' function, we need to estimate an upper-bound for ln(base)*exponent.
- Dividing 0x386bfdba29 by this value will tell us what value we can set PRECISION to.
- Of course, this is slightly a 'chicken-egg' paradox, because 0x386bfdba29 corresponds with PRECISION = 32.
- Ideally, we would check each PRECISION using the corresponding limit
  (see https://github.com/bancorprotocol/contracts/blob/master/solidity/python/constants/PrintMaxExpPerPrecision.py).

Note: since we assert that x <= 0x386bfdba29 before calling fixedExpUnsafe, we cannot use a PRECISION lower than 32.

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

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

contract BancorFormula is IBancorFormula, SafeMath {

    uint256 constant MAX_FIXED_EXP_32 = 0x386bfdba29;
    string public version = '0.2';

    function BancorFormula() {
    }

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

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

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

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

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

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

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

        uint8 precision = getBestPrecision(baseN, _reserveBalance, _reserveRatio, 100)
        uint256 resN = power(baseN, _reserveBalance, _reserveRatio, 100, precision);

        temp = safeMul(_supply, resN) >> precision;

        return safeSub(temp, _supply);
     }

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

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

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

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

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

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

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

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

        uint8 precision = getBestPrecision(_supply, baseD, 100, _reserveRatio)
        uint256 resN = power(_supply, baseD, 100, _reserveRatio, precision);

        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, uint256(1) << precision);

        return safeSub(temp1, temp2) / resN;
    }

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

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

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

        This method asserts outside of bounds

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

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

        // Upper bits are scaled off by PRECISION
        uint256 MAX_VAL = uint256(1) << (256 - PRECISION);
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

        return fixedLoge( (_numerator << PRECISION) / _denominator, PRECISION);
    }

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

        This method asserts outside of bounds

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

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

        */
        //Cannot represent negative numbers (below 1)
        assert(_x >= uint256(1) << PRECISION);

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

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

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

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

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x, uint8 PRECISION) constant returns (uint256) {
        uint256 FIXED_ONE = uint256(1) << PRECISION;
        uint256 FIXED_TWO = uint256(2) << PRECISION;

        // Numbers below 1 are negative.
        assert( _x >= FIXED_ONE);

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

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

        return hi;
    }

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

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

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

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

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

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

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

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

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

    */
    function fixedExpUnsafe(uint256 _x, uint8 PRECISION) constant returns (uint256) {

        uint256 xi;
        uint256 res = 0xde1bc4d19efcac82445da75b00000000 << PRECISION;

        xi = (xi * _x) >> PRECISION;
        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x650139600;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x8c40;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x462;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }

    /**
        getBestPrecision
    */
    function getBestPrecision(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD) constant returns (uint8) {
        uint8 precision = floorLog2(MAX_FIXED_EXP_32*_expD/(lnUpperBound(_baseN,_baseD)*_expN));
        return precision >= 32 ? precision : 32;
    }

    /**
        lnUpperBound
    */
    function lnUpperBound(uint256 baseN, uint256 baseD) constant returns (uint8) {
        assert(baseN > baseD)
        if (100000*baseN <= 271828*baseD) // baseN/baseD < e^1
            return 1;
        if (100000*baseN <= 738905*baseD) // baseN/baseD < e^2
            return 2;
        if (baseN <= 8*baseD)             // baseN/baseD <= 2^3 < e^3
            return 3;
        return floorLog2(baseN/baseD);
    }

    /**
        floorLog2
    */
    function floorLog2(uint256 n) constant returns (uint8) {
        uint256 t = 0;
        for (int k = 7; k >= 0; k--) {
            if (n > (uint256(1)<<(1<<k))-1) {
                uint256 s = uint256(1) << k;
                n >>= s;
                t |= s;
            }
        }
        return uint8(t | (n >> 1));
    }
}

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

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

contract BancorFormula is IBancorFormula, SafeMath {

    uint8 constant PRECISION   = 32;  // fractional bits
    uint256 constant FIXED_ONE = uint256(1) << PRECISION; // 0x100000000
    uint256 constant FIXED_TWO = uint256(2) << PRECISION; // 0x200000000
    uint256 constant MAX_VAL   = uint256(1) << (256 - PRECISION); // 0x0000000100000000000000000000000000000000000000000000000000000000
    string public version = '0.2';

    function BancorFormula() {
    }

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

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

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

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

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

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

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

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

        temp = safeMul(_supply, resN) / FIXED_ONE;

        return safeSub(temp, _supply);
     }

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

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

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

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

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

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

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

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

        uint256 resN = power(_supply, baseD, 100, _reserveRatio);

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

        return safeSub(temp1, temp2) / resN;
    }

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

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

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

        This method asserts outside of bounds

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

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

        // Upper 32 bits are scaled off by PRECISION
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

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

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

        This method asserts outside of bounds

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

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

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

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

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

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

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

        This method asserts outside of bounds

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

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

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

        return hi;
    }

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

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

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

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

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

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

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

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

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

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

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

        xi = (xi * _x) >> PRECISION;
        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x650139600;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x8c40;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x462;
        xi = (xi * _x) >> PRECISION;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }
}


remove deprecated test

remove deprecated test

/*
    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 "truffle/Assert.sol";
import "../contracts/Linkable.sol";

contract TestLinkable {

    function testLinkableCreation() public {
        Linkable linkable = new Linkable(msg.sender);
        Assert.equal(
            msg.sender,
            linkable.linkedAddress(),
            "Linked address is as expected in constructor"
        );
    }
}


Fixed comment typo (#2372)

Fixed comment typo (#2372)

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./UpgradeableProxy.sol";

/**
 * @dev This contract implements a proxy that is upgradeable by an admin.
 *
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 *
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches one of the admin functions exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
 * "admin cannot fallback to proxy target".
 *
 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
 * to sudden errors when trying to call a function from the proxy implementation.
 *
 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
 * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
 */
contract TransparentUpgradeableProxy is UpgradeableProxy {
    /**
     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
     * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
     */
    constructor(address _logic, address _admin, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
        assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
        _setAdmin(_admin);
    }

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
     */
    modifier ifAdmin() {
        if (msg.sender == _admin()) {
            _;
        } else {
            _fallback();
        }
    }

    /**
     * @dev Returns the current admin.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function admin() external ifAdmin returns (address) {
        return _admin();
    }

    /**
     * @dev Returns the current implementation.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function implementation() external ifAdmin returns (address) {
        return _implementation();
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
     */
    function changeAdmin(address newAdmin) external ifAdmin {
        require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev Upgrade the implementation of the proxy.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
     */
    function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeTo(newImplementation);
    }

    /**
     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
     * proxied contract.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
     */
    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
        _upgradeTo(newImplementation);
        // solhint-disable-next-line avoid-low-level-calls
        (bool success,) = newImplementation.delegatecall(data);
        require(success);
    }

    /**
     * @dev Returns the current admin.
     */
    function _admin() internal view returns (address adm) {
        bytes32 slot = _ADMIN_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            adm := sload(slot)
        }
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        bytes32 slot = _ADMIN_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newAdmin)
        }
    }

    /**
     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
     */
    function _beforeFallback() internal override virtual {
        require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
        super._beforeFallback();
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./UpgradeableProxy.sol";

/**
 * @dev This contract implements a proxy that is upgradeable by an admin.
 *
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 *
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches one of the admin functions exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
 * "admin cannot fallback to proxy target".
 *
 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
 * to sudden errors when trying to call a function from the proxy implementation.
 *
 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
 * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.
 */
contract TransparentUpgradeableProxy is UpgradeableProxy {
    /**
     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
     * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
     */
    constructor(address _logic, address _admin, bytes memory _data) public payable UpgradeableProxy(_logic, _data) {
        assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
        _setAdmin(_admin);
    }

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
     */
    modifier ifAdmin() {
        if (msg.sender == _admin()) {
            _;
        } else {
            _fallback();
        }
    }

    /**
     * @dev Returns the current admin.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function admin() external ifAdmin returns (address) {
        return _admin();
    }

    /**
     * @dev Returns the current implementation.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function implementation() external ifAdmin returns (address) {
        return _implementation();
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
     */
    function changeAdmin(address newAdmin) external ifAdmin {
        require(newAdmin != address(0), "TransparentUpgradeableProxy: new admin is the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev Upgrade the implementation of the proxy.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
     */
    function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeTo(newImplementation);
    }

    /**
     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
     * proxied contract.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
     */
    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
        _upgradeTo(newImplementation);
        // solhint-disable-next-line avoid-low-level-calls
        (bool success,) = newImplementation.delegatecall(data);
        require(success);
    }

    /**
     * @dev Returns the current admin.
     */
    function _admin() internal view returns (address adm) {
        bytes32 slot = _ADMIN_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            adm := sload(slot)
        }
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        bytes32 slot = _ADMIN_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, newAdmin)
        }
    }

    /**
     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
     */
    function _beforeFallback() internal override virtual {
        require(msg.sender != _admin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
        super._beforeFallback();
    }
}


fixed resubmitting

fixed resubmitting

pragma solidity ^0.4.16;

import "./DepositsManager.sol";

interface InteractiveI {
    function make(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 par, uint to) public returns (bytes32);
    function makeFinality(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 _steps, uint to) public returns (bytes32);

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32);
    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool);
    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool);

    // Check if a task has been rejected
    function isRejected(uint id) public returns (bool);
    // Check if a task is blocked, returns the block when it can be accepted
    function blockedTime(uint id) public returns (uint);
    function getChallenger(bytes32 id) public returns (address);
    function getTask(bytes32 id) public view returns (uint);
    function deleteChallenge(bytes32 id) public;
}

interface Callback {
    function solved(uint id, bytes32[] files) public;
    function rejected(uint id) public;
}

interface FilesystemI {
  function getRoot(bytes32 id) public view returns (bytes32);
  function getNameHash(bytes32 id) public view returns (bytes32);
}

contract TasksResubmit is DepositsManager {

    uint constant DEPOSIT = 0.1 ether;
    uint constant DEPOSIT_PART = 0.01 ether;
    uint constant LIMIT = 20;

    enum CodeType {
        WAST,
        WASM,
        INTERNAL
    }

    enum Storage {
        IPFS,
        BLOCKCHAIN
    }

    event Posted(address giver, bytes32 hash, CodeType ct, Storage cs, string stor, uint id);
    event Solved(uint id, bytes32 hash, bytes32 init, CodeType ct, Storage cs, string stor, address solver);
    event Finalized(uint id);

    InteractiveI iactive;
    FilesystemI fs;

    function TasksResubmit(address contr, address fs_addr) public {
        iactive = InteractiveI(contr);
        fs = FilesystemI(fs_addr);
    }

    function getInteractive() public view returns (address) {
        return address(iactive);
    }

    struct RequiredFile {
       bytes32 name_hash;
       Storage file_storage;
       bytes32 file_id;
    }

    struct IO {
       bytes32 name;
       bytes32 size;
       bytes32 data;

       RequiredFile[] uploads;
    }

    struct VMParameters {
        uint8 stack_size;
        uint8 memory_size;
        uint8 call_size;
        uint8 globals_size;
        uint8 table_size;
    }

    struct Task2 {
        address solver;
        bytes32 result;

        bool good; // has the file been loaded
        uint blocked; // how long we have to wait to accept solution

        bytes32 challenge;
    }

    struct Task {
        address giver;
        bytes32 init; // includes code and input roots, the output should be similar
        string stor;

        CodeType code_type;
        Storage storage_type;

        uint state;
        uint task_id;
        uint deposit;
    }

    Task[] public tasks;
    Task2[] public tasks2;
    VMParameters[] params;
    IO[] io_roots;

    mapping (bytes32 => uint) challenges;

    function defaultParameters(uint id) internal {
        VMParameters storage param = params[id];
        param.stack_size = 14;
        param.memory_size = 16;
        param.globals_size = 8;
        param.table_size = 8;
        param.call_size = 10;
    }

    function add(bytes32 init, CodeType ct, Storage cs, string stor) public returns (uint) {
        uint id = tasks.length;
        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        t.giver = msg.sender;
        t.init = init;
        t.stor = stor;
        t2.good = true;
        t.code_type = ct;
        t.storage_type = cs;
        t.task_id = id;
        t.deposit = 1;

        defaultParameters(id);
        Posted(msg.sender, init, ct, cs, stor, id);
        return id;
    }

    function addWithParameters(bytes32 init, CodeType ct, Storage cs, string stor, uint8 stack, uint8 mem, uint8 globals, uint8 table, uint8 call) public returns (uint) {
        uint id = tasks.length;
        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        t.giver = msg.sender;
        t.init = init;
        t.stor = stor;
        t2.good = true;
        t.code_type = ct;
        t.storage_type = cs;
        t.task_id = id;
        t.deposit = 1;

        VMParameters storage param = params[id];
        param.stack_size = stack;
        param.memory_size = mem;
        param.globals_size = globals;
        param.table_size = table;
        param.call_size = call;
        Posted(msg.sender, init, ct, cs, stor, id);
        return id;
    }

    function resubmit(uint old_id) internal returns (uint) {
        uint id = tasks.length;
        Task storage t = tasks[old_id];

        if (t.deposit > LIMIT) {
            if (io_roots[old_id].uploads.length > 0) Callback(t.giver).rejected(t.task_id);
            return;
        }

        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;

        tasks[id] = tasks[old_id];
        tasks[id].deposit *= 2;
        tasks2[id] = tasks2[old_id];
        params[id] = params[old_id];
        io_roots[id] = io_roots[old_id];

        return id;
    }

    // Make sure they won't be required after the task has been posted already
    function requireFile(uint id, bytes32 hash, Storage st) public {
        IO storage io = io_roots[id];
        io.uploads.push(RequiredFile(hash, st, 0));
    }

    function getUploadNames(uint id) public view returns (bytes32[]) {
        RequiredFile[] storage lst = io_roots[id].uploads;
        bytes32[] memory arr = new bytes32[](lst.length);
        for (uint i = 0; i < arr.length; i++) arr[i] = lst[i].name_hash;
        return arr;

    }

    function getUploadTypes(uint id) public view returns (Storage[]) {
        RequiredFile[] storage lst = io_roots[id].uploads;
        Storage[] memory arr = new Storage[](lst.length);
        for (uint i = 0; i < arr.length; i++) arr[i] = lst[i].file_storage;
        return arr;
    }

    function taskInfo(uint unq) public view returns (address giver, bytes32 hash, CodeType ct, Storage cs, string stor, uint id) {
        Task storage t = tasks[unq];
        return (t.giver, t.init, t.code_type, t.storage_type, t.stor, unq);
    }

    function getVMParameters(uint id) public view returns (uint8 stack, uint8 mem, uint8 globals, uint8 table, uint8 call) {
        VMParameters storage param = params[id];
        stack = param.stack_size;
        mem = param.memory_size;
        globals = param.globals_size;
        table = param.table_size;
        call = param.call_size;
    }

    function nextTask() public view returns (uint) {
        return tasks.length;
    }

    function getSolver(uint id) public view returns (address) {
        return tasks2[id].solver;
    }

    function solveIO(uint id, bytes32 code, bytes32 size, bytes32 name, bytes32 data) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        IO storage io = io_roots[t.task_id];
        require(t2.solver == 0 && t2.good);

        io.size = size;
        io.name = name;
        io.data = data;
        t2.solver = msg.sender;
        t2.result = keccak256(code, size, name, data);
        t.state = 1;
        t2.blocked = block.number + 10;
        Solved(id, t2.result, t.init, t.code_type, t.storage_type, t.stor, t2.solver);
        subDeposit(msg.sender, DEPOSIT*t.deposit);
    }

    function solutionInfo(uint unq) public view returns (uint id, bytes32 hash, bytes32 init, CodeType ct, Storage cs, string stor, address solver) {
        Task storage t = tasks[unq];
        Task2 storage t2 = tasks2[unq];
        return (unq, t2.result, t.init, t.code_type, t.storage_type, t.stor, t2.solver);
    }

    /*
    function getCodeType(uint id) public view returns (CodeType) {
        return tasks[id].code_type;
    }

    function getCodeStorage(uint id) public view returns (Storage) {
        // return tasks[id].code_storage;
    }
    */

    function challenge(uint id) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        // VMParameters storage p = params[id];
        require(t.state == 1 && t2.challenge == 0);
        bytes32 uniq = iactive.make(id, t2.solver, msg.sender, t.init, t2.result, 1, 10);
        challenges[uniq] = id;
        t2.challenge = uniq;

        subDeposit(msg.sender, DEPOSIT*t.deposit);
        addDeposit(t.giver, DEPOSIT_PART*t.deposit); // rewarding task giver for delay
        addDeposit(t2.solver, DEPOSIT_PART*t.deposit);
        resubmit(id);
    }

    function challengeFinality(uint id) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        require(t.state == 1 && t2.challenge == 0);
        bytes32 uniq = iactive.makeFinality(id, t2.solver, msg.sender, t.init, t2.result, /* t2.steps */ 100, 10);
        challenges[uniq] = id;
        t2.challenge = uniq;

        subDeposit(msg.sender, DEPOSIT*t.deposit);
        addDeposit(t.giver, DEPOSIT_PART*t.deposit); // rewarding task giver for delay
        addDeposit(t2.solver, DEPOSIT_PART*t.deposit);
        resubmit(id);
    }

    function queryChallenge(bytes32 uniq) constant public returns (uint) {
        return challenges[uniq];
    }

    function getChallenges(uint id) public view returns (bytes32[]) {
        bytes32 chal = tasks2[id].challenge;
        bytes32[] memory res;
        if (chal == 0) {
            res = new bytes32[](0);
            return res;
        }
        res = new bytes32[](1);
        res[0] = chal;
        return res;
    }

    function uploadFile(uint id, uint num, bytes32 file_id, bytes32[] name_proof, bytes32[] data_proof, uint file_num) public returns (bool) {
        IO storage io = io_roots[id];
        RequiredFile storage file = io.uploads[num];
        if (!iactive.checkProof(fs.getRoot(file_id), io.data, data_proof, file_num) || !iactive.checkProof(fs.getNameHash(file_id), io.name, name_proof, file_num)) return false;
        require(iactive.checkProof(fs.getRoot(file_id), io.data, data_proof, file_num));
        require(iactive.checkProof(fs.getNameHash(file_id), io.name, name_proof, file_num));

        file.file_id = file_id;
        return true;
    }

    function finalizeTask(uint id) public returns (bool) {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        IO storage io = io_roots[id];
        if (!(t.state == 1 && t2.blocked < block.number && t2.challenge != 0)) return false;
        t.state = 3;

        bytes32[] memory files = new bytes32[](io.uploads.length);
        for (uint i = 0; i < io.uploads.length; i++) {
           if (!(io.uploads[i].file_id != 0)) return false;
           require(io.uploads[i].file_id != 0);
           files[i] = io.uploads[i].file_id;
        }

        if (files.length > 0) Callback(t.giver).solved(t.task_id, files);

        Finalized(id);
        addDeposit(t2.solver, DEPOSIT*t.deposit);

        return true;
    }

    function claimDeposit(bytes32 cid) public {
        uint id = iactive.getTask(cid);
        Task storage t = tasks[id];
        require(iactive.isRejected(id));
        require(iactive.getChallenger(cid) == msg.sender);
        iactive.deleteChallenge(cid);
        addDeposit(msg.sender, (DEPOSIT+DEPOSIT_PART*2)*t.deposit);
    }

    uint tick_var;

    // For testing, mine this to create new block
    function tick() public {
        tick_var++;
    }

}

pragma solidity ^0.4.16;

import "./DepositsManager.sol";

interface InteractiveI {
    function make(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 par, uint to) public returns (bytes32);
    function makeFinality(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 _steps, uint to) public returns (bytes32);

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32);
    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool);
    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool);

    // Check if a task has been rejected
    function isRejected(uint id) public returns (bool);
    // Check if a task is blocked, returns the block when it can be accepted
    function blockedTime(uint id) public returns (uint);
    function getChallenger(bytes32 id) public returns (address);
    function getTask(bytes32 id) public view returns (uint);
    function deleteChallenge(bytes32 id) public;
}

interface Callback {
    function solved(uint id, bytes32[] files) public;
    function rejected(uint id) public;
}

interface FilesystemI {
  function getRoot(bytes32 id) public view returns (bytes32);
  function getNameHash(bytes32 id) public view returns (bytes32);
}

contract TasksResubmit is DepositsManager {

    uint constant DEPOSIT = 0.1 ether;
    uint constant DEPOSIT_PART = 0.01 ether;
    uint constant LIMIT = 20;

    enum CodeType {
        WAST,
        WASM,
        INTERNAL
    }

    enum Storage {
        IPFS,
        BLOCKCHAIN
    }

    event Posted(address giver, bytes32 hash, CodeType ct, Storage cs, string stor, uint id);
    event Solved(uint id, bytes32 hash, bytes32 init, CodeType ct, Storage cs, string stor, address solver);
    event Finalized(uint id);

    InteractiveI iactive;
    FilesystemI fs;

    function TasksResubmit(address contr, address fs_addr) public {
        iactive = InteractiveI(contr);
        fs = FilesystemI(fs_addr);
    }

    function getInteractive() public view returns (address) {
        return address(iactive);
    }

    struct RequiredFile {
       bytes32 name_hash;
       Storage file_storage;
       bytes32 file_id;
    }

    struct IO {
       bytes32 name;
       bytes32 size;
       bytes32 data;

       RequiredFile[] uploads;
    }

    struct VMParameters {
        uint8 stack_size;
        uint8 memory_size;
        uint8 call_size;
        uint8 globals_size;
        uint8 table_size;
    }

    struct Task2 {
        address solver;
        bytes32 result;

        bool good; // has the file been loaded
        uint blocked; // how long we have to wait to accept solution

        bytes32 challenge;
    }

    struct Task {
        address giver;
        bytes32 init; // includes code and input roots, the output should be similar
        string stor;

        CodeType code_type;
        Storage storage_type;

        uint state;
        uint task_id;
        uint deposit;
    }

    Task[] public tasks;
    Task2[] public tasks2;
    VMParameters[] params;
    IO[] io_roots;

    mapping (bytes32 => uint) challenges;

    function defaultParameters(uint id) internal {
        VMParameters storage param = params[id];
        param.stack_size = 14;
        param.memory_size = 16;
        param.globals_size = 8;
        param.table_size = 8;
        param.call_size = 10;
    }

    function add(bytes32 init, CodeType ct, Storage cs, string stor) public returns (uint) {
        uint id = tasks.length;
        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        t.giver = msg.sender;
        t.init = init;
        t.stor = stor;
        t2.good = true;
        t.code_type = ct;
        t.storage_type = cs;
        t.task_id = id;
        t.deposit = 1;

        defaultParameters(id);
        Posted(msg.sender, init, ct, cs, stor, id);
        return id;
    }

    function addWithParameters(bytes32 init, CodeType ct, Storage cs, string stor, uint8 stack, uint8 mem, uint8 globals, uint8 table, uint8 call) public returns (uint) {
        uint id = tasks.length;
        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        t.giver = msg.sender;
        t.init = init;
        t.stor = stor;
        t2.good = true;
        t.code_type = ct;
        t.storage_type = cs;
        t.task_id = id;
        t.deposit = 1;

        VMParameters storage param = params[id];
        param.stack_size = stack;
        param.memory_size = mem;
        param.globals_size = globals;
        param.table_size = table;
        param.call_size = call;
        Posted(msg.sender, init, ct, cs, stor, id);
        return id;
    }

    function resubmit(uint old_id) internal returns (uint) {
        uint id = tasks.length;
        Task storage t = tasks[old_id];

        if (t.deposit > LIMIT) {
            if (io_roots[old_id].uploads.length > 0) Callback(t.giver).rejected(t.task_id);
            return;
        }

        tasks.length++;
        tasks2.length++;
        params.length++;
        io_roots.length++;

        tasks[id] = tasks[old_id];
        tasks[id].deposit *= 2;
        tasks2[id] = tasks2[old_id];
        params[id] = params[old_id];
        io_roots[id] = io_roots[old_id];

        return id;
    }

    // Make sure they won't be required after the task has been posted already
    function requireFile(uint id, bytes32 hash, Storage st) public {
        IO storage io = io_roots[id];
        io.uploads.push(RequiredFile(hash, st, 0));
    }

    function getUploadNames(uint id) public view returns (bytes32[]) {
        RequiredFile[] storage lst = io_roots[id].uploads;
        bytes32[] memory arr = new bytes32[](lst.length);
        for (uint i = 0; i < arr.length; i++) arr[i] = lst[i].name_hash;
        return arr;

    }

    function getUploadTypes(uint id) public view returns (Storage[]) {
        RequiredFile[] storage lst = io_roots[id].uploads;
        Storage[] memory arr = new Storage[](lst.length);
        for (uint i = 0; i < arr.length; i++) arr[i] = lst[i].file_storage;
        return arr;
    }

    function taskInfo(uint unq) public view returns (address giver, bytes32 hash, CodeType ct, Storage cs, string stor, uint id) {
        Task storage t = tasks[unq];
        return (t.giver, t.init, t.code_type, t.storage_type, t.stor, unq);
    }

    function getVMParameters(uint id) public view returns (uint8 stack, uint8 mem, uint8 globals, uint8 table, uint8 call) {
        VMParameters storage param = params[id];
        stack = param.stack_size;
        mem = param.memory_size;
        globals = param.globals_size;
        table = param.table_size;
        call = param.call_size;
    }

    function nextTask() public view returns (uint) {
        return tasks.length;
    }

    function getSolver(uint id) public view returns (address) {
        return tasks2[id].solver;
    }

    function solveIO(uint id, bytes32 code, bytes32 size, bytes32 name, bytes32 data) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        IO storage io = io_roots[t.task_id];
        require(t2.solver == 0 && t2.good);

        io.size = size;
        io.name = name;
        io.data = data;
        t2.solver = msg.sender;
        t2.result = keccak256(code, size, name, data);
        t.state = 1;
        t2.blocked = block.number + 10;
        Solved(id, t2.result, t.init, t.code_type, t.storage_type, t.stor, t2.solver);
        subDeposit(msg.sender, DEPOSIT*t.deposit);
    }

    function solutionInfo(uint unq) public view returns (uint id, bytes32 hash, bytes32 init, CodeType ct, Storage cs, string stor, address solver) {
        Task storage t = tasks[unq];
        Task2 storage t2 = tasks2[unq];
        return (unq, t2.result, t.init, t.code_type, t.storage_type, t.stor, t2.solver);
    }

    /*
    function getCodeType(uint id) public view returns (CodeType) {
        return tasks[id].code_type;
    }

    function getCodeStorage(uint id) public view returns (Storage) {
        // return tasks[id].code_storage;
    }
    */

    function challenge(uint id) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        // VMParameters storage p = params[id];
        require(t.state == 1 && t2.challenge == 0);
        bytes32 uniq = iactive.make(id, t2.solver, msg.sender, t.init, t2.result, 1, 10);
        challenges[uniq] = id;
        t2.challenge = uniq;

        subDeposit(msg.sender, DEPOSIT*t.deposit);
        addDeposit(t.giver, DEPOSIT_PART*t.deposit); // rewarding task giver for delay
        addDeposit(t2.solver, DEPOSIT_PART*t.deposit);
        resubmit(id);
    }

    function challengeFinality(uint id) public {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        require(t.state == 1 && t2.challenge == 0);
        bytes32 uniq = iactive.makeFinality(id, t2.solver, msg.sender, t.init, t2.result, /* t2.steps */ 100, 10);
        challenges[uniq] = id;
        t2.challenge = uniq;

        subDeposit(msg.sender, DEPOSIT*t.deposit);
        addDeposit(t.giver, DEPOSIT_PART*t.deposit); // rewarding task giver for delay
        addDeposit(t2.solver, DEPOSIT_PART*t.deposit);
        resubmit(id);
    }

    function queryChallenge(bytes32 uniq) constant public returns (uint) {
        return challenges[uniq];
    }

    function getChallenges(uint id) public view returns (bytes32[]) {
        bytes32 chal = tasks2[id].challenge;
        bytes32[] memory res;
        if (chal == 0) {
            res = new bytes32[](0);
            return res;
        }
        res = new bytes32[](1);
        res[0] = chal;
        return res;
    }

    function uploadFile(uint id, uint num, bytes32 file_id, bytes32[] name_proof, bytes32[] data_proof, uint file_num) public returns (bool) {
        IO storage io = io_roots[id];
        RequiredFile storage file = io.uploads[num];
        if (!iactive.checkProof(fs.getRoot(file_id), io.data, data_proof, file_num) || !iactive.checkProof(fs.getNameHash(file_id), io.name, name_proof, file_num)) return false;
        require(iactive.checkProof(fs.getRoot(file_id), io.data, data_proof, file_num));
        require(iactive.checkProof(fs.getNameHash(file_id), io.name, name_proof, file_num));

        file.file_id = file_id;
        return true;
    }

    function finalizeTask(uint id) public returns (bool) {
        Task storage t = tasks[id];
        Task2 storage t2 = tasks2[id];
        IO storage io = io_roots[id];
        if (!(t.state == 1 && t2.blocked < block.number && t2.challenge != 0)) return false;
        t.state = 3;

        bytes32[] memory files = new bytes32[](io.uploads.length);
        for (uint i = 0; i < io.uploads.length; i++) {
           if (!(io.uploads[i].file_id != 0)) return false;
           require(io.uploads[i].file_id != 0);
           files[i] = io.uploads[i].file_id;
        }

        if (files.length > 0) Callback(t.giver).solved(t.task_id, files);

        Finalized(id);
        addDeposit(t2.solver, DEPOSIT*t.deposit);

        return true;
    }

    function claimDeposit(bytes32 cid) public {
        uint id = iactive.getTask(cid);
        Task storage t = tasks[id];
        require(iactive.isRejected(id));
        require(iactive.getChallenger(cid) == msg.sender);
        iactive.deleteChallenge(cid);
        addDeposit(msg.sender, (DEPOSIT+DEPOSIT_PART)*t.deposit);
    }

    uint tick_var;

    // For testing, mine this to create new block
    function tick() public {
        tick_var++;
    }

}


protect from sending ether to the contract

contract BasicSign {

    event Created(
        address indexed from,
        uint256 id
    );
    event Signed(
        address indexed from,
        uint256 docId,
        uint8 singId,
        bytes16 signType,
        bytes sign
    );

    address owner;
    mapping (uint256 => Document) public documents;

    struct Document {
        address organizer;
        Sign[] signs;
    }

    struct Sign {
        address signer;
        bytes16 signType;
        bytes   sign;
    }

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

    function createDocument(uint256 nonce) returns (uint256 docId) {
        docId = generateId(nonce);
        if (documents[docId].organizer != 0) throw;
        documents[docId].organizer = msg.sender;
        Created(msg.sender, docId);
    }

    function removeDocument(uint256 docId) {
        Document doc = documents[docId];
        if (doc.organizer != msg.sender) throw;
        delete documents[docId];
    }

    function addSignature(uint256 docId, bytes16 _type, bytes _sign) {
        Document doc = documents[docId];
        if (doc.organizer != msg.sender) throw;
        if (doc.signs.length >= 0xFF) throw;
        uint idx = doc.signs.push(Sign(msg.sender, _type, _sign));
        Signed(msg.sender, docId, uint8(idx), _type, _sign);
    }

    function getDocumentDetails(uint256 docId) returns (address organizer, uint count) {
        Document doc = documents[docId];
        organizer = doc.organizer;
        count = doc.signs.length;
    }

    function getSignsCount(uint256 docId) returns (uint) {
        return documents[docId].signs.length;
    }

    function getSignDetails(uint256 docId, uint8 signId) returns (address, bytes16) {
        Document doc = documents[docId];
        Sign s = doc.signs[signId];
        return (s.signer, s.signType);
    }

    function getSignData(uint256 docId, uint8 signId) returns (bytes) {
        Document doc = documents[docId];
        Sign s = doc.signs[signId];
        return s.sign;
    }

    function generateId(uint256 nonce) returns (uint256) {
        return uint256(sha3(msg.sender, nonce));
    }

    function () {
        throw;
    }

}

contract BasicSign {

    event Created(
        address indexed from,
        uint256 id
    );
    event Signed(
        address indexed from,
        uint256 docId,
        uint8 singId,
        bytes16 signType,
        bytes sign
    );

    address owner;
    mapping (uint256 => Document) public documents;

    struct Document {
        address organizer;
        Sign[] signs;
    }

    struct Sign {
        address signer;
        bytes16 signType;
        bytes   sign;
    }

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

    function createDocument(uint256 nonce) returns (uint256 docId) {
        docId = generateId(nonce);
        if (documents[docId].organizer != 0) throw;
        documents[docId].organizer = msg.sender;
        Created(msg.sender, docId);
    }

    function removeDocument(uint256 docId) {
        Document doc = documents[docId];
        if (doc.organizer != msg.sender) throw;
        delete documents[docId];
    }

    function addSignature(uint256 docId, bytes16 _type, bytes _sign) {
        Document doc = documents[docId];
        if (doc.organizer != msg.sender) throw;
        if (doc.signs.length >= 0xFF) throw;
        uint idx = doc.signs.push(Sign(msg.sender, _type, _sign));
        Signed(msg.sender, docId, uint8(idx), _type, _sign);
    }

    function getDocumentDetails(uint256 docId) returns (address organizer, uint count) {
        Document doc = documents[docId];
        organizer = doc.organizer;
        count = doc.signs.length;
    }

    function getSignsCount(uint256 docId) returns (uint) {
        return documents[docId].signs.length;
    }

    function getSignDetails(uint256 docId, uint8 signId) returns (address, bytes16) {
        Document doc = documents[docId];
        Sign s = doc.signs[signId];
        return (s.signer, s.signType);
    }

    function getSignData(uint256 docId, uint8 signId) returns (bytes) {
        Document doc = documents[docId];
        Sign s = doc.signs[signId];
        return s.sign;
    }

    function generateId(uint256 nonce) returns (uint256) {
        return uint256(sha3(msg.sender, nonce));
    }

}