Mitigate short address attacks + race conditions

pragma solidity ^0.4.11;

contract Token {
    uint256 public totalSupply;
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract StandardToken is Token {
    modifier onlyPayloadSize(uint numwords) {
        assert(msg.data.length == numwords * 32 + 4);
        _;
    }

    function transfer(address _to, uint256 _value) onlyPayloadSize(2) returns (bool success) {
        if (balances[msg.sender] >= _value && _value > 0) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            Transfer(msg.sender, _to, _value);
            return true;
        } else {
            return false;
        }
    }

    function transferFrom(address _from, address _to, uint256 _value) onlyPayloadSize(3) returns (bool success) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
            Transfer(_from, _to, _value);
            return true;
        } else {
            return false;
        }
    }

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

    function approve(address _spender, uint256 _value) onlyPayloadSize(2) returns (bool success) {
        require(_value == 0 || allowed[msg.sender][_spender] == 0);

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

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

    mapping (address => uint256) balances;

    mapping (address => mapping (address => uint256)) allowed;
}

contract SolarEclipseToken is StandardToken {
    uint8 public decimals = 18;
    string public name = 'Solar Eclipse Token';
    address owner;
    string public symbol = 'SET';

    uint startTime = 1503330410; // Aug 21, 2017 at 15:46:50 UTC
    uint endTime = 1503349461; // Aug 21, 2017 at 21:04:21 UTC

    uint metersInAstronomicalUnit = 149597870700;
    uint milesInAstronomicalUnit = 92955807;
    uint speedOfLightInMetersPerSecond = 299792458;

    uint public totalSupplyCap = metersInAstronomicalUnit * 1 ether;
    uint public tokensPerETH = milesInAstronomicalUnit;

    uint public ownerTokens = speedOfLightInMetersPerSecond * 10 ether;

    function ownerWithdraw() {
        if (msg.sender != owner) revert(); // revert if not owner

        owner.transfer(this.balance); // send contract balance to owner
    }

    function () payable {
        if (now < startTime) revert(); // revert if solar eclipse has not started
        if (now > endTime) revert(); // revert if solar eclipse has ended
        if (totalSupply >= totalSupplyCap) revert(); // revert if totalSupplyCap has been exhausted

        uint tokensIssued = msg.value * tokensPerETH;

        if (totalSupply + tokensIssued > totalSupplyCap) {
            tokensIssued = totalSupplyCap - totalSupply; // ensure supply is capped
        }

        totalSupply += tokensIssued;
        balances[msg.sender] += tokensIssued; // transfer tokens to contributor
    }

    function SolarEclipseToken() {
        owner = msg.sender;
        totalSupply = ownerTokens;
        balances[owner] = ownerTokens;
    }
}

pragma solidity ^0.4.11;

contract Token {
    uint256 public totalSupply;
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract StandardToken is Token {
    function transfer(address _to, uint256 _value) returns (bool success) {
        if (balances[msg.sender] >= _value && _value > 0) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            Transfer(msg.sender, _to, _value);
            return true;
        } else {
            return false;
        }
    }

    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
            Transfer(_from, _to, _value);
            return true;
        } else {
            return false;
        }
    }

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

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

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

    mapping (address => uint256) balances;

    mapping (address => mapping (address => uint256)) allowed;
}

contract SolarEclipseToken is StandardToken {
    uint8 public decimals = 18;
    string public name = 'Solar Eclipse Token';
    address owner;
    string public symbol = 'SET';

    uint startTime = 1503330410; // Aug 21, 2017 at 15:46:50 UTC
    uint endTime = 1503349461; // Aug 21, 2017 at 21:04:21 UTC

    uint metersInAstronomicalUnit = 149597870700;
    uint milesInAstronomicalUnit = 92955807;
    uint speedOfLightInMetersPerSecond = 299792458;

    uint public totalSupplyCap = metersInAstronomicalUnit * 1 ether;
    uint public tokensPerETH = milesInAstronomicalUnit;

    uint public ownerTokens = speedOfLightInMetersPerSecond * 10 ether;

    function ownerWithdraw() {
        if (msg.sender != owner) revert(); // revert if not owner

        owner.transfer(this.balance); // send contract balance to owner
    }

    function () payable {
        if (now < startTime) revert(); // revert if solar eclipse has not started
        if (now > endTime) revert(); // revert if solar eclipse has ended
        if (totalSupply >= totalSupplyCap) revert(); // revert if totalSupplyCap has been exhausted

        uint tokensIssued = msg.value * tokensPerETH;

        if (totalSupply + tokensIssued > totalSupplyCap) {
            tokensIssued = totalSupplyCap - totalSupply; // ensure supply is capped
        }

        totalSupply += tokensIssued;
        balances[msg.sender] += tokensIssued; // transfer tokens to contributor
    }

    function SolarEclipseToken() {
        owner = msg.sender;
        totalSupply = ownerTokens;
        balances[owner] = ownerTokens;
    }
}


Update ERC20.sol (#1313)

Update ERC20.sol (#1313)

correct typo in doc

pragma solidity ^0.4.24;

import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract ERC20 is IERC20 {
  using SafeMath for uint256;

  mapping (address => uint256) private _balances;

  mapping (address => mapping (address => uint256)) private _allowed;

  uint256 private _totalSupply;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param owner The address to query the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address owner) public view returns (uint256) {
    return _balances[owner];
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param owner address The address which owns the funds.
   * @param spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address owner,
    address spender
   )
    public
    view
    returns (uint256)
  {
    return _allowed[owner][spender];
  }

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    require(value <= _balances[msg.sender]);
    require(to != address(0));

    _balances[msg.sender] = _balances[msg.sender].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(msg.sender, to, value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param spender The address which will spend the funds.
   * @param value The amount of tokens to be spent.
   */
  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));

    _allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    public
    returns (bool)
  {
    require(value <= _balances[from]);
    require(value <= _allowed[from][msg.sender]);
    require(to != address(0));

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    emit Transfer(from, to, value);
    return true;
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(
    address spender,
    uint256 addedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].add(addedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(
    address spender,
    uint256 subtractedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].sub(subtractedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Internal function that mints an amount of the token and assigns it to
   * an account. This encapsulates the modification of balances such that the
   * proper events are emitted.
   * @param account The account that will receive the created tokens.
   * @param amount The amount that will be created.
   */
  function _mint(address account, uint256 amount) internal {
    require(account != 0);
    _totalSupply = _totalSupply.add(amount);
    _balances[account] = _balances[account].add(amount);
    emit Transfer(address(0), account, amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burn(address account, uint256 amount) internal {
    require(account != 0);
    require(amount <= _balances[account]);

    _totalSupply = _totalSupply.sub(amount);
    _balances[account] = _balances[account].sub(amount);
    emit Transfer(account, address(0), amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account, deducting from the sender's allowance for said account. Uses the
   * internal burn function.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burnFrom(address account, uint256 amount) internal {
    require(amount <= _allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
      amount);
    _burn(account, amount);
  }
}

pragma solidity ^0.4.24;

import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract ERC20 is IERC20 {
  using SafeMath for uint256;

  mapping (address => uint256) private _balances;

  mapping (address => mapping (address => uint256)) private _allowed;

  uint256 private _totalSupply;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param owner The address to query the the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address owner) public view returns (uint256) {
    return _balances[owner];
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param owner address The address which owns the funds.
   * @param spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address owner,
    address spender
   )
    public
    view
    returns (uint256)
  {
    return _allowed[owner][spender];
  }

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    require(value <= _balances[msg.sender]);
    require(to != address(0));

    _balances[msg.sender] = _balances[msg.sender].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(msg.sender, to, value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param spender The address which will spend the funds.
   * @param value The amount of tokens to be spent.
   */
  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));

    _allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    public
    returns (bool)
  {
    require(value <= _balances[from]);
    require(value <= _allowed[from][msg.sender]);
    require(to != address(0));

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    emit Transfer(from, to, value);
    return true;
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(
    address spender,
    uint256 addedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].add(addedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(
    address spender,
    uint256 subtractedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].sub(subtractedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Internal function that mints an amount of the token and assigns it to
   * an account. This encapsulates the modification of balances such that the
   * proper events are emitted.
   * @param account The account that will receive the created tokens.
   * @param amount The amount that will be created.
   */
  function _mint(address account, uint256 amount) internal {
    require(account != 0);
    _totalSupply = _totalSupply.add(amount);
    _balances[account] = _balances[account].add(amount);
    emit Transfer(address(0), account, amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burn(address account, uint256 amount) internal {
    require(account != 0);
    require(amount <= _balances[account]);

    _totalSupply = _totalSupply.sub(amount);
    _balances[account] = _balances[account].sub(amount);
    emit Transfer(account, address(0), amount);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account, deducting from the sender's allowance for said account. Uses the
   * internal burn function.
   * @param account The account whose tokens will be burnt.
   * @param amount The amount that will be burnt.
   */
  function _burnFrom(address account, uint256 amount) internal {
    require(amount <= _allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
      amount);
    _burn(account, amount);
  }
}


Fix signature of `getElement` to make it public


Minor fix in documentation

Minor fix in documentation

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
    - Improve dynamic precision support
*/

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.
        The maximum value which can be passed to fixedExpUnsafe depends on the precision used.
        The following array maps each precision between 0 and 63 to the maximum value permitted:
        maxExpArray = {
            0xc1               ,0x17a              ,0x2e5              ,0x5ab              ,
            0xb1b              ,0x15bf             ,0x2a0c             ,0x50a2             ,
            0x9aa2             ,0x1288c            ,0x238b2            ,0x4429a            ,
            0x82b78            ,0xfaadc            ,0x1e0bb8           ,0x399e96           ,
            0x6e7f88           ,0xd3e7a3           ,0x1965fea          ,0x30b5057          ,
            0x5d681f3          ,0xb320d03          ,0x15784a40         ,0x292c5bdd         ,
            0x4ef57b9b         ,0x976bd995         ,0x122624e32        ,0x22ce03cd5        ,
            0x42beef808        ,0x7ffffffff        ,0xf577eded5        ,0x1d6bd8b2eb       ,
            0x386bfdba29       ,0x6c3390ecc8       ,0xcf8014760f       ,0x18ded91f0e7      ,
            0x2fb1d8fe082      ,0x5b771955b36      ,0xaf67a93bb50      ,0x15060c256cb2     ,
            0x285145f31ae5     ,0x4d5156639708     ,0x944620b0e70e     ,0x11c592761c666    ,
            0x2214d10d014ea    ,0x415bc6d6fb7dd    ,0x7d56e76777fc5    ,0xf05dc6b27edad    ,
            0x1ccf4b44bb4820   ,0x373fc456c53bb7   ,0x69f3d1c921891c   ,0xcb2ff529eb71e4   ,
            0x185a82b87b72e95  ,0x2eb40f9f620fda6  ,0x5990681d961a1ea  ,0xabc25204e02828d  ,
            0x14962dee9dc97640 ,0x277abdcdab07d5a7 ,0x4bb5ecca963d54ab ,0x9131271922eaa606 ,
            0x116701e6ab0cd188d,0x215f77c045fbe8856,0x3ffffffffffffffff,0x7abbf6f6abb9d087f,
        };
        Since we cannot use an array of constants, we need to approximate the maximum value dynamically.
        The precision may be a value between 32 and 64, in multiples of 2 (i.e., 32, 34, 36, ..., 64).
        For the minimum precision of 32, the maximum value is MAX_FIXED_EXP_32.
        For each additional precision unit, the maximum value permitted increases by approximately 1.9.
        So in order to calculate it, we should multiply MAX_FIXED_EXP_32 by 1.9 ^ ((precision - 32) / 2).
        Since we cannot use non-integers, we multiply by 19 ^ ((precision - 32) / 2) and divide by 10 ^ ((precision - 32) / 2).
        But there is a better approximation, since this "1.9" factor in fact extends beyond a single decimal digit.
        So instead, we use 367765941410234761 / 100000000000000000, which yields maximum values quite close to real ones:
        maxExpArray = {
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            0x386bfdba29       ,-------------------,0xcf8014760e       ,-------------------,
            0x2fb1d8fe07b      ,-------------------,0xaf67a93bb37      ,-------------------,
            0x285145f31a8f     ,-------------------,0x944620b0e5ee     ,-------------------,
            0x2214d10d0112e    ,-------------------,0x7d56e7677738e    ,-------------------,
            0x1ccf4b44bb20d0   ,-------------------,0x69f3d1c9210d27   ,-------------------,
            0x185a82b87b5b294  ,-------------------,0x5990681d95d4371  ,-------------------,
            0x14962dee9dbd672a ,-------------------,0x4bb5ecca961fb9b8 ,-------------------,
            0x116701e6ab096705a,-------------------,0x3fffffffffffe6599,-------------------,
        };
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = maxExp * 367765941410234761 / 100000000000000000;

        assert(_x <= maxExp);
        return fixedExpUnsafe(_x, _precision);
    }

    /**
        fixedExpUnsafe
        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 fixedExpUnsafe"""

            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 = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _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
        Predicts the highest precision which can be used in order to compute "base^exp" without exceeding 256 bits in any of the intermediate computations.
        Instead of calculating "base^exp", we calculate "e^(ln(base)*exp)".
        The value of ln(base) is represented with an integer slightly smaller than ln(base)*2^precision.
        The larger the 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 on the precision (e.g, for precision=32, the maximum value of x is MAX_FIXED_EXP_32).
        Hence before calling the 'power' function, we need to estimate an upper-bound for ln(base)*exponent.
        Dividing MAX_FIXED_EXP_32 by this value will indicate the highest precision which can be used.
        Of course, this is slightly a 'chicken-egg' paradox, because MAX_FIXED_EXP_32 corresponds with a precision of 32 to begin with.
        For example, if we deduce that the highest precision which can be used is 33, then we should have actually used "MAX_FIXED_EXP_33" in order to deduce that.
        However, the value of MAX_FIXED_EXP(precision) is appriximately 2 times larger than the value of MAX_FIXED_EXP(precision-1).
        Hence if we deduce that the highest precision which can be used is 33, then we can in fact most likely use a precision of 34.
        So instead of returning 'precision', we return 'precision * 2 - 32'.
        Of course, we should later assert that the value passed to fixedExpUnsafe is not larger than MAX_FIXED_EXP(precision).
        Due to this assertion (made in function fixedExp before calling function fixedExpUnsafe), the precision must be a value between 32 and 64.
        In addition, since the value of 'precision * 2 - 32' is even, we can calculate MAX_FIXED_EXP(precision) within half as many iterations.
        Hence both functions (getBestPrecision and fixedExp) are tightly coupled.
        Note that the outcome of this function only affects the accuracy of the computation of "base^exp".
        Therefore, there is no need to assert that no intermediate result exceeds 256 bits (nor in this function, neither in any of the functions down the calling tree).
    */
    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));
        if (precision <= 32)
            return 32;
        if (precision >= 48)
            return 64;
        return precision * 2 - 32;
    }

    /**
        lnUpperBound
        Takes a rational number (baseN / baseD) as input.
        Returns an estimated upper-bound integer of the natural logarithm of the input.
        We can generally use floorLog2, although there is possibly a tighter bound.
        We cannot use floorLog2 when the input is smaller than 8.
        Complexity is O(log(input)).
    */
    function lnUpperBound(uint256 baseN, uint256 baseD) constant returns (uint8) {
        assert(baseN > baseD);

        uint256 scaledBaseN = baseN * 100000;
        if (scaledBaseN <= baseD *  271828) // baseN / baseD < e^1 (floorLog2 will return 0 if baseN / baseD < 2)
            return 1;
        if (scaledBaseN <= baseD *  738905) // baseN / baseD < e^2 (floorLog2 will return 1 if baseN / baseD < 4)
            return 2;
        if (scaledBaseN <= baseD * 2008553) // baseN / baseD < e^3 (floorLog2 will return 2 if baseN / baseD < 8)
            return 3;

        return floorLog2(baseN/baseD);
    }

    /**
        floorLog2
        Takes a natural number (n) as input.
        Returns the largest integer smaller than or equal to the binary logarithm of the input.
        Complexity is O(log(input)).
    */
    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
    - Improve dynamic precision support
*/

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.
        The maximum value which can be passed to fixedExpUnsafe depends on the precision used.
        The following array maps each precision between 0 and 63 to the maximum value permitted:
        maxExpArray = {
            0xc1               ,0x17a              ,0x2e5              ,0x5ab              ,
            0xb1b              ,0x15bf             ,0x2a0c             ,0x50a2             ,
            0x9aa2             ,0x1288c            ,0x238b2            ,0x4429a            ,
            0x82b78            ,0xfaadc            ,0x1e0bb8           ,0x399e96           ,
            0x6e7f88           ,0xd3e7a3           ,0x1965fea          ,0x30b5057          ,
            0x5d681f3          ,0xb320d03          ,0x15784a40         ,0x292c5bdd         ,
            0x4ef57b9b         ,0x976bd995         ,0x122624e32        ,0x22ce03cd5        ,
            0x42beef808        ,0x7ffffffff        ,0xf577eded5        ,0x1d6bd8b2eb       ,
            0x386bfdba29       ,0x6c3390ecc8       ,0xcf8014760f       ,0x18ded91f0e7      ,
            0x2fb1d8fe082      ,0x5b771955b36      ,0xaf67a93bb50      ,0x15060c256cb2     ,
            0x285145f31ae5     ,0x4d5156639708     ,0x944620b0e70e     ,0x11c592761c666    ,
            0x2214d10d014ea    ,0x415bc6d6fb7dd    ,0x7d56e76777fc5    ,0xf05dc6b27edad    ,
            0x1ccf4b44bb4820   ,0x373fc456c53bb7   ,0x69f3d1c921891c   ,0xcb2ff529eb71e4   ,
            0x185a82b87b72e95  ,0x2eb40f9f620fda6  ,0x5990681d961a1ea  ,0xabc25204e02828d  ,
            0x14962dee9dc97640 ,0x277abdcdab07d5a7 ,0x4bb5ecca963d54ab ,0x9131271922eaa606 ,
            0x116701e6ab0cd188d,0x215f77c045fbe8856,0x3ffffffffffffffff,0x7abbf6f6abb9d087f,
        };
        Since we cannot use an array of constants, we need to approximate the maximum value dynamically.
        The precision may be a value between 32 and 64, in multiples of 2 (i.e., 32, 34, 36, ..., 64).
        For the minimum precision of 32, the maximum value is MAX_FIXED_EXP_32.
        For each additional precision unit, the maximum value permitted increases by approximately 1.9.
        So in order to calculate it, we should multiply MAX_FIXED_EXP_32 by 1.9 ^ ((precision - 32) / 2).
        Since we cannot use non-integers, we multiply by 19 ^ ((precision - 32) / 2) and divide by 10 ^ ((precision - 32) / 2).
        But there is a better approximation, since this "1.9" factor in fact extends beyond a single decimal digit.
        So instead, we use 367765941410234761 / 100000000000000000, which yields maximum values quite close to real ones:
        maxExpArray = {
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            0x386bfdba29       ,-------------------,0xcf8014760e       ,-------------------,
            0x2fb1d8fe07b      ,-------------------,0xaf67a93bb37      ,-------------------,
            0x285145f31a8f     ,-------------------,0x944620b0e5ee     ,-------------------,
            0x2214d10d0112e    ,-------------------,0x7d56e7677738e    ,-------------------,
            0x1ccf4b44bb20d0   ,-------------------,0x69f3d1c9210d27   ,-------------------,
            0x185a82b87b5b294  ,-------------------,0x5990681d95d4371  ,-------------------,
            0x14962dee9dbd672a ,-------------------,0x4bb5ecca961fb9b8 ,-------------------,
            0x116701e6ab096705a,-------------------,0x3fffffffffffe6599,-------------------,
        };
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = maxExp * 367765941410234761 / 100000000000000000;

        assert(_x <= maxExp);
        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 = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _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
        Predicts the highest precision which can be used in order to compute "base^exp" without exceeding 256 bits in any of the intermediate computations.
        Instead of calculating "base^exp", we calculate "e^(ln(base)*exp)".
        The value of ln(base) is represented with an integer slightly smaller than ln(base)*2^precision.
        The larger the 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 on the precision (e.g, for precision=32, the maximum value of x is MAX_FIXED_EXP_32).
        Hence before calling the 'power' function, we need to estimate an upper-bound for ln(base)*exponent.
        Dividing MAX_FIXED_EXP_32 by this value will indicate the highest precision which can be used.
        Of course, this is slightly a 'chicken-egg' paradox, because MAX_FIXED_EXP_32 corresponds with a precision of 32 to begin with.
        For example, if we deduce that the highest precision which can be used is 33, then we should have actually used "MAX_FIXED_EXP_33" in order to deduce that.
        However, the value of MAX_FIXED_EXP(precision) is appriximately 2 times larger than the value of MAX_FIXED_EXP(precision-1).
        Hence if we deduce that the highest precision which can be used is 33, then we can in fact most likely use a precision of 34.
        So instead of returning 'precision', we return 'precision * 2 - 32'.
        Of course, we should later assert that the value passed to fixedExpUnsafe is not larger than MAX_FIXED_EXP(precision).
        Due to this assertion (made in function fixedExp before calling function fixedExpUnsafe), the precision must be a value between 32 and 64.
        In addition, since the value of 'precision * 2 - 32' is even, we can calculate MAX_FIXED_EXP(precision) within half as many iterations.
        Hence both functions (getBestPrecision and fixedExp) are tightly coupled.
        Note that the outcome of this function only affects the accuracy of the computation of "base^exp".
        Therefore, there is no need to assert that no intermediate result exceeds 256 bits (nor in this function, neither in any of the functions down the calling tree).
    */
    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));
        if (precision <= 32)
            return 32;
        if (precision >= 48)
            return 64;
        return precision * 2 - 32;
    }

    /**
        lnUpperBound
        Takes a rational number (baseN / baseD) as input.
        Returns an estimated upper-bound integer of the natural logarithm of the input.
        We can generally use floorLog2, although there is possibly a tighter bound.
        We cannot use floorLog2 when the input is smaller than 8.
        Complexity is O(log(input)).
    */
    function lnUpperBound(uint256 baseN, uint256 baseD) constant returns (uint8) {
        assert(baseN > baseD);

        uint256 scaledBaseN = baseN * 100000;
        if (scaledBaseN <= baseD *  271828) // baseN / baseD < e^1 (floorLog2 will return 0 if baseN / baseD < 2)
            return 1;
        if (scaledBaseN <= baseD *  738905) // baseN / baseD < e^2 (floorLog2 will return 1 if baseN / baseD < 4)
            return 2;
        if (scaledBaseN <= baseD * 2008553) // baseN / baseD < e^3 (floorLog2 will return 2 if baseN / baseD < 8)
            return 3;

        return floorLog2(baseN/baseD);
    }

    /**
        floorLog2
        Takes a natural number (n) as input.
        Returns the largest integer smaller than or equal to the binary logarithm of the input.
        Complexity is O(log(input)).
    */
    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));
    }
}


Changed Default Behaviour

Changed Default Behaviour

pragma solidity ^0.4.10;
/**
 * StromDAO Business Objects
 * ====================================================================
 * Upper level business objects required for power delivery on a public
 * energy distribution system. Defines PowerDelivery as digital asset
 * used for transaction data and entities (roles) for master data.
 *
 * @author Thorsten Zoerner <thorsten.zoerner(at)stromdao.de)
 **/

contract owned {
    address public owner;
    event Transfered(address old_owner,address new_owner);
    function owned() {
        owner = msg.sender;
    }

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

    modifier onlyOwnerAsOriginator {
        if (tx.origin != owner) throw;
        _;
    }

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

contract DeliveryReceiver is owned {
    RoleLookup public roles;
    DeliveryReceiver public nextReceiver;
    mapping(address=>bool) public monitored;

    event Process(address sender,address account,uint256 startTime,uint256 endTime,uint256 power);

    function DeliveryReceiver(RoleLookup _roles) {
        roles=_roles;
    }

    function process(Delivery _delivery) {
        if(monitored[_delivery.account()]) {
            Process(msg.sender,_delivery.account(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.deliverable_power());
        }
        if(address(nextReceiver)!=address(0)) nextReceiver.process(_delivery);
    }

    function  monitor(address _account,bool _monitor) internal {
        monitored[_account]=_monitor;
    }
    function setNextReceiver(DeliveryReceiver _next) onlyOwner {
        nextReceiver=_next;
    }
}

/**
 * RoleLookup
 *
 * ====================================================================
 * Provides entity relation model (yellowpages, who-implements-what)
 * to StromDAO Business Objects. A single consensframe must always share
 * a single RoleLookup deployment.
 */
contract RoleLookup {
    mapping(uint256 => uint8) public roles;
    mapping(address=>mapping(address=>address)) public relations;

    event Relation(address _from,uint8 _for, address _to);

    function RoleLookup() {
        roles[0]= 0;
        roles[1]= 1;
        roles[2]= 2;
        roles[3]= 3;
        roles[4]= 4;
        roles[5]= 5;
    }
    function setRelation(uint8 _for,address _from) {
        relations[msg.sender][_for]=_from;
        Relation(_from,_for,msg.sender);
    }
    /*
    function setRelationOnBehalf(uint8 _for,address _from,address _to)  onlyOwnerAsOriginator {
        relations[_to][_for]=_from;
        Relation(_from,_for,msg.sender);
    }
    */
    /*
    function deleteRelation(uint8 _for, address _to) onlyOwner {
        relations[_to][_for]=address(0);
        Relation(_to,_for,address(0));
    }
    */

}

/**
 * MeterPointOperator
 * ====================================================================
 * An entity that manages several meters
 */

contract MPO is owned {
    RoleLookup public roles;

    event StatusChange(address _meter_point,bool _is_approved);
    event IssuedDelivery(address delivery,address _meterpoint,uint256 _roleId,uint256 fromTime,uint256 toTime,uint256 power);
    mapping(address=>uint8) public approvedMeterPoints;
    mapping(address=>reading) public readings;
    mapping(address=>reading) public processed;
    mapping(address=>Delivery) public lastDelivery;
    mapping(address=>mapping(address=>address)) public issuedDeliverables;
    struct reading {
        uint256 time;
        uint256 power;

    }
    function MPO(RoleLookup _roles) {
        roles=_roles;
    }

    function approveMP(address _meter_point,uint8 role_id)  {
        approvedMeterPoints[_meter_point]=role_id;
        StatusChange(_meter_point,true);
    }

    function declineMP(address _meter_point)  {
        approvedMeterPoints[_meter_point]=0;
        StatusChange(_meter_point,false);
    }

    function storeReading(uint256 _reading) {
        if((approvedMeterPoints[msg.sender]!=4)&&(approvedMeterPoints[msg.sender]!=5)) throw;
        if(readings[msg.sender].power>_reading) throw;
        if(readings[msg.sender].power<_reading) {
            Delivery delivery = new Delivery(roles,msg.sender,approvedMeterPoints[msg.sender],readings[msg.sender].time,now,_reading-readings[msg.sender].power);
            IssuedDelivery(address(delivery),msg.sender,approvedMeterPoints[msg.sender],readings[msg.sender].time,now,_reading-readings[msg.sender].power);
            issuedDeliverables[msg.sender][address(lastDelivery[msg.sender])]=address(delivery);
            lastDelivery[msg.sender]=delivery;
            address nextOwner = msg.sender;
            address provider = roles.relations(msg.sender,roles.roles(3));
            if(address(0)!=provider) {
                nextOwner=provider;
               // DeliveryReceiver provider_receiver = DeliveryReceiver(provider);
            //    provider_receiver.process(delivery);
            }
            delivery.transferOwnership(nextOwner);

            address dso = roles.relations(msg.sender,roles.roles(2));
            if(dso!=address(0)) {
                DeliveryReceiver provider_dso = DeliveryReceiver(dso);
                provider_dso.process(delivery);
            }

        }
        readings[msg.sender]=reading(now,_reading);
    }

}

contract TxHandler is owned  {

	  function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
	  }

}

contract Stromkonto is TxHandler {

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

    mapping (address => uint256) public balancesHaben;
    mapping (address => uint256) public balancesSoll;

    function transfer(address _to, uint256 _value) returns (bool success) { return false; throw;}

    function balanceHaben(address _owner) constant returns (uint256 balance) {
        return balancesHaben[_owner];
    }

    function balanceSoll(address _owner) constant returns (uint256 balance) {
        return balancesSoll[_owner];
    }

    function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
        balancesSoll[_from]+=_value;
        balancesHaben[_to]+=_value;
        Tx(_from,_to,_value,_base);
    }

}

contract StromkontoProxy is Stromkonto {

		mapping(address=>bool) public allowedSenders;

		function StromkontoProxy() {
				allowedSenders[msg.sender]=true;
		}
		function modifySender(address _who,bool _allow) {
				allowedSenders[_who]=_allow;
		}

		function addTx(address _from,address _to, uint256 _value,uint256 _base)  {
			if(allowedSenders[msg.sender]) {
				balancesSoll[_from]+=_value;
				balancesHaben[_to]+=_value;
				Tx(_from,_to,_value,_base);
			}
		}

}
contract Billing {

    event Calculated(address from,address to,uint256 cost);
    address public from;
    address public to;
    uint256 public cost_per_day;
    uint256 public cost_per_energy;

    function Billing(uint256 _cost_per_day,uint256 _cost_per_energy) {
        cost_per_day=_cost_per_day;
        cost_per_energy=_cost_per_energy;
    }

    function becomeFrom() {
        if(address(0)!=from) throw;
        from=msg.sender;
    }

    function becomeTo() {
        if(address(0)!=to) throw;
        to=msg.sender;
    }

    function calculate(Delivery _delivery) returns(uint256) {
        if(msg.sender!=from) throw;
        if(address(0)==to) throw;
        uint256 cost=0;

        cost+=_delivery.deliverable_power()*cost_per_energy;
        cost+=((_delivery.deliverable_endTime()-_delivery.deliverable_startTime())/86400)*cost_per_day;

        Calculated(from,to,cost);

        return cost;

    }
}

contract Provider is owned  {
    RoleLookup public roles;
    Delivery public base_delivery_out;
    Delivery public base_delivery_in;
    TxHandler public stromkonto;

    mapping(address=>Billing) public billings;

    function Provider(RoleLookup _roles,TxHandler _stromkonto) {
		stromkonto=_stromkonto;
        roles=_roles;
        roles.setRelation(roles.roles(1),this);
        roles.setRelation(roles.roles(2),this);
        stromkonto=_stromkonto;
        base_delivery_out=new Delivery(roles,this,5,now,now,0);
        base_delivery_in=new Delivery(roles,this,4,now,now,0);
    }

    function powerToMoney(Delivery _delivery) internal {
        if(address(billings[msg.sender])!=address(0)) {
            stromkonto.addTx(msg.sender,this,billings[msg.sender].calculate(_delivery),_delivery.deliverable_power());
        }
    }

    function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
			stromkonto.addTx(_from,_to,_value,_base);
	}

    function handleDelivery(Delivery _delivery) {
        if(_delivery.owner()!=address(this)) throw;

        powerToMoney(_delivery);

        if(_delivery.role()==base_delivery_in.role()) {
            _delivery.transferOwnership(address(base_delivery_in));
           base_delivery_in.includeDelivery(_delivery);
        } else if(_delivery.role()==base_delivery_out.role()) {
            _delivery.transferOwnership(address(base_delivery_out));
            base_delivery_out.includeDelivery(_delivery);
        }

    }
    function doCrossing(Delivery _del1,Delivery _del2) internal {
        _del1.transferOwnership(address(_del2));
		_del2.includeDelivery(_del1);
    }
    /** Crosses In And Out BaseDelivery */
    function crossBalance() onlyOwner {
		if(base_delivery_in.deliverable_power()>base_delivery_out.deliverable_power()) {
		        doCrossing(base_delivery_out,base_delivery_in);
				base_delivery_out=new Delivery(roles,this,5,now,now,0);
		} else {
                doCrossing(base_delivery_in,base_delivery_out);
				base_delivery_in=new Delivery(roles,this,4,now,now,0);
		}
	}

    function approveSender(address _address,bool _approve,uint256 cost_per_day,uint256 cost_per_energy) {
        // TODO: Set onlyOwner in production
        Billing billing=new Billing(cost_per_day,cost_per_energy);
        if(_approve) {
            billing.becomeFrom();
        }
        billings[_address]=billing;
    }

}

contract DSO is  owned {
    RoleLookup public roles;
    mapping(address=>bool) public approvedProvider;
    mapping(address=>uint256) public approvedConnections;
    function DSO(RoleLookup _roles) {
        roles=_roles;
    }

    function approveConnection(address _address,uint256 _power_limit)  {
            approvedConnections[_address]=_power_limit;
            if(_power_limit>0) {
                monitor(_address,true);
            } else {
                monitor(_address,false);
            }
    }

    function providerAllowance(address dso,bool allow) onlyOwner {
        approvedProvider[dso]=allow;
    }

    DeliveryReceiver public nextReceiver;
    mapping(address=>bool) public monitored;

    event Process(address sender,address account,uint256 startTime,uint256 endTime,uint256 power);

    function process(Delivery _delivery) {
        if(monitored[_delivery.account()]) {
            Process(msg.sender,_delivery.account(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.deliverable_power());
        }
        if(address(nextReceiver)!=address(0)) nextReceiver.process(_delivery);
    }

    function  monitor(address _account,bool _monitor) internal {
        monitored[_account]=_monitor;
    }
    function setNextReceiver(DeliveryReceiver _next) onlyOwner {
        nextReceiver=_next;
    }
}

contract Delivery is owned {
    RoleLookup public roles;
    address public dso;
    uint8 public role;

    uint256 public deliverable_startTime;
    uint256 public deliverable_endTime;
    uint256 public deliverable_power;
    address public resolution;
    address public account;
     event Destructed(address _destruction);
     event Included(address _address,uint256 power,uint256 startTime,uint256 endTime,uint256 role);

    function Delivery(RoleLookup _roles,address _meterpoint,uint8 _mprole,uint256 _startTime,uint256 _endTime, uint256 _power)  {
        roles=_roles;
        role=_mprole;

        deliverable_startTime=_startTime;
        deliverable_endTime=_endTime;
        deliverable_power=_power;

        // check sender is MPO for MP
       // if(msg.sender!=roles.relations(_meterpoint,roles.roles(1))) throw;
        //dso=roles.relations(_meterpoint,roles.roles(2)); TODO: Check why that throws
        //if(address(0)==dso) throw;
        account=_meterpoint;

    }

    function includeDelivery(Delivery _delivery) onlyOwner {
        if(_delivery.owner()!=address(this)) throw; // Operation only allowed if not owned by this Delivery

        if(deliverable_startTime>_delivery.deliverable_startTime()) deliverable_startTime=_delivery.deliverable_startTime();
        if(deliverable_endTime<_delivery.deliverable_endTime()) deliverable_endTime=_delivery.deliverable_endTime();
        if(_delivery.role()==role) {
            // add
            deliverable_power+=_delivery.deliverable_power();
        } else {
            // substract (Need to change Role, if lt 0)
            if(_delivery.deliverable_power()>deliverable_power) throw; // Not a include!
           deliverable_power-=_delivery.deliverable_power();
        }
        Included(address(_delivery),_delivery.deliverable_power(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.role());
        _delivery.destructWith(this);

    }

    function destructWith(Delivery _delivery) onlyOwner {

        if(address(resolution)!=0) throw;
        deliverable_power=0;
        Destructed(address(_delivery));

        resolution=address(_delivery);
        transferOwnership(account);

    }
}

pragma solidity ^0.4.10;
/**
 * StromDAO Business Objects
 * ====================================================================
 * Upper level business objects required for power delivery on a public
 * energy distribution system. Defines PowerDelivery as digital asset
 * used for transaction data and entities (roles) for master data.
 *
 * @author Thorsten Zoerner <thorsten.zoerner(at)stromdao.de)
 **/

contract owned {
    address public owner;
    event Transfered(address old_owner,address new_owner);
    function owned() {
        owner = msg.sender;
    }

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

    modifier onlyOwnerAsOriginator {
        if (tx.origin != owner) throw;
        _;
    }

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

contract DeliveryReceiver is owned {
    RoleLookup public roles;
    DeliveryReceiver public nextReceiver;
    mapping(address=>bool) public monitored;

    event Process(address sender,address account,uint256 startTime,uint256 endTime,uint256 power);

    function DeliveryReceiver(RoleLookup _roles) {
        roles=_roles;
    }

    function process(Delivery _delivery) {
        if(monitored[_delivery.account()]) {
            Process(msg.sender,_delivery.account(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.deliverable_power());
        }
        if(address(nextReceiver)!=address(0)) nextReceiver.process(_delivery);
    }

    function  monitor(address _account,bool _monitor) internal {
        monitored[_account]=_monitor;
    }
    function setNextReceiver(DeliveryReceiver _next) onlyOwner {
        nextReceiver=_next;
    }
}

/**
 * RoleLookup
 *
 * ====================================================================
 * Provides entity relation model (yellowpages, who-implements-what)
 * to StromDAO Business Objects. A single consensframe must always share
 * a single RoleLookup deployment.
 */
contract RoleLookup {
    mapping(uint256 => uint8) public roles;
    mapping(address=>mapping(address=>address)) public relations;

    event Relation(address _from,uint8 _for, address _to);

    function RoleLookup() {
        roles[0]= 0;
        roles[1]= 1;
        roles[2]= 2;
        roles[3]= 3;
        roles[4]= 4;
        roles[5]= 5;
    }
    function setRelation(uint8 _for,address _from) {
        relations[msg.sender][_for]=_from;
        Relation(_from,_for,msg.sender);
    }
    /*
    function setRelationOnBehalf(uint8 _for,address _from,address _to)  onlyOwnerAsOriginator {
        relations[_to][_for]=_from;
        Relation(_from,_for,msg.sender);
    }
    */
    /*
    function deleteRelation(uint8 _for, address _to) onlyOwner {
        relations[_to][_for]=address(0);
        Relation(_to,_for,address(0));
    }
    */

}

/**
 * MeterPointOperator
 * ====================================================================
 * An entity that manages several meters
 */

contract MPO is owned {
    RoleLookup public roles;

    event StatusChange(address _meter_point,bool _is_approved);
    event IssuedDelivery(address delivery,address _meterpoint,uint256 _roleId,uint256 fromTime,uint256 toTime,uint256 power);
    mapping(address=>uint8) public approvedMeterPoints;
    mapping(address=>reading) public readings;
    mapping(address=>reading) public processed;
    mapping(address=>Delivery) public lastDelivery;
    mapping(address=>mapping(address=>address)) public issuedDeliverables;
    struct reading {
        uint256 time;
        uint256 power;

    }
    function MPO(RoleLookup _roles) {
        roles=_roles;
    }

    function approveMP(address _meter_point,uint8 role_id)  {
        approvedMeterPoints[_meter_point]=role_id;
        StatusChange(_meter_point,true);
    }

    function declineMP(address _meter_point)  {
        approvedMeterPoints[_meter_point]=0;
        StatusChange(_meter_point,false);
    }

    function storeReading(uint256 _reading) {
        if((approvedMeterPoints[msg.sender]!=4)&&(approvedMeterPoints[msg.sender]!=5)) throw;
        if(readings[msg.sender].power>_reading) throw;
        if(readings[msg.sender].power<_reading) {
            Delivery delivery = new Delivery(roles,msg.sender,approvedMeterPoints[msg.sender],readings[msg.sender].time,now,_reading-readings[msg.sender].power);
            IssuedDelivery(address(delivery),msg.sender,approvedMeterPoints[msg.sender],readings[msg.sender].time,now,_reading-readings[msg.sender].power);
            issuedDeliverables[msg.sender][address(lastDelivery[msg.sender])]=address(delivery);
            lastDelivery[msg.sender]=delivery;
            address nextOwner = msg.sender;
            address provider = roles.relations(msg.sender,roles.roles(3));
            if(address(0)!=provider) {
                nextOwner=provider;
               // DeliveryReceiver provider_receiver = DeliveryReceiver(provider);
            //    provider_receiver.process(delivery);
            }
            delivery.transferOwnership(nextOwner);

            /*
            address dso = roles.relations(msg.sender,roles.roles(2));
            if(dso!=address(0)) {
                DeliveryReceiver provider_dso = DeliveryReceiver(dso);
                provider_dso.process(delivery);
            }
            */

        }
        readings[msg.sender]=reading(now,_reading);
    }

}

contract TxHandler is owned  {

	  function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
	  }

}

contract Stromkonto is TxHandler {

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

    mapping (address => uint256) public balancesHaben;
    mapping (address => uint256) public balancesSoll;

    function transfer(address _to, uint256 _value) returns (bool success) { return false; throw;}

    function balanceHaben(address _owner) constant returns (uint256 balance) {
        return balancesHaben[_owner];
    }

    function balanceSoll(address _owner) constant returns (uint256 balance) {
        return balancesSoll[_owner];
    }

    function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
        balancesSoll[_from]+=_value;
        balancesHaben[_to]+=_value;
        Tx(_from,_to,_value,_base);
    }

}

contract StromkontoProxy is Stromkonto {

		mapping(address=>bool) public allowedSenders;

		function StromkontoProxy() {
				allowedSenders[msg.sender]=true;
		}
		function modifySender(address _who,bool _allow) {
				allowedSenders[_who]=_allow;
		}

		function addTx(address _from,address _to, uint256 _value,uint256 _base)  {
			if(allowedSenders[msg.sender]) {
				balancesSoll[_from]+=_value;
				balancesHaben[_to]+=_value;
				Tx(_from,_to,_value,_base);
			}
		}

}
contract Billing {

    event Calculated(address from,address to,uint256 cost);
    address public from;
    address public to;
    uint256 public cost_per_day;
    uint256 public cost_per_energy;

    function Billing(uint256 _cost_per_day,uint256 _cost_per_energy) {
        cost_per_day=_cost_per_day;
        cost_per_energy=_cost_per_energy;
    }

    function becomeFrom() {
        if(address(0)!=from) throw;
        from=msg.sender;
    }

    function becomeTo() {
        if(address(0)!=to) throw;
        to=msg.sender;
    }

    function calculate(Delivery _delivery) returns(uint256) {
        if(msg.sender!=from) throw;
        if(address(0)==to) throw;
        uint256 cost=0;

        cost+=_delivery.deliverable_power()*cost_per_energy;
        cost+=((_delivery.deliverable_endTime()-_delivery.deliverable_startTime())/86400)*cost_per_day;

        Calculated(from,to,cost);

        return cost;

    }
}

contract Provider is owned  {
    RoleLookup public roles;
    Delivery public base_delivery_out;
    Delivery public base_delivery_in;
    TxHandler public stromkonto;

    mapping(address=>Billing) public billings;

    function Provider(RoleLookup _roles,TxHandler _stromkonto) {
		stromkonto=_stromkonto;
        roles=_roles;
        roles.setRelation(roles.roles(1),this);
        roles.setRelation(roles.roles(2),this);
        stromkonto=_stromkonto;
        base_delivery_out=new Delivery(roles,this,5,now,now,0);
        base_delivery_in=new Delivery(roles,this,4,now,now,0);
    }

    function powerToMoney(Delivery _delivery) internal {
        if(address(billings[msg.sender])!=address(0)) {
            stromkonto.addTx(msg.sender,this,billings[msg.sender].calculate(_delivery),_delivery.deliverable_power());
        }
    }

    function addTx(address _from,address _to, uint256 _value,uint256 _base) onlyOwner {
			stromkonto.addTx(_from,_to,_value,_base);
	}

    function handleDelivery(Delivery _delivery) {
        if(_delivery.owner()!=address(this)) throw;

        powerToMoney(_delivery);

        if(_delivery.role()==base_delivery_in.role()) {
            _delivery.transferOwnership(address(base_delivery_in));
           base_delivery_in.includeDelivery(_delivery);
        } else if(_delivery.role()==base_delivery_out.role()) {
            _delivery.transferOwnership(address(base_delivery_out));
            base_delivery_out.includeDelivery(_delivery);
        }

    }
    function doCrossing(Delivery _del1,Delivery _del2) internal {
        _del1.transferOwnership(address(_del2));
		_del2.includeDelivery(_del1);
    }
    /** Crosses In And Out BaseDelivery */
    function crossBalance() onlyOwner {
		if(base_delivery_in.deliverable_power()>base_delivery_out.deliverable_power()) {
		        doCrossing(base_delivery_out,base_delivery_in);
				base_delivery_out=new Delivery(roles,this,5,now,now,0);
		} else {
                doCrossing(base_delivery_in,base_delivery_out);
				base_delivery_in=new Delivery(roles,this,4,now,now,0);
		}
	}

    function approveSender(address _address,bool _approve,uint256 cost_per_day,uint256 cost_per_energy) {
        // TODO: Set onlyOwner in production
        Billing billing=new Billing(cost_per_day,cost_per_energy);
        if(_approve) {
            billing.becomeFrom();
        }
        billings[_address]=billing;
    }

}

contract DSO is  owned {
    RoleLookup public roles;
    mapping(address=>bool) public approvedProvider;
    mapping(address=>uint256) public approvedConnections;
    function DSO(RoleLookup _roles) {
        roles=_roles;
    }

    function approveConnection(address _address,uint256 _power_limit)  {
            approvedConnections[_address]=_power_limit;
            if(_power_limit>0) {
                monitor(_address,true);
            } else {
                monitor(_address,false);
            }
    }

    function providerAllowance(address dso,bool allow) onlyOwner {
        approvedProvider[dso]=allow;
    }

    DeliveryReceiver public nextReceiver;
    mapping(address=>bool) public monitored;

    event Process(address sender,address account,uint256 startTime,uint256 endTime,uint256 power);

    function process(Delivery _delivery) {
        if(monitored[_delivery.account()]) {
            Process(msg.sender,_delivery.account(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.deliverable_power());
        }
        if(address(nextReceiver)!=address(0)) nextReceiver.process(_delivery);
    }

    function  monitor(address _account,bool _monitor) internal {
        monitored[_account]=_monitor;
    }
    function setNextReceiver(DeliveryReceiver _next) onlyOwner {
        nextReceiver=_next;
    }
}

contract Delivery is owned {
    RoleLookup public roles;
    address public dso;
    uint8 public role;

    uint256 public deliverable_startTime;
    uint256 public deliverable_endTime;
    uint256 public deliverable_power;
    address public resolution;
    address public account;
     event Destructed(address _destruction);
     event Included(address _address,uint256 power,uint256 startTime,uint256 endTime,uint256 role);

    function Delivery(RoleLookup _roles,address _meterpoint,uint8 _mprole,uint256 _startTime,uint256 _endTime, uint256 _power)  {
        roles=_roles;
        role=_mprole;

        deliverable_startTime=_startTime;
        deliverable_endTime=_endTime;
        deliverable_power=_power;

        // check sender is MPO for MP
       // if(msg.sender!=roles.relations(_meterpoint,roles.roles(1))) throw;
        //dso=roles.relations(_meterpoint,roles.roles(2)); TODO: Check why that throws
        //if(address(0)==dso) throw;
        account=_meterpoint;

    }

    function includeDelivery(Delivery _delivery) onlyOwner {
        if(_delivery.owner()!=address(this)) throw; // Operation only allowed if not owned by this Delivery

        if(deliverable_startTime>_delivery.deliverable_startTime()) deliverable_startTime=_delivery.deliverable_startTime();
        if(deliverable_endTime<_delivery.deliverable_endTime()) deliverable_endTime=_delivery.deliverable_endTime();
        if(_delivery.role()==role) {
            // add
            deliverable_power+=_delivery.deliverable_power();
        } else {
            // substract (Need to change Role, if lt 0)
            if(_delivery.deliverable_power()>deliverable_power) throw; // Not a include!
           deliverable_power-=_delivery.deliverable_power();
        }
        Included(address(_delivery),_delivery.deliverable_power(),_delivery.deliverable_startTime(),_delivery.deliverable_endTime(),_delivery.role());
        _delivery.destructWith(this);

    }

    function destructWith(Delivery _delivery) onlyOwner {

        if(address(resolution)!=0) throw;
        deliverable_power=0;
        Destructed(address(_delivery));
        resolution=address(_delivery);

    }
}