Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 1 txn
Misc:
Address Watch: Add To Watch List
Contract Creator: 0xb1f919db227048a1a45883138b9d12b9ef03df25at txn 0x9174afb5952e41e2277a7ed1b5e8136efcefd86ec45bbca92ec396eb6227f50e
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: DutchExchange
Compiler Text: v0.4.21+commit.dfe3193c
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.21;

// File: contracts/Oracle/DSAuth.sol

contract DSAuthority {
    function canCall(
        address src, address dst, bytes4 sig
    ) public view returns (bool);
}

contract DSAuthEvents {
    event LogSetAuthority (address indexed authority);
    event LogSetOwner     (address indexed owner);
}

contract DSAuth is DSAuthEvents {
    DSAuthority  public  authority;
    address      public  owner;

    function DSAuth() public {
        owner = msg.sender;
        LogSetOwner(msg.sender);
    }

    function setOwner(address owner_)
        public
        auth
    {
        owner = owner_;
        LogSetOwner(owner);
    }

    function setAuthority(DSAuthority authority_)
        public
        auth
    {
        authority = authority_;
        LogSetAuthority(authority);
    }

    modifier auth {
        require(isAuthorized(msg.sender, msg.sig));
        _;
    }

    function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
        if (src == address(this)) {
            return true;
        } else if (src == owner) {
            return true;
        } else if (authority == DSAuthority(0)) {
            return false;
        } else {
            return authority.canCall(src, this, sig);
        }
    }
}

// File: contracts/Oracle/DSMath.sol

contract DSMath {
    
    /*
    standard uint256 functions
     */

    function add(uint256 x, uint256 y) constant internal returns (uint256 z) {
        assert((z = x + y) >= x);
    }

    function sub(uint256 x, uint256 y) constant internal returns (uint256 z) {
        assert((z = x - y) <= x);
    }

    function mul(uint256 x, uint256 y) constant internal returns (uint256 z) {
        assert((z = x * y) >= x);
    }

    function div(uint256 x, uint256 y) constant internal returns (uint256 z) {
        z = x / y;
    }

    function min(uint256 x, uint256 y) constant internal returns (uint256 z) {
        return x <= y ? x : y;
    }
    function max(uint256 x, uint256 y) constant internal returns (uint256 z) {
        return x >= y ? x : y;
    }

    /*
    uint128 functions (h is for half)
     */


    function hadd(uint128 x, uint128 y) constant internal returns (uint128 z) {
        assert((z = x + y) >= x);
    }

    function hsub(uint128 x, uint128 y) constant internal returns (uint128 z) {
        assert((z = x - y) <= x);
    }

    function hmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
        assert((z = x * y) >= x);
    }

    function hdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
        z = x / y;
    }

    function hmin(uint128 x, uint128 y) constant internal returns (uint128 z) {
        return x <= y ? x : y;
    }
    function hmax(uint128 x, uint128 y) constant internal returns (uint128 z) {
        return x >= y ? x : y;
    }


    /*
    int256 functions
     */

    function imin(int256 x, int256 y) constant internal returns (int256 z) {
        return x <= y ? x : y;
    }
    function imax(int256 x, int256 y) constant internal returns (int256 z) {
        return x >= y ? x : y;
    }

    /*
    WAD math
     */

    uint128 constant WAD = 10 ** 18;

    function wadd(uint128 x, uint128 y) constant internal returns (uint128) {
        return hadd(x, y);
    }

    function wsub(uint128 x, uint128 y) constant internal returns (uint128) {
        return hsub(x, y);
    }

    function wmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
        z = cast((uint256(x) * y + WAD / 2) / WAD);
    }

    function wdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
        z = cast((uint256(x) * WAD + y / 2) / y);
    }

    function wmin(uint128 x, uint128 y) constant internal returns (uint128) {
        return hmin(x, y);
    }
    function wmax(uint128 x, uint128 y) constant internal returns (uint128) {
        return hmax(x, y);
    }

    /*
    RAY math
     */

    uint128 constant RAY = 10 ** 27;

    function radd(uint128 x, uint128 y) constant internal returns (uint128) {
        return hadd(x, y);
    }

    function rsub(uint128 x, uint128 y) constant internal returns (uint128) {
        return hsub(x, y);
    }

    function rmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
        z = cast((uint256(x) * y + RAY / 2) / RAY);
    }

    function rdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
        z = cast((uint256(x) * RAY + y / 2) / y);
    }

    function rpow(uint128 x, uint64 n) constant internal returns (uint128 z) {
        // This famous algorithm is called "exponentiation by squaring"
        // and calculates x^n with x as fixed-point and n as regular unsigned.
        //
        // It's O(log n), instead of O(n) for naive repeated multiplication.
        //
        // These facts are why it works:
        //
        //  If n is even, then x^n = (x^2)^(n/2).
        //  If n is odd,  then x^n = x * x^(n-1),
        //   and applying the equation for even x gives
        //    x^n = x * (x^2)^((n-1) / 2).
        //
        //  Also, EVM division is flooring and
        //    floor[(n-1) / 2] = floor[n / 2].

        z = n % 2 != 0 ? x : RAY;

        for (n /= 2; n != 0; n /= 2) {
            x = rmul(x, x);

            if (n % 2 != 0) {
                z = rmul(z, x);
            }
        }
    }

    function rmin(uint128 x, uint128 y) constant internal returns (uint128) {
        return hmin(x, y);
    }
    function rmax(uint128 x, uint128 y) constant internal returns (uint128) {
        return hmax(x, y);
    }

    function cast(uint256 x) constant internal returns (uint128 z) {
        assert((z = uint128(x)) == x);
    }

}

// File: contracts/Oracle/DSNote.sol

contract DSNote {
    event LogNote(
        bytes4   indexed  sig,
        address  indexed  guy,
        bytes32  indexed  foo,
        bytes32  indexed  bar,
        uint              wad,
        bytes             fax
    ) anonymous;

    modifier note {
        bytes32 foo;
        bytes32 bar;

        assembly {
            foo := calldataload(4)
            bar := calldataload(36)
        }

        LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);

        _;
    }
}

// File: contracts/Oracle/DSThing.sol

contract DSThing is DSAuth, DSNote, DSMath {
}

// File: contracts/Oracle/DSValue.sol

contract DSValue is DSThing {
    bool    has;
    bytes32 val;
    function peek() constant returns (bytes32, bool) {
        return (val,has);
    }
    function read() constant returns (bytes32) {
        var (wut, has) = peek();
        assert(has);
        return wut;
    }
    function poke(bytes32 wut) note auth {
        val = wut;
        has = true;
    }
    function void() note auth { // unset the value
        has = false;
    }
}

// File: contracts/Oracle/Medianizer.sol

contract Medianizer is DSValue {
    mapping (bytes12 => address) public values;
    mapping (address => bytes12) public indexes;
    bytes12 public next = 0x1;

    uint96 public min = 0x1;

    function set(address wat) auth {
        bytes12 nextId = bytes12(uint96(next) + 1);
        assert(nextId != 0x0);
        set(next, wat);
        next = nextId;
    }

    function set(bytes12 pos, address wat) note auth {
        if (pos == 0x0) throw;

        if (wat != 0 && indexes[wat] != 0) throw;

        indexes[values[pos]] = 0; // Making sure to remove a possible existing address in that position

        if (wat != 0) {
            indexes[wat] = pos;
        }

        values[pos] = wat;
    }

    function setMin(uint96 min_) note auth {
        if (min_ == 0x0) throw;
        min = min_;
    }

    function setNext(bytes12 next_) note auth {
        if (next_ == 0x0) throw;
        next = next_;
    }

    function unset(bytes12 pos) {
        set(pos, 0);
    }

    function unset(address wat) {
        set(indexes[wat], 0);
    }

    function poke() {
        poke(0);
    }

    function poke(bytes32) note {
        (val, has) = compute();
    }

    function compute() constant returns (bytes32, bool) {
        bytes32[] memory wuts = new bytes32[](uint96(next) - 1);
        uint96 ctr = 0;
        for (uint96 i = 1; i < uint96(next); i++) {
            if (values[bytes12(i)] != 0) {
                var (wut, wuz) = DSValue(values[bytes12(i)]).peek();
                if (wuz) {
                    if (ctr == 0 || wut >= wuts[ctr - 1]) {
                        wuts[ctr] = wut;
                    } else {
                        uint96 j = 0;
                        while (wut >= wuts[j]) {
                            j++;
                        }
                        for (uint96 k = ctr; k > j; k--) {
                            wuts[k] = wuts[k - 1];
                        }
                        wuts[j] = wut;
                    }
                    ctr++;
                }
            }
        }

        if (ctr < min) return (val, false);

        bytes32 value;
        if (ctr % 2 == 0) {
            uint128 val1 = uint128(wuts[(ctr / 2) - 1]);
            uint128 val2 = uint128(wuts[ctr / 2]);
            value = bytes32(wdiv(hadd(val1, val2), 2 ether));
        } else {
            value = wuts[(ctr - 1) / 2];
        }

        return (value, true);
    }
}

// File: contracts/Oracle/PriceFeed.sol

/// price-feed.sol

// Copyright (C) 2017  DappHub, LLC

// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.

// 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 (express or implied).



contract PriceFeed is DSThing {

    uint128 val;
    uint32 public zzz;

    function peek() public view
        returns (bytes32, bool)
    {
        return (bytes32(val), now < zzz);
    }

    function read() public view
        returns (bytes32)
    {
        assert(now < zzz);
        return bytes32(val);
    }

    function post(uint128 val_, uint32 zzz_, address med_) public note auth
    {
        val = val_;
        zzz = zzz_;
        bool ret = med_.call(bytes4(keccak256("poke()")));
        ret;
    }

    function void() public note auth
    {
        zzz = 0;
    }

}

// File: contracts/Oracle/PriceOracleInterface.sol

/*
This contract is the interface between the MakerDAO priceFeed and our DX platform.
*/



contract PriceOracleInterface {

    address public priceFeedSource;
    address public owner;
    bool public emergencyMode;

    event NonValidPriceFeed(address priceFeedSource);

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

    /// @dev constructor of the contract
    /// @param _priceFeedSource address of price Feed Source -> should be maker feeds Medianizer contract
    function PriceOracleInterface(
        address _owner,
        address _priceFeedSource
    )
        public
    {
        owner = _owner;
        priceFeedSource = _priceFeedSource;
    }
    /// @dev gives the owner the possibility to put the Interface into an emergencyMode, which will 
    /// output always a price of 600 USD. This gives everyone time to set up a new pricefeed.
    function raiseEmergency(bool _emergencyMode)
        public
        onlyOwner()
    {
        emergencyMode = _emergencyMode;
    }

    /// @dev updates the priceFeedSource
    /// @param _owner address of owner
    function updateCurator(
        address _owner
    )
        public
        onlyOwner()
    {
        owner = _owner;
    }

    /// @dev returns the USDETH price, ie gets the USD price from Maker feed with 18 digits, but last 18 digits are cut off
    function getUSDETHPrice() 
        public
        returns (uint256)
    {
        // if the contract is in the emergencyMode, because there is an issue with the oracle, we will simply return a price of 600 USD
        if(emergencyMode){
            return 600;
        }

        bytes32 price;
        bool valid=true;
        (price, valid) = Medianizer(priceFeedSource).peek();
        if (!valid) {
            NonValidPriceFeed(priceFeedSource);
        }
        // ensuring that there is no underflow or overflow possible,
        // even if the price is compromised
        uint priceUint = uint256(price)/(1 ether);
        if (priceUint == 0) return 1;
        if (priceUint > 1000000) return 1000000; 
        return priceUint;
    }  
}

// File: @gnosis.pm/util-contracts/contracts/Math.sol

/// @title Math library - Allows calculation of logarithmic and exponential functions
/// @author Alan Lu - <[email protected]>
/// @author Stefan George - <[email protected]>
library Math {

    /*
     *  Constants
     */
    // This is equal to 1 in our calculations
    uint public constant ONE =  0x10000000000000000;
    uint public constant LN2 = 0xb17217f7d1cf79ac;
    uint public constant LOG2_E = 0x171547652b82fe177;

    /*
     *  Public functions
     */
    /// @dev Returns natural exponential function value of given x
    /// @param x x
    /// @return e**x
    function exp(int x)
        public
        pure
        returns (uint)
    {
        // revert if x is > MAX_POWER, where
        // MAX_POWER = int(mp.floor(mp.log(mpf(2**256 - 1) / ONE) * ONE))
        require(x <= 2454971259878909886679);
        // return 0 if exp(x) is tiny, using
        // MIN_POWER = int(mp.floor(mp.log(mpf(1) / ONE) * ONE))
        if (x < -818323753292969962227)
            return 0;
        // Transform so that e^x -> 2^x
        x = x * int(ONE) / int(LN2);
        // 2^x = 2^whole(x) * 2^frac(x)
        //       ^^^^^^^^^^ is a bit shift
        // so Taylor expand on z = frac(x)
        int shift;
        uint z;
        if (x >= 0) {
            shift = x / int(ONE);
            z = uint(x % int(ONE));
        }
        else {
            shift = x / int(ONE) - 1;
            z = ONE - uint(-x % int(ONE));
        }
        // 2^x = 1 + (ln 2) x + (ln 2)^2/2! x^2 + ...
        //
        // Can generate the z coefficients using mpmath and the following lines
        // >>> from mpmath import mp
        // >>> mp.dps = 100
        // >>> ONE =  0x10000000000000000
        // >>> print('\n'.join(hex(int(mp.log(2)**i / mp.factorial(i) * ONE)) for i in range(1, 7)))
        // 0xb17217f7d1cf79ab
        // 0x3d7f7bff058b1d50
        // 0xe35846b82505fc5
        // 0x276556df749cee5
        // 0x5761ff9e299cc4
        // 0xa184897c363c3
        uint zpow = z;
        uint result = ONE;
        result += 0xb17217f7d1cf79ab * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x3d7f7bff058b1d50 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0xe35846b82505fc5 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x276556df749cee5 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x5761ff9e299cc4 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0xa184897c363c3 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0xffe5fe2c4586 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x162c0223a5c8 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x1b5253d395e * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x1e4cf5158b * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x1e8cac735 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x1c3bd650 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x1816193 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x131496 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0xe1b7 * zpow / ONE;
        zpow = zpow * z / ONE;
        result += 0x9c7 * zpow / ONE;
        if (shift >= 0) {
            if (result >> (256-shift) > 0)
                return (2**256-1);
            return result << shift;
        }
        else
            return result >> (-shift);
    }

    /// @dev Returns natural logarithm value of given x
    /// @param x x
    /// @return ln(x)
    function ln(uint x)
        public
        pure
        returns (int)
    {
        require(x > 0);
        // binary search for floor(log2(x))
        int ilog2 = floorLog2(x);
        int z;
        if (ilog2 < 0)
            z = int(x << uint(-ilog2));
        else
            z = int(x >> uint(ilog2));
        // z = x * 2^-⌊log₂x⌋
        // so 1 <= z < 2
        // and ln z = ln x - ⌊log₂x⌋/log₂e
        // so just compute ln z using artanh series
        // and calculate ln x from that
        int term = (z - int(ONE)) * int(ONE) / (z + int(ONE));
        int halflnz = term;
        int termpow = term * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 3;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 5;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 7;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 9;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 11;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 13;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 15;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 17;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 19;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 21;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 23;
        termpow = termpow * term / int(ONE) * term / int(ONE);
        halflnz += termpow / 25;
        return (ilog2 * int(ONE)) * int(ONE) / int(LOG2_E) + 2 * halflnz;
    }

    /// @dev Returns base 2 logarithm value of given x
    /// @param x x
    /// @return logarithmic value
    function floorLog2(uint x)
        public
        pure
        returns (int lo)
    {
        lo = -64;
        int hi = 193;
        // I use a shift here instead of / 2 because it floors instead of rounding towards 0
        int mid = (hi + lo) >> 1;
        while((lo + 1) < hi) {
            if (mid < 0 && x << uint(-mid) < ONE || mid >= 0 && x >> uint(mid) < ONE)
                hi = mid;
            else
                lo = mid;
            mid = (hi + lo) >> 1;
        }
    }

    /// @dev Returns maximum of an array
    /// @param nums Numbers to look through
    /// @return Maximum number
    function max(int[] nums)
        public
        pure
        returns (int maxNum)
    {
        require(nums.length > 0);
        maxNum = -2**255;
        for (uint i = 0; i < nums.length; i++)
            if (nums[i] > maxNum)
                maxNum = nums[i];
    }

    /// @dev Returns whether an add operation causes an overflow
    /// @param a First addend
    /// @param b Second addend
    /// @return Did no overflow occur?
    function safeToAdd(uint a, uint b)
        internal
        pure
        returns (bool)
    {
        return a + b >= a;
    }

    /// @dev Returns whether a subtraction operation causes an underflow
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Did no underflow occur?
    function safeToSub(uint a, uint b)
        internal
        pure
        returns (bool)
    {
        return a >= b;
    }

    /// @dev Returns whether a multiply operation causes an overflow
    /// @param a First factor
    /// @param b Second factor
    /// @return Did no overflow occur?
    function safeToMul(uint a, uint b)
        internal
        pure
        returns (bool)
    {
        return b == 0 || a * b / b == a;
    }

    /// @dev Returns sum if no overflow occurred
    /// @param a First addend
    /// @param b Second addend
    /// @return Sum
    function add(uint a, uint b)
        internal
        pure
        returns (uint)
    {
        require(safeToAdd(a, b));
        return a + b;
    }

    /// @dev Returns difference if no overflow occurred
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Difference
    function sub(uint a, uint b)
        internal
        pure
        returns (uint)
    {
        require(safeToSub(a, b));
        return a - b;
    }

    /// @dev Returns product if no overflow occurred
    /// @param a First factor
    /// @param b Second factor
    /// @return Product
    function mul(uint a, uint b)
        internal
        pure
        returns (uint)
    {
        require(safeToMul(a, b));
        return a * b;
    }

    /// @dev Returns whether an add operation causes an overflow
    /// @param a First addend
    /// @param b Second addend
    /// @return Did no overflow occur?
    function safeToAdd(int a, int b)
        internal
        pure
        returns (bool)
    {
        return (b >= 0 && a + b >= a) || (b < 0 && a + b < a);
    }

    /// @dev Returns whether a subtraction operation causes an underflow
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Did no underflow occur?
    function safeToSub(int a, int b)
        internal
        pure
        returns (bool)
    {
        return (b >= 0 && a - b <= a) || (b < 0 && a - b > a);
    }

    /// @dev Returns whether a multiply operation causes an overflow
    /// @param a First factor
    /// @param b Second factor
    /// @return Did no overflow occur?
    function safeToMul(int a, int b)
        internal
        pure
        returns (bool)
    {
        return (b == 0) || (a * b / b == a);
    }

    /// @dev Returns sum if no overflow occurred
    /// @param a First addend
    /// @param b Second addend
    /// @return Sum
    function add(int a, int b)
        internal
        pure
        returns (int)
    {
        require(safeToAdd(a, b));
        return a + b;
    }

    /// @dev Returns difference if no overflow occurred
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Difference
    function sub(int a, int b)
        internal
        pure
        returns (int)
    {
        require(safeToSub(a, b));
        return a - b;
    }

    /// @dev Returns product if no overflow occurred
    /// @param a First factor
    /// @param b Second factor
    /// @return Product
    function mul(int a, int b)
        internal
        pure
        returns (int)
    {
        require(safeToMul(a, b));
        return a * b;
    }
}

// File: @gnosis.pm/util-contracts/contracts/Proxy.sol

/// @title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.
/// @author Alan Lu - <[email protected]>
contract Proxied {
    address public masterCopy;
}

/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <[email protected]>
contract Proxy is Proxied {
    /// @dev Constructor function sets address of master copy contract.
    /// @param _masterCopy Master copy address.
    function Proxy(address _masterCopy)
        public
    {
        require(_masterCopy != 0);
        masterCopy = _masterCopy;
    }

    /// @dev Fallback function forwards all transactions and returns all received return data.
    function ()
        external
        payable
    {
        address _masterCopy = masterCopy;
        assembly {
            calldatacopy(0, 0, calldatasize())
            let success := delegatecall(not(0), _masterCopy, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch success
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }
}

// File: @gnosis.pm/util-contracts/contracts/Token.sol

/// Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
pragma solidity ^0.4.21;


/// @title Abstract token contract - Functions to be implemented by token contracts
contract Token {

    /*
     *  Events
     */
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);

    /*
     *  Public functions
     */
    function transfer(address to, uint value) public returns (bool);
    function transferFrom(address from, address to, uint value) public returns (bool);
    function approve(address spender, uint value) public returns (bool);
    function balanceOf(address owner) public view returns (uint);
    function allowance(address owner, address spender) public view returns (uint);
    function totalSupply() public view returns (uint);
}

// File: @gnosis.pm/util-contracts/contracts/StandardToken.sol

contract StandardTokenData {

    /*
     *  Storage
     */
    mapping (address => uint) balances;
    mapping (address => mapping (address => uint)) allowances;
    uint totalTokens;
}

/// @title Standard token contract with overflow protection
contract StandardToken is Token, StandardTokenData {
    using Math for *;

    /*
     *  Public functions
     */
    /// @dev Transfers sender's tokens to a given address. Returns success
    /// @param to Address of token receiver
    /// @param value Number of tokens to transfer
    /// @return Was transfer successful?
    function transfer(address to, uint value)
        public
        returns (bool)
    {
        if (   !balances[msg.sender].safeToSub(value)
            || !balances[to].safeToAdd(value))
            return false;
        balances[msg.sender] -= value;
        balances[to] += value;
        emit Transfer(msg.sender, to, value);
        return true;
    }

    /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success
    /// @param from Address from where tokens are withdrawn
    /// @param to Address to where tokens are sent
    /// @param value Number of tokens to transfer
    /// @return Was transfer successful?
    function transferFrom(address from, address to, uint value)
        public
        returns (bool)
    {
        if (   !balances[from].safeToSub(value)
            || !allowances[from][msg.sender].safeToSub(value)
            || !balances[to].safeToAdd(value))
            return false;
        balances[from] -= value;
        allowances[from][msg.sender] -= value;
        balances[to] += value;
        emit Transfer(from, to, value);
        return true;
    }

    /// @dev Sets approved amount of tokens for spender. Returns success
    /// @param spender Address of allowed account
    /// @param value Number of approved tokens
    /// @return Was approval successful?
    function approve(address spender, uint value)
        public
        returns (bool)
    {
        allowances[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    /// @dev Returns number of allowed tokens for given address
    /// @param owner Address of token owner
    /// @param spender Address of token spender
    /// @return Remaining allowance for spender
    function allowance(address owner, address spender)
        public
        view
        returns (uint)
    {
        return allowances[owner][spender];
    }

    /// @dev Returns number of tokens owned by given address
    /// @param owner Address of token owner
    /// @return Balance of owner
    function balanceOf(address owner)
        public
        view
        returns (uint)
    {
        return balances[owner];
    }

    /// @dev Returns total supply of tokens
    /// @return Total supply
    function totalSupply()
        public
        view
        returns (uint)
    {
        return totalTokens;
    }
}

// File: contracts/TokenFRT.sol

/// @title Standard token contract with overflow protection
contract TokenFRT is StandardToken {
    string public constant symbol = "MGN";
    string public constant name = "Magnolia Token";
    uint8 public constant decimals = 18;

    struct unlockedToken {
        uint amountUnlocked;
        uint withdrawalTime;
    }

    /*
     *  Storage
     */

    address public owner;
    address public minter;

    // user => unlockedToken
    mapping (address => unlockedToken) public unlockedTokens;

    // user => amount
    mapping (address => uint) public lockedTokenBalances;

    /*
     *  Public functions
     */

    function TokenFRT(
        address _owner
    )
        public
    {
        require(_owner != address(0));
        owner = _owner;
    }

    // @dev allows to set the minter of Magnolia tokens once.
    // @param   _minter the minter of the Magnolia tokens, should be the DX-proxy
    function updateMinter(
        address _minter
    )
        public
    {
        require(msg.sender == owner);
        require(_minter != address(0));

        minter = _minter;
    }

    // @dev the intention is to set the owner as the DX-proxy, once it is deployed
    // Then only an update of the DX-proxy contract after a 30 days delay could change the minter again.
    function updateOwner(   
        address _owner
    )
        public
    {
        require(msg.sender == owner);
        require(_owner != address(0));
        owner = _owner;
    }

    function mintTokens(
        address user,
        uint amount
    )
        public
    {
        require(msg.sender == minter);

        lockedTokenBalances[user] = add(lockedTokenBalances[user], amount);
        totalTokens = add(totalTokens, amount);
    }

    /// @dev Lock Token
    function lockTokens(
        uint amount
    )
        public
        returns (uint totalAmountLocked)
    {
        // Adjust amount by balance
        amount = min(amount, balances[msg.sender]);
        
        // Update state variables
        balances[msg.sender] = sub(balances[msg.sender], amount);
        lockedTokenBalances[msg.sender] = add(lockedTokenBalances[msg.sender], amount);

        // Get return variable
        totalAmountLocked = lockedTokenBalances[msg.sender];
    }

    function unlockTokens(
        uint amount
    )
        public
        returns (uint totalAmountUnlocked, uint withdrawalTime)
    {
        // Adjust amount by locked balances
        amount = min(amount, lockedTokenBalances[msg.sender]);

        if (amount > 0) {
            // Update state variables
            lockedTokenBalances[msg.sender] = sub(lockedTokenBalances[msg.sender], amount);
            unlockedTokens[msg.sender].amountUnlocked =  add(unlockedTokens[msg.sender].amountUnlocked, amount);
            unlockedTokens[msg.sender].withdrawalTime = now + 24 hours;
        }

        // Get return variables
        totalAmountUnlocked = unlockedTokens[msg.sender].amountUnlocked;
        withdrawalTime = unlockedTokens[msg.sender].withdrawalTime;
    }

    function withdrawUnlockedTokens()
        public
    {
        require(unlockedTokens[msg.sender].withdrawalTime < now);
        balances[msg.sender] = add(balances[msg.sender], unlockedTokens[msg.sender].amountUnlocked);
        unlockedTokens[msg.sender].amountUnlocked = 0;
    }

    function min(uint a, uint b) 
        public
        pure
        returns (uint)
    {
        if (a < b) {
            return a;
        } else {
            return b;
        }
    }
        /// @dev Returns whether an add operation causes an overflow
    /// @param a First addend
    /// @param b Second addend
    /// @return Did no overflow occur?
    function safeToAdd(uint a, uint b)
        public
        constant
        returns (bool)
    {
        return a + b >= a;
    }

    /// @dev Returns whether a subtraction operation causes an underflow
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Did no underflow occur?
    function safeToSub(uint a, uint b)
        public
        constant
        returns (bool)
    {
        return a >= b;
    }


    /// @dev Returns sum if no overflow occurred
    /// @param a First addend
    /// @param b Second addend
    /// @return Sum
    function add(uint a, uint b)
        public
        constant
        returns (uint)
    {
        require(safeToAdd(a, b));
        return a + b;
    }

    /// @dev Returns difference if no overflow occurred
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Difference
    function sub(uint a, uint b)
        public
        constant
        returns (uint)
    {
        require(safeToSub(a, b));
        return a - b;
    }
}

// File: @gnosis.pm/owl-token/contracts/TokenOWL.sol

contract TokenOWL is Proxied, StandardToken {
    using Math for *;

    string public constant name = "OWL Token";
    string public constant symbol = "OWL";
    uint8 public constant decimals = 18;

    struct masterCopyCountdownType {
        address masterCopy;
        uint timeWhenAvailable;
    }

    masterCopyCountdownType masterCopyCountdown;

    address public creator;
    address public minter;

    event Minted(address indexed to, uint256 amount);
    event Burnt(address indexed from, address indexed user, uint256 amount);

    modifier onlyCreator() {
        // R1
        require(msg.sender == creator);
        _;
    }
    /// @dev trickers the update process via the proxyMaster for a new address _masterCopy 
    /// updating is only possible after 30 days
    function startMasterCopyCountdown (
        address _masterCopy
     )
        public
        onlyCreator()
    {
        require(address(_masterCopy) != 0);

        // Update masterCopyCountdown
        masterCopyCountdown.masterCopy = _masterCopy;
        masterCopyCountdown.timeWhenAvailable = now + 30 days;
    }

     /// @dev executes the update process via the proxyMaster for a new address _masterCopy
    function updateMasterCopy()
        public
        onlyCreator()
    {   
        require(address(masterCopyCountdown.masterCopy) != 0);
        require(now >= masterCopyCountdown.timeWhenAvailable);

        // Update masterCopy
        masterCopy = masterCopyCountdown.masterCopy;
    }

    function getMasterCopy()
        public
        view
        returns (address)
    {
        return masterCopy;
    }

    /// @dev Set minter. Only the creator of this contract can call this.
    /// @param newMinter The new address authorized to mint this token
    function setMinter(address newMinter)
        public
        onlyCreator()
    {
        minter = newMinter;
    }


    /// @dev change owner/creator of the contract. Only the creator/owner of this contract can call this.
    /// @param newOwner The new address, which should become the owner
    function setNewOwner(address newOwner)
        public
        onlyCreator()
    {
        creator = newOwner;
    }

    /// @dev Mints OWL.
    /// @param to Address to which the minted token will be given
    /// @param amount Amount of OWL to be minted
    function mintOWL(address to, uint amount)
        public
    {
        require(minter != 0 && msg.sender == minter);
        balances[to] = balances[to].add(amount);
        totalTokens = totalTokens.add(amount);
        emit Minted(to, amount);
    }

    /// @dev Burns OWL.
    /// @param user Address of OWL owner
    /// @param amount Amount of OWL to be burnt
    function burnOWL(address user, uint amount)
        public
    {
        allowances[user][msg.sender] = allowances[user][msg.sender].sub(amount);
        balances[user] = balances[user].sub(amount);
        totalTokens = totalTokens.sub(amount);
        emit Burnt(msg.sender, user, amount);
    }
}

// File: contracts/DutchExchange.sol

/// @title Dutch Exchange - exchange token pairs with the clever mechanism of the dutch auction
/// @author Alex Herrmann - <[email protected]>
/// @author Dominik Teiml - <[email protected]>

contract DutchExchange is Proxied {

    // The price is a rational number, so we need a concept of a fraction
    struct fraction {
        uint num;
        uint den;
    }

    uint constant WAITING_PERIOD_NEW_TOKEN_PAIR = 6 hours;
    uint constant WAITING_PERIOD_NEW_AUCTION = 10 minutes;
    uint constant WAITING_PERIOD_CHANGE_MASTERCOPY_OR_ORACLE = 30 days;
    uint constant AUCTION_START_WAITING_FOR_FUNDING = 1;

    address public newMasterCopy;
    // Time when new masterCopy is updatabale
    uint public masterCopyCountdown;

    // > Storage
    // auctioneer has the power to manage some variables
    address public auctioneer;
    // Ether ERC-20 token
    address public ethToken;
    // Price Oracle interface 
    PriceOracleInterface public ethUSDOracle;
    // Price Oracle interface proposals during update process
    PriceOracleInterface public newProposalEthUSDOracle;
    uint public oracleInterfaceCountdown;
    // Minimum required sell funding for adding a new token pair, in USD
    uint public thresholdNewTokenPair;
    // Minimum required sell funding for starting antoher auction, in USD
    uint public thresholdNewAuction;
    // Fee reduction token (magnolia, ERC-20 token)
    TokenFRT public frtToken;
    // Token for paying fees
    TokenOWL public owlToken;

    // mapping that stores the tokens, which are approved
    // Token => approved
    // Only tokens approved by auctioneer generate frtToken tokens
    mapping (address => bool) public approvedTokens;

    // For the following two mappings, there is one mapping for each token pair
    // The order which the tokens should be called is smaller, larger
    // These variables should never be called directly! They have getters below
    // Token => Token => index
    mapping (address => mapping (address => uint)) public latestAuctionIndices;
    // Token => Token => time
    mapping (address => mapping (address => uint)) public auctionStarts;

    // Token => Token => auctionIndex => price
    mapping (address => mapping (address => mapping (uint => fraction))) public closingPrices;

    // Token => Token => amount
    mapping (address => mapping (address => uint)) public sellVolumesCurrent;
    // Token => Token => amount
    mapping (address => mapping (address => uint)) public sellVolumesNext;
    // Token => Token => amount
    mapping (address => mapping (address => uint)) public buyVolumes;

    // Token => user => amount
    // balances stores a user's balance in the DutchX
    mapping (address => mapping (address => uint)) public balances;

    // Token => Token => auctionIndex => amount
    mapping (address => mapping (address => mapping (uint => uint))) public extraTokens;

    // Token => Token =>  auctionIndex => user => amount
    mapping (address => mapping (address => mapping (uint => mapping (address => uint)))) public sellerBalances;
    mapping (address => mapping (address => mapping (uint => mapping (address => uint)))) public buyerBalances;
    mapping (address => mapping (address => mapping (uint => mapping (address => uint)))) public claimedAmounts;

    // > Modifiers
    modifier onlyAuctioneer() {
        // Only allows auctioneer to proceed
        // R1
        require(msg.sender == auctioneer);
        _;
    }

    /// @dev Constructor-Function creates exchange
    /// @param _frtToken - address of frtToken ERC-20 token
    /// @param _owlToken - address of owlToken ERC-20 token
    /// @param _auctioneer - auctioneer for managing interfaces
    /// @param _ethToken - address of ETH ERC-20 token
    /// @param _ethUSDOracle - address of the oracle contract for fetching feeds
    /// @param _thresholdNewTokenPair - Minimum required sell funding for adding a new token pair, in USD
    function setupDutchExchange(
        TokenFRT _frtToken,
        TokenOWL _owlToken,
        address _auctioneer, 
        address _ethToken,
        PriceOracleInterface _ethUSDOracle,
        uint _thresholdNewTokenPair,
        uint _thresholdNewAuction
    )
        public
    {
        // Make sure contract hasn't been initialised
        require(ethToken == 0);

        // Validates inputs
        require(address(_owlToken) != address(0));
        require(address(_frtToken) != address(0));
        require(_auctioneer != 0);
        require(_ethToken != 0);
        require(address(_ethUSDOracle) != address(0));

        frtToken = _frtToken;
        owlToken = _owlToken;
        auctioneer = _auctioneer;
        ethToken = _ethToken;
        ethUSDOracle = _ethUSDOracle;
        thresholdNewTokenPair = _thresholdNewTokenPair;
        thresholdNewAuction = _thresholdNewAuction;
    }

    function updateAuctioneer(
        address _auctioneer
    )
        public
        onlyAuctioneer
    {
        require(_auctioneer != address(0));
        auctioneer = _auctioneer;
    }

    function initiateEthUsdOracleUpdate(
        PriceOracleInterface _ethUSDOracle
    )
        public
        onlyAuctioneer
    {         
        require(address(_ethUSDOracle) != address(0));
        newProposalEthUSDOracle = _ethUSDOracle;
        oracleInterfaceCountdown = add(now, WAITING_PERIOD_CHANGE_MASTERCOPY_OR_ORACLE);
        NewOracleProposal(_ethUSDOracle);
    }

    function updateEthUSDOracle()
        public
        onlyAuctioneer
    {
        require(address(newProposalEthUSDOracle) != address(0));
        require(oracleInterfaceCountdown < now);
        ethUSDOracle = newProposalEthUSDOracle;
        newProposalEthUSDOracle = PriceOracleInterface(0);
    }

    function updateThresholdNewTokenPair(
        uint _thresholdNewTokenPair
    )
        public
        onlyAuctioneer
    {
        thresholdNewTokenPair = _thresholdNewTokenPair;
    }

    function updateThresholdNewAuction(
        uint _thresholdNewAuction
    )
        public
        onlyAuctioneer
    {
        thresholdNewAuction = _thresholdNewAuction;
    }

    function updateApprovalOfToken(
        address[] token,
        bool approved
    )
        public
        onlyAuctioneer
     {  
        for(uint i = 0; i < token.length; i++) {
            approvedTokens[token[i]] = approved;
            Approval(token[i], approved);
        }
     }

     function startMasterCopyCountdown (
        address _masterCopy
     )
        public
        onlyAuctioneer
    {
        require(_masterCopy != address(0));

        // Update masterCopyCountdown
        newMasterCopy = _masterCopy;
        masterCopyCountdown = add(now, WAITING_PERIOD_CHANGE_MASTERCOPY_OR_ORACLE);
        NewMasterCopyProposal(_masterCopy);
    }

    function updateMasterCopy()
        public
        onlyAuctioneer
    {
        require(newMasterCopy != address(0));
        require(now >= masterCopyCountdown);

        // Update masterCopy
        masterCopy = newMasterCopy;
        newMasterCopy = address(0);
    }

    /// @param initialClosingPriceNum initial price will be 2 * initialClosingPrice. This is its numerator
    /// @param initialClosingPriceDen initial price will be 2 * initialClosingPrice. This is its denominator
    function addTokenPair(
        address token1,
        address token2,
        uint token1Funding,
        uint token2Funding,
        uint initialClosingPriceNum,
        uint initialClosingPriceDen 
    )
        public
    {
        // R1
        require(token1 != token2);

        // R2
        require(initialClosingPriceNum != 0);

        // R3
        require(initialClosingPriceDen != 0);

        // R4
        require(getAuctionIndex(token1, token2) == 0);

        // R5: to prevent overflow
        require(initialClosingPriceNum < 10 ** 18);

        // R6
        require(initialClosingPriceDen < 10 ** 18);

        setAuctionIndex(token1, token2);

        token1Funding = min(token1Funding, balances[token1][msg.sender]);
        token2Funding = min(token2Funding, balances[token2][msg.sender]);

        // R7
        require(token1Funding < 10 ** 30);

        // R8
        require(token2Funding < 10 ** 30);

        uint fundedValueUSD;
        uint ethUSDPrice = ethUSDOracle.getUSDETHPrice();

        // Compute fundedValueUSD
        address ethTokenMem = ethToken;
        if (token1 == ethTokenMem) {
            // C1
            // MUL: 10^30 * 10^6 = 10^36
            fundedValueUSD = mul(token1Funding, ethUSDPrice);
        } else if (token2 == ethTokenMem) {
            // C2
            // MUL: 10^30 * 10^6 = 10^36
            fundedValueUSD = mul(token2Funding, ethUSDPrice);
        } else {
            // C3: Neither token is ethToken
            fundedValueUSD = calculateFundedValueTokenToken(token1, token2, 
                token1Funding, token2Funding, ethTokenMem, ethUSDPrice);
        }

        // R5
        require(fundedValueUSD >= thresholdNewTokenPair);

        // Save prices of opposite auctions
        closingPrices[token1][token2][0] = fraction(initialClosingPriceNum, initialClosingPriceDen);
        closingPrices[token2][token1][0] = fraction(initialClosingPriceDen, initialClosingPriceNum);

        // Split into two fns because of 16 local-var cap
        addTokenPairSecondPart(token1, token2, token1Funding, token2Funding);
    }

    function calculateFundedValueTokenToken(
        address token1,
        address token2,
        uint token1Funding,
        uint token2Funding,
        address ethTokenMem,
        uint ethUSDPrice
    )
        internal
        view
        returns (uint fundedValueUSD)
    {
        // We require there to exist ethToken-Token auctions
        // R3.1
        require(getAuctionIndex(token1, ethTokenMem) > 0);

        // R3.2
        require(getAuctionIndex(token2, ethTokenMem) > 0);

        // Price of Token 1
        uint priceToken1Num;
        uint priceToken1Den;
        (priceToken1Num, priceToken1Den) = getPriceOfTokenInLastAuction(token1);

        // Price of Token 2
        uint priceToken2Num;
        uint priceToken2Den;
        (priceToken2Num, priceToken2Den) = getPriceOfTokenInLastAuction(token2);

        // Compute funded value in ethToken and USD
        // 10^30 * 10^30 = 10^60
        uint fundedValueETH = add(mul(token1Funding, priceToken1Num) / priceToken1Den,
            token2Funding * priceToken2Num / priceToken2Den);

        fundedValueUSD = mul(fundedValueETH, ethUSDPrice);
    }

    function addTokenPairSecondPart(
        address token1,
        address token2,
        uint token1Funding,
        uint token2Funding
    )
        internal
    {
        balances[token1][msg.sender] = sub(balances[token1][msg.sender], token1Funding);
        balances[token2][msg.sender] = sub(balances[token2][msg.sender], token2Funding);

        // Fee mechanism, fees are added to extraTokens
        uint token1FundingAfterFee = settleFee(token1, token2, 1, token1Funding);
        uint token2FundingAfterFee = settleFee(token2, token1, 1, token2Funding);

        // Update other variables
        sellVolumesCurrent[token1][token2] = token1FundingAfterFee;
        sellVolumesCurrent[token2][token1] = token2FundingAfterFee;
        sellerBalances[token1][token2][1][msg.sender] = token1FundingAfterFee;
        sellerBalances[token2][token1][1][msg.sender] = token2FundingAfterFee;
        
        setAuctionStart(token1, token2, WAITING_PERIOD_NEW_TOKEN_PAIR);
        NewTokenPair(token1, token2);
    }

    function deposit(
        address tokenAddress,
        uint amount
    )
        public
        returns (uint)
    {
        // R1
        require(Token(tokenAddress).transferFrom(msg.sender, this, amount));

        uint newBal = add(balances[tokenAddress][msg.sender], amount);

        balances[tokenAddress][msg.sender] = newBal;

        NewDeposit(tokenAddress, amount);

        return newBal;
    }

    function withdraw(
        address tokenAddress,
        uint amount
    )
        public
        returns (uint)
    {
        uint usersBalance = balances[tokenAddress][msg.sender];
        amount = min(amount, usersBalance);

        // R1
        require(amount > 0);

        // R2
        require(Token(tokenAddress).transfer(msg.sender, amount));

        uint newBal = sub(usersBalance, amount);
        balances[tokenAddress][msg.sender] = newBal;

        NewWithdrawal(tokenAddress, amount);

        return newBal;
    }

    function postSellOrder(
        address sellToken,
        address buyToken,
        uint auctionIndex,
        uint amount
    )
        public
        returns (uint, uint)
    {
        // Note: if a user specifies auctionIndex of 0, it
        // means he is agnostic which auction his sell order goes into

        amount = min(amount, balances[sellToken][msg.sender]);

        // R1
        require(amount > 0);
        
        // R2
        uint latestAuctionIndex = getAuctionIndex(sellToken, buyToken);
        require(latestAuctionIndex > 0);
      
        // R3
        uint auctionStart = getAuctionStart(sellToken, buyToken);
        if (auctionStart == AUCTION_START_WAITING_FOR_FUNDING || auctionStart > now) {
            // C1: We are in the 10 minute buffer period
            // OR waiting for an auction to receive sufficient sellVolume
            // Auction has already cleared, and index has been incremented
            // sell order must use that auction index
            // R1.1
            if (auctionIndex == 0) {
                auctionIndex = latestAuctionIndex;
            } else {
                require(auctionIndex == latestAuctionIndex);
            }

            // R1.2
            require(add(sellVolumesCurrent[sellToken][buyToken], amount) < 10 ** 30);
        } else {
            // C2
            // R2.1: Sell orders must go to next auction
            if (auctionIndex == 0) {
                auctionIndex = latestAuctionIndex + 1;
            } else {
                require(auctionIndex == latestAuctionIndex + 1);
            }

            // R2.2
            require(add(sellVolumesNext[sellToken][buyToken], amount) < 10 ** 30);
        }

        // Fee mechanism, fees are added to extraTokens
        uint amountAfterFee = settleFee(sellToken, buyToken, auctionIndex, amount);

        // Update variables
        balances[sellToken][msg.sender] = sub(balances[sellToken][msg.sender], amount);
        uint newSellerBal = add(sellerBalances[sellToken][buyToken][auctionIndex][msg.sender], amountAfterFee);
        sellerBalances[sellToken][buyToken][auctionIndex][msg.sender] = newSellerBal;

        if (auctionStart == AUCTION_START_WAITING_FOR_FUNDING || auctionStart > now) {
            // C1
            uint sellVolumeCurrent = sellVolumesCurrent[sellToken][buyToken];
            sellVolumesCurrent[sellToken][buyToken] = add(sellVolumeCurrent, amountAfterFee);
        } else {
            // C2
            uint sellVolumeNext = sellVolumesNext[sellToken][buyToken];
            sellVolumesNext[sellToken][buyToken] = add(sellVolumeNext, amountAfterFee);
        }

        if (auctionStart == AUCTION_START_WAITING_FOR_FUNDING) {
            scheduleNextAuction(sellToken, buyToken);
        }

        NewSellOrder(sellToken, buyToken, msg.sender, auctionIndex, amountAfterFee);

        return (auctionIndex, newSellerBal);
    }

    function postBuyOrder(
        address sellToken,
        address buyToken,
        uint auctionIndex,
        uint amount
    )
        public
        returns (uint)
    {
        // R1: auction must not have cleared
        require(closingPrices[sellToken][buyToken][auctionIndex].den == 0);

        uint auctionStart = getAuctionStart(sellToken, buyToken);

        // R2
        require(auctionStart <= now);

        // R4
        require(auctionIndex == getAuctionIndex(sellToken, buyToken));
        
        // R5: auction must not be in waiting period
        require(auctionStart > AUCTION_START_WAITING_FOR_FUNDING);
        
        // R6: auction must be funded
        require(sellVolumesCurrent[sellToken][buyToken] > 0);
        
        uint buyVolume = buyVolumes[sellToken][buyToken];
        amount = min(amount, balances[buyToken][msg.sender]);

        // R7
        require(add(buyVolume, amount) < 10 ** 30);
        
        // Overbuy is when a part of a buy order clears an auction
        // In that case we only process the part before the overbuy
        // To calculate overbuy, we first get current price
        uint sellVolume = sellVolumesCurrent[sellToken][buyToken];

        uint num;
        uint den;
        (num, den) = getCurrentAuctionPrice(sellToken, buyToken, auctionIndex);
        // 10^30 * 10^37 = 10^67
        uint outstandingVolume = atleastZero(int(mul(sellVolume, num) / den - buyVolume));

        uint amountAfterFee;
        if (amount < outstandingVolume) {
            if (amount > 0) {
                amountAfterFee = settleFee(buyToken, sellToken, auctionIndex, amount);
            }
        } else {
            amount = outstandingVolume;
            amountAfterFee = outstandingVolume;
        }

        // Here we could also use outstandingVolume or amountAfterFee, it doesn't matter
        if (amount > 0) {
            // Update variables
            balances[buyToken][msg.sender] = sub(balances[buyToken][msg.sender], amount);
            uint newBuyerBal = add(buyerBalances[sellToken][buyToken][auctionIndex][msg.sender], amountAfterFee);
            buyerBalances[sellToken][buyToken][auctionIndex][msg.sender] = newBuyerBal;
            buyVolumes[sellToken][buyToken] = add(buyVolumes[sellToken][buyToken], amountAfterFee);
            NewBuyOrder(sellToken, buyToken, msg.sender, auctionIndex, amountAfterFee);
        }

        // Checking for equality would suffice here. nevertheless:
        if (amount >= outstandingVolume) {
            // Clear auction
            clearAuction(sellToken, buyToken, auctionIndex, sellVolume);
        }

        return (newBuyerBal);
    }
    
    function claimSellerFunds(
        address sellToken,
        address buyToken,
        address user,
        uint auctionIndex
    )
        public
        // < (10^60, 10^61)
        returns (uint returned, uint frtsIssued)
    {
        closeTheoreticalClosedAuction(sellToken, buyToken, auctionIndex);
        uint sellerBalance = sellerBalances[sellToken][buyToken][auctionIndex][user];

        // R1
        require(sellerBalance > 0);

        // Get closing price for said auction
        fraction memory closingPrice = closingPrices[sellToken][buyToken][auctionIndex];
        uint num = closingPrice.num;
        uint den = closingPrice.den;

        // R2: require auction to have cleared
        require(den > 0);

        // Calculate return
        // < 10^30 * 10^30 = 10^60
        returned = mul(sellerBalance, num) / den;

        frtsIssued = issueFrts(sellToken, buyToken, returned, auctionIndex, sellerBalance, user);

        // Claim tokens
        sellerBalances[sellToken][buyToken][auctionIndex][user] = 0;
        if (returned > 0) {
            balances[buyToken][user] = add(balances[buyToken][user], returned);
        }
        NewSellerFundsClaim(sellToken, buyToken, user, auctionIndex, returned, frtsIssued);
    }

    function claimBuyerFunds(
        address sellToken,
        address buyToken,
        address user,
        uint auctionIndex
    )
        public
        returns (uint returned, uint frtsIssued)
    {
        closeTheoreticalClosedAuction(sellToken, buyToken, auctionIndex);
        
        uint num;
        uint den;
        (returned, num, den) = getUnclaimedBuyerFunds(sellToken, buyToken, user, auctionIndex);

        if (closingPrices[sellToken][buyToken][auctionIndex].den == 0) {
            // Auction is running
            claimedAmounts[sellToken][buyToken][auctionIndex][user] = add(claimedAmounts[sellToken][buyToken][auctionIndex][user], returned);
        } else {
            // Auction has closed
            // We DON'T want to check for returned > 0, because that would fail if a user claims
            // intermediate funds & auction clears in same block (he/she would not be able to claim extraTokens)

            // Assign extra sell tokens (this is possible only after auction has cleared,
            // because buyVolume could still increase before that)
            uint extraTokensTotal = extraTokens[sellToken][buyToken][auctionIndex];
            uint buyerBalance = buyerBalances[sellToken][buyToken][auctionIndex][user];

            // closingPrices.num represents buyVolume
            // < 10^30 * 10^30 = 10^60
            uint tokensExtra = mul(buyerBalance, extraTokensTotal) / closingPrices[sellToken][buyToken][auctionIndex].num;
            returned = add(returned, tokensExtra);

            frtsIssued = issueFrts(buyToken, sellToken, mul(buyerBalance, den) / num, auctionIndex, buyerBalance, user);

            // Auction has closed
            // Reset buyerBalances and claimedAmounts
            buyerBalances[sellToken][buyToken][auctionIndex][user] = 0;
            claimedAmounts[sellToken][buyToken][auctionIndex][user] = 0; 
        }

        // Claim tokens
        if (returned > 0) {
            balances[sellToken][user] = add(balances[sellToken][user], returned);
        }
        
        NewBuyerFundsClaim(sellToken, buyToken, user, auctionIndex, returned, frtsIssued);
    }

    function issueFrts(
        address primaryToken,
        address secondaryToken,
        uint x,
        uint auctionIndex,
        uint bal,
        address user
    )
        internal
        returns (uint frtsIssued)
    {
        if (approvedTokens[primaryToken] && approvedTokens[secondaryToken]) {
            address ethTokenMem = ethToken;
            // Get frts issued based on ETH price of returned tokens
            if (primaryToken == ethTokenMem) {
                frtsIssued = bal;
            } else if (secondaryToken == ethTokenMem) {
                // 10^30 * 10^39 = 10^66
                frtsIssued = x;
            } else {
                // Neither token is ethToken, so we use getHhistoricalPriceOracle()
                uint pastNum;
                uint pastDen;
                (pastNum, pastDen) = getPriceInPastAuction(primaryToken, ethTokenMem, auctionIndex - 1);
                // 10^30 * 10^35 = 10^65
                frtsIssued = mul(bal, pastNum) / pastDen;
            }

            if (frtsIssued > 0) {
                // Issue frtToken
                frtToken.mintTokens(user, frtsIssued);
            }
        }
    }

    //@dev allows to close possible theoretical closed markets
    //@param sellToken sellToken of an auction
    //@param buyToken buyToken of an auction 
    //@param index is the auctionIndex of the auction
    function closeTheoreticalClosedAuction(
        address sellToken,
        address buyToken,
        uint auctionIndex
    )
        public
    {
        if(auctionIndex == getAuctionIndex(buyToken, sellToken) && closingPrices[sellToken][buyToken][auctionIndex].num == 0) {
            uint buyVolume = buyVolumes[sellToken][buyToken];
            uint sellVolume = sellVolumesCurrent[sellToken][buyToken];
            uint num;
            uint den;
            (num, den) = getCurrentAuctionPrice(sellToken, buyToken, auctionIndex);
            // 10^30 * 10^37 = 10^67
            uint outstandingVolume = atleastZero(int(mul(sellVolume, num) / den - buyVolume));
            
            if(outstandingVolume == 0) {
                postBuyOrder(sellToken, buyToken, auctionIndex, 0);
            }
        }
    }

    /// @dev Claim buyer funds for one auction
    function getUnclaimedBuyerFunds(
        address sellToken,
        address buyToken,
        address user,
        uint auctionIndex
    )
        public
        view
        // < (10^67, 10^37)
        returns (uint unclaimedBuyerFunds, uint num, uint den)
    {
        // R1: checks if particular auction has ever run
        require(auctionIndex <= getAuctionIndex(sellToken, buyToken));

        (num, den) = getCurrentAuctionPrice(sellToken, buyToken, auctionIndex);

        if (num == 0) {
            // This should rarely happen - as long as there is >= 1 buy order,
            // auction will clear before price = 0. So this is just fail-safe
            unclaimedBuyerFunds = 0;
        } else {
            uint buyerBalance = buyerBalances[sellToken][buyToken][auctionIndex][user];
            // < 10^30 * 10^37 = 10^67
            unclaimedBuyerFunds = atleastZero(int(
                mul(buyerBalance, den) / num - 
                claimedAmounts[sellToken][buyToken][auctionIndex][user]
            ));
        }
    }

    function settleFee(
        address primaryToken,
        address secondaryToken,
        uint auctionIndex,
        uint amount
    )
        internal
        // < 10^30
        returns (uint amountAfterFee)
    {
        uint feeNum;
        uint feeDen;
        (feeNum, feeDen) = getFeeRatio(msg.sender);
        // 10^30 * 10^3 / 10^4 = 10^29
        uint fee = mul(amount, feeNum) / feeDen;

        if (fee > 0) {
            fee = settleFeeSecondPart(primaryToken, fee);
            
            uint usersExtraTokens = extraTokens[primaryToken][secondaryToken][auctionIndex + 1];
            extraTokens[primaryToken][secondaryToken][auctionIndex + 1] = add(usersExtraTokens, fee);

            Fee(primaryToken, secondaryToken, msg.sender, auctionIndex, fee);
        }
        
        amountAfterFee = sub(amount, fee);
    }

    function settleFeeSecondPart(
        address primaryToken,
        uint fee
    )
        internal
        returns (uint newFee)
    {
        // Allow user to reduce up to half of the fee with owlToken
        uint num;
        uint den;
        (num, den) = getPriceOfTokenInLastAuction(primaryToken);

        // Convert fee to ETH, then USD
        // 10^29 * 10^30 / 10^30 = 10^29
        uint feeInETH = mul(fee, num) / den;

        uint ethUSDPrice = ethUSDOracle.getUSDETHPrice();
        // 10^29 * 10^6 = 10^35
        // Uses 18 decimal places <> exactly as owlToken tokens: 10**18 owlToken == 1 USD 
        uint feeInUSD = mul(feeInETH, ethUSDPrice);
        uint amountOfowlTokenBurned = min(owlToken.allowance(msg.sender, this), feeInUSD / 2);
        amountOfowlTokenBurned = min(owlToken.balanceOf(msg.sender), amountOfowlTokenBurned);


        if (amountOfowlTokenBurned > 0) {
            owlToken.burnOWL(msg.sender, amountOfowlTokenBurned);
            // Adjust fee
            // 10^35 * 10^29 = 10^64
            uint adjustment = mul(amountOfowlTokenBurned, fee) / feeInUSD;
            newFee = sub(fee, adjustment);
        } else {
            newFee = fee;
        }
    }
    
    function getFeeRatio(
        address user
    )
        public
        view
        // feeRatio < 10^4
        returns (uint num, uint den)
    {
        uint t = frtToken.totalSupply();
        uint b = frtToken.lockedTokenBalances(user);

        if (b * 100000 < t || t == 0) {
            // 0.5%
            num = 1;
            den = 200;
        } else if (b * 10000 < t) {
            // 0.4%
            num = 1;
            den = 250;
        } else if (b * 1000 < t) {
            // 0.3%
            num = 3;
            den = 1000;
        } else if (b * 100 < t) {
            // 0.2%
            num = 1;
            den = 500;
        } else if (b * 10 < t) {
            // 0.1%
            num = 1;
            den = 1000;
        } else {
            // 0% 
            num = 0; 
            den = 1;
        }
    }

    /// @dev clears an Auction
    /// @param sellToken sellToken of the auction
    /// @param buyToken  buyToken of the auction
    /// @param auctionIndex of the auction to be cleared.
    function clearAuction(
        address sellToken,
        address buyToken,
        uint auctionIndex,
        uint sellVolume
    )
        internal
    {
        // Get variables
        uint buyVolume = buyVolumes[sellToken][buyToken];
        uint sellVolumeOpp = sellVolumesCurrent[buyToken][sellToken];
        uint closingPriceOppDen = closingPrices[buyToken][sellToken][auctionIndex].den;
        uint auctionStart = getAuctionStart(sellToken, buyToken);

        // Update closing price
        if (sellVolume > 0) {
            closingPrices[sellToken][buyToken][auctionIndex] = fraction(buyVolume, sellVolume);
        }

        // if (opposite is 0 auction OR price = 0 OR opposite auction cleared)
        // price = 0 happens if auction pair has been running for >= 24 hrs = 86400
        if (sellVolumeOpp == 0 || now >= auctionStart + 86400 || closingPriceOppDen > 0) {
            // Close auction pair
            uint buyVolumeOpp = buyVolumes[buyToken][sellToken];
            if (closingPriceOppDen == 0 && sellVolumeOpp > 0) {
                // Save opposite price
                closingPrices[buyToken][sellToken][auctionIndex] = fraction(buyVolumeOpp, sellVolumeOpp);
            }

            uint sellVolumeNext = sellVolumesNext[sellToken][buyToken];
            uint sellVolumeNextOpp = sellVolumesNext[buyToken][sellToken];

            // Update state variables for both auctions
            sellVolumesCurrent[sellToken][buyToken] = sellVolumeNext;
            if (sellVolumeNext > 0) {
                sellVolumesNext[sellToken][buyToken] = 0;
            }
            if (buyVolume > 0) {
                buyVolumes[sellToken][buyToken] = 0;
            }

            sellVolumesCurrent[buyToken][sellToken] = sellVolumeNextOpp;
            if (sellVolumeNextOpp > 0) {
                sellVolumesNext[buyToken][sellToken] = 0;
            }
            if (buyVolumeOpp > 0) {
                buyVolumes[buyToken][sellToken] = 0;
            }

            // Increment auction index
            setAuctionIndex(sellToken, buyToken);
            // Check if next auction can be scheduled
            scheduleNextAuction(sellToken, buyToken);
        }

        AuctionCleared(sellToken, buyToken, sellVolume, buyVolume, auctionIndex);
    }

    function scheduleNextAuction(
        address sellToken,
        address buyToken
    )
        internal
    {
        // Check if auctions received enough sell orders
        uint ethUSDPrice = ethUSDOracle.getUSDETHPrice();

        uint sellNum;
        uint sellDen;
        (sellNum, sellDen) = getPriceOfTokenInLastAuction(sellToken);

        uint buyNum;
        uint buyDen;
        (buyNum, buyDen) = getPriceOfTokenInLastAuction(buyToken);

        // We use current sell volume, because in clearAuction() we set
        // sellVolumesCurrent = sellVolumesNext before calling this function
        // (this is so that we don't need case work,
        // since it might also be called from postSellOrder())

        // < 10^30 * 10^31 * 10^6 = 10^67
        uint sellVolume = mul(mul(sellVolumesCurrent[sellToken][buyToken], sellNum), ethUSDPrice) / sellDen;
        uint sellVolumeOpp = mul(mul(sellVolumesCurrent[buyToken][sellToken], buyNum), ethUSDPrice) / buyDen;
        if (sellVolume >= thresholdNewAuction || sellVolumeOpp >= thresholdNewAuction) {
            // Schedule next auction
            setAuctionStart(sellToken, buyToken, WAITING_PERIOD_NEW_AUCTION);
        } else {
            resetAuctionStart(sellToken, buyToken);
        }
    }

    //@ dev returns price in units [token2]/[token1]
    //@ param token1 first token for price calculation
    //@ param token2 second token for price calculation
    //@ param auctionIndex index for the auction to get the averaged price from
    function getPriceInPastAuction(
        address token1,
        address token2,
        uint auctionIndex
    )
        public
        view
        // price < 10^31
        returns (uint num, uint den)
    {
        if (token1 == token2) {
            // C1
            num = 1;
            den = 1;
        } else {
            // C2
            // R2.1
            require(auctionIndex >= 0);


            // C3
            // R3.1
            require(auctionIndex <= getAuctionIndex(token1, token2));
            // auction still running

            uint i = 0;
            bool correctPair = false;
            fraction memory closingPriceToken1;
            fraction memory closingPriceToken2;

            while (!correctPair) {
                closingPriceToken2 = closingPrices[token2][token1][auctionIndex - i];
                closingPriceToken1 = closingPrices[token1][token2][auctionIndex - i];
                
                if (closingPriceToken1.num > 0 && closingPriceToken1.den > 0 || 
                    closingPriceToken2.num > 0 && closingPriceToken2.den > 0)
                {
                    correctPair = true;
                }
                i++;
            }

            // At this point at least one closing price is strictly positive
            // If only one is positive, we want to output that
            if (closingPriceToken1.num == 0 || closingPriceToken1.den == 0) {
                num = closingPriceToken2.den;
                den = closingPriceToken2.num;
            } else if (closingPriceToken2.num == 0 || closingPriceToken2.den == 0) {
                num = closingPriceToken1.num;
                den = closingPriceToken1.den;
            } else {
                // If both prices are positive, output weighted average
                num = closingPriceToken2.den + closingPriceToken1.num;
                den = closingPriceToken2.num + closingPriceToken1.den;
            }
        } 
    }

    /// @dev Gives best estimate for market price of a token in ETH of any price oracle on the Ethereum network
    /// @param token address of ERC-20 token
    /// @return Weighted average of closing prices of opposite Token-ethToken auctions, based on their sellVolume  
    function getPriceOfTokenInLastAuction(
        address token
    )
        public
        view
        // price < 10^31
        returns (uint num, uint den)
    {
        uint latestAuctionIndex = getAuctionIndex(token, ethToken);
        // getPriceInPastAuction < 10^30
        (num, den) = getPriceInPastAuction(token, ethToken, latestAuctionIndex - 1);
    }

    function getCurrentAuctionPrice(
        address sellToken,
        address buyToken,
        uint auctionIndex
    )
        public
        view
        // price < 10^37
        returns (uint num, uint den)
    {
        fraction memory closingPrice = closingPrices[sellToken][buyToken][auctionIndex];

        if (closingPrice.den != 0) {
            // Auction has closed
            (num, den) = (closingPrice.num, closingPrice.den);
        } else if (auctionIndex > getAuctionIndex(sellToken, buyToken)) {
            (num, den) = (0, 0);
        } else {
            // Auction is running
            uint pastNum;
            uint pastDen;
            (pastNum, pastDen) = getPriceInPastAuction(sellToken, buyToken, auctionIndex - 1);

            // If we're calling the function into an unstarted auction,
            // it will return the starting price of that auction
            uint timeElapsed = atleastZero(int(now - getAuctionStart(sellToken, buyToken)));

            // The numbers below are chosen such that
            // P(0 hrs) = 2 * lastClosingPrice, P(6 hrs) = lastClosingPrice, P(>=24 hrs) = 0

            // 10^5 * 10^31 = 10^36
            num = atleastZero(int((86400 - timeElapsed) * pastNum));
            // 10^6 * 10^31 = 10^37
            den = mul((timeElapsed + 43200), pastDen);

            if (mul(num, sellVolumesCurrent[sellToken][buyToken]) <= mul(den, buyVolumes[sellToken][buyToken])) {
                num = buyVolumes[sellToken][buyToken];
                den = sellVolumesCurrent[sellToken][buyToken];
            }
        }
    }

    function depositAndSell(
        address sellToken,
        address buyToken,
        uint amount
    )
        external
        returns (uint newBal, uint auctionIndex, uint newSellerBal)
    {
        newBal = deposit(sellToken, amount);
        (auctionIndex, newSellerBal) = postSellOrder(sellToken, buyToken, 0, amount);
    }

    function claimAndWithdraw(
        address sellToken,
        address buyToken,
        address user,
        uint auctionIndex,
        uint amount
    )
        external
        returns (uint returned, uint frtsIssued, uint newBal)
    {
        (returned, frtsIssued) = claimSellerFunds(sellToken, buyToken, user, auctionIndex);
        newBal = withdraw(buyToken, amount);
    }

    // > Helper fns
    function getTokenOrder(
        address token1,
        address token2
    )
        public
        pure
        returns (address, address)
    {
        if (token2 < token1) {
            (token1, token2) = (token2, token1);
        }

        return (token1, token2);
    }

    function setAuctionStart(
        address token1,
        address token2,
        uint value
    )
        internal
    {
        (token1, token2) = getTokenOrder(token1, token2);        
        uint auctionStart = now + value;
        uint auctionIndex = latestAuctionIndices[token1][token2];
        auctionStarts[token1][token2] = auctionStart;
        AuctionStartScheduled(token1, token2, auctionIndex, auctionStart);
    }

    function resetAuctionStart(
        address token1,
        address token2
    )
        internal
    {
        (token1, token2) = getTokenOrder(token1, token2);
        if (auctionStarts[token1][token2] != AUCTION_START_WAITING_FOR_FUNDING) {
            auctionStarts[token1][token2] = AUCTION_START_WAITING_FOR_FUNDING;
        }
    }

    function getAuctionStart(
        address token1,
        address token2
    )
        public
        view
        returns (uint auctionStart)
    {
        (token1, token2) = getTokenOrder(token1, token2);
        auctionStart = auctionStarts[token1][token2];
    }

    function setAuctionIndex(
        address token1,
        address token2
    )
        internal
    {
        (token1, token2) = getTokenOrder(token1, token2);
        latestAuctionIndices[token1][token2] += 1;
    }


    function getAuctionIndex(
        address token1,
        address token2
    )
        public
        view
        returns (uint auctionIndex) 
    {
        (token1, token2) = getTokenOrder(token1, token2);
        auctionIndex = latestAuctionIndices[token1][token2];
    }

    // > Math fns
    function min(uint a, uint b) 
        public
        pure
        returns (uint)
    {
        if (a < b) {
            return a;
        } else {
            return b;
        }
    }

    function atleastZero(int a)
        public
        pure
        returns (uint)
    {
        if (a < 0) {
            return 0;
        } else {
            return uint(a);
        }
    }
    /// @dev Returns whether an add operation causes an overflow
    /// @param a First addend
    /// @param b Second addend
    /// @return Did no overflow occur?
    function safeToAdd(uint a, uint b)
        public
        pure
        returns (bool)
    {
        return a + b >= a;
    }

    /// @dev Returns whether a subtraction operation causes an underflow
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Did no underflow occur?
    function safeToSub(uint a, uint b)
        public
        pure
        returns (bool)
    {
        return a >= b;
    }

    /// @dev Returns whether a multiply operation causes an overflow
    /// @param a First factor
    /// @param b Second factor
    /// @return Did no overflow occur?
    function safeToMul(uint a, uint b)
        public
        pure
        returns (bool)
    {
        return b == 0 || a * b / b == a;
    }

    /// @dev Returns sum if no overflow occurred
    /// @param a First addend
    /// @param b Second addend
    /// @return Sum
    function add(uint a, uint b)
        public
        pure
        returns (uint)
    {
        require(safeToAdd(a, b));
        return a + b;
    }

    /// @dev Returns difference if no overflow occurred
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Difference
    function sub(uint a, uint b)
        public
        pure
        returns (uint)
    {
        require(safeToSub(a, b));
        return a - b;
    }

    /// @dev Returns product if no overflow occurred
    /// @param a First factor
    /// @param b Second factor
    /// @return Product
    function mul(uint a, uint b)
        public
        pure
        returns (uint)
    {
        require(safeToMul(a, b));
        return a * b;
    }

    function getRunningTokenPairs(
        address[] tokens
    )
        external
        view
        returns (address[] tokens1, address[] tokens2)
    {
        uint arrayLength;

        for (uint k = 0; k < tokens.length - 1; k++) {
            for (uint l = k + 1; l < tokens.length; l++) {
                if (getAuctionIndex(tokens[k], tokens[l]) > 0) {
                    arrayLength++;
                }
            }
        }

        tokens1 = new address[](arrayLength);
        tokens2 = new address[](arrayLength);

        uint h;

        for (uint i = 0; i < tokens.length - 1; i++) {
            for (uint j = i + 1; j < tokens.length; j++) {
                if (getAuctionIndex(tokens[i], tokens[j]) > 0) {
                    tokens1[h] = tokens[i];
                    tokens2[h] = tokens[j];
                    h++;
                }
            }
        }
    }
    
    //@dev for quick overview of possible sellerBalances to calculate the possible withdraw tokens
    //@param auctionSellToken is the sellToken defining an auctionPair
    //@param auctionBuyToken is the buyToken defining an auctionPair
    //@param user is the user who wants to his tokens
    //@param lastNAuctions how many auctions will be checked. 0 means all
    //@returns returns sellbal for all indices for all tokenpairs 
    function getIndicesWithClaimableTokensForSellers(
        address auctionSellToken,
        address auctionBuyToken,
        address user,
        uint lastNAuctions
    )
        external
        view
        returns(uint[] indices, uint[] usersBalances)
    {
        uint runningAuctionIndex = getAuctionIndex(auctionSellToken, auctionBuyToken);

        uint arrayLength;
        
        uint startingIndex = lastNAuctions == 0 ? 1 : runningAuctionIndex - lastNAuctions + 1;

        for (uint j = startingIndex; j <= runningAuctionIndex; j++) {
            if (sellerBalances[auctionSellToken][auctionBuyToken][j][user] > 0) {
                arrayLength++;
            }
        }

        indices = new uint[](arrayLength);
        usersBalances = new uint[](arrayLength);

        uint k;

        for (uint i = startingIndex; i <= runningAuctionIndex; i++) {
            if (sellerBalances[auctionSellToken][auctionBuyToken][i][user] > 0) {
                indices[k] = i;
                usersBalances[k] = sellerBalances[auctionSellToken][auctionBuyToken][i][user];
                k++;
            }
        }
    }    

    //@dev for quick overview of current sellerBalances for a user
    //@param auctionSellTokens are the sellTokens defining an auctionPair
    //@param auctionBuyTokens are the buyTokens defining an auctionPair
    //@param user is the user who wants to his tokens
    function getSellerBalancesOfCurrentAuctions(
        address[] auctionSellTokens,
        address[] auctionBuyTokens,
        address user
    )
        external
        view
        returns (uint[])
    {
        uint length = auctionSellTokens.length;
        uint length2 = auctionBuyTokens.length;
        require(length == length2);

        uint[] memory sellersBalances = new uint[](length);

        for (uint i = 0; i < length; i++) {
            uint runningAuctionIndex = getAuctionIndex(auctionSellTokens[i], auctionBuyTokens[i]);
            sellersBalances[i] = sellerBalances[auctionSellTokens[i]][auctionBuyTokens[i]][runningAuctionIndex][user];
        }

        return sellersBalances;
    }

    //@dev for quick overview of possible buyerBalances to calculate the possible withdraw tokens
    //@param auctionSellToken is the sellToken defining an auctionPair
    //@param auctionBuyToken is the buyToken defining an auctionPair
    //@param user is the user who wants to his tokens
    //@param lastNAuctions how many auctions will be checked. 0 means all
    //@returns returns sellbal for all indices for all tokenpairs 
    function getIndicesWithClaimableTokensForBuyers(
        address auctionSellToken,
        address auctionBuyToken,
        address user,
        uint lastNAuctions
    )
        external
        view
        returns(uint[] indices, uint[] usersBalances)
    {
        uint runningAuctionIndex = getAuctionIndex(auctionSellToken, auctionBuyToken);

        uint arrayLength;
        
        uint startingIndex = lastNAuctions == 0 ? 1 : runningAuctionIndex - lastNAuctions + 1;

        for (uint j = startingIndex; j <= runningAuctionIndex; j++) {
            if (buyerBalances[auctionSellToken][auctionBuyToken][j][user] > 0) {
                arrayLength++;
            }
        }

        indices = new uint[](arrayLength);
        usersBalances = new uint[](arrayLength);

        uint k;

        for (uint i = startingIndex; i <= runningAuctionIndex; i++) {
            if (buyerBalances[auctionSellToken][auctionBuyToken][i][user] > 0) {
                indices[k] = i;
                usersBalances[k] = buyerBalances[auctionSellToken][auctionBuyToken][i][user];
                k++;
            }
        }
    }    

    //@dev for quick overview of current sellerBalances for a user
    //@param auctionSellTokens are the sellTokens defining an auctionPair
    //@param auctionBuyTokens are the buyTokens defining an auctionPair
    //@param user is the user who wants to his tokens
    function getBuyerBalancesOfCurrentAuctions(
        address[] auctionSellTokens,
        address[] auctionBuyTokens,
        address user
    )
        external
        view
        returns (uint[])
    {
        uint length = auctionSellTokens.length;
        uint length2 = auctionBuyTokens.length;
        require(length == length2);

        uint[] memory buyersBalances = new uint[](length);

        for (uint i = 0; i < length; i++) {
            uint runningAuctionIndex = getAuctionIndex(auctionSellTokens[i], auctionBuyTokens[i]);
            buyersBalances[i] = buyerBalances[auctionSellTokens[i]][auctionBuyTokens[i]][runningAuctionIndex][user];
        }

        return buyersBalances;
    }

    //@dev for quick overview of approved Tokens
    //@param addressesToCheck are the ERC-20 token addresses to be checked whether they are approved
    function getApprovedAddressesOfList(
        address[] addressToCheck
    )
        external
        view
        returns (bool[])
    {
        uint length = addressToCheck.length;

        bool[] memory isApproved = new bool[](length);

        for (uint i = 0; i < length; i++) {
            isApproved[i] = approvedTokens[addressToCheck[i]];
        }

        return isApproved;
    }

    //@dev for multiple withdraws
    //@param auctionSellTokens are the sellTokens defining an auctionPair
    //@param auctionBuyTokens are the buyTokens defining an auctionPair
    //@param auctionIndices are the auction indices on which an token should be claimedAmounts
    //@param user is the user who wants to his tokens
    function claimTokensFromSeveralAuctionsAsSeller(
        address[] auctionSellTokens,
        address[] auctionBuyTokens,
        uint[] auctionIndices,
        address user
    )
        external
    {
        uint length = auctionSellTokens.length;
        uint length2 = auctionBuyTokens.length;
        require(length == length2);

        uint length3 = auctionIndices.length;
        require(length2 == length3);

        for (uint i = 0; i < length; i++)
            claimSellerFunds(auctionSellTokens[i], auctionBuyTokens[i], user, auctionIndices[i]);
    }
    //@dev for multiple withdraws
    //@param auctionSellTokens are the sellTokens defining an auctionPair
    //@param auctionBuyTokens are the buyTokens defining an auctionPair
    //@param auctionIndices are the auction indices on which an token should be claimedAmounts
    //@param user is the user who wants to his tokens
    function claimTokensFromSeveralAuctionsAsBuyer(
        address[] auctionSellTokens,
        address[] auctionBuyTokens,
        uint[] auctionIndices,
        address user
    )
        external
    {
        uint length = auctionSellTokens.length;
        uint length2 = auctionBuyTokens.length;
        require(length == length2);

        uint length3 = auctionIndices.length;
        require(length2 == length3);

        for (uint i = 0; i < length; i++)
            claimBuyerFunds(auctionSellTokens[i], auctionBuyTokens[i], user, auctionIndices[i]);
    }

    function getMasterCopy()
        external
        view 
        returns (address)
    {
        return masterCopy;
    }

    // > Events
    event NewDeposit(
         address indexed token,
         uint amount
    );

    event NewOracleProposal(
         PriceOracleInterface priceOracleInterface
    );


    event NewMasterCopyProposal(
         address newMasterCopy
    );

    event NewWithdrawal(
        address indexed token,
        uint amount
    );
    
    event NewSellOrder(
        address indexed sellToken,
        address indexed buyToken,
        address indexed user,
        uint auctionIndex,
        uint amount
    );

    event NewBuyOrder(
        address indexed sellToken,
        address indexed buyToken,
        address indexed user,
        uint auctionIndex,
        uint amount
    );

    event NewSellerFundsClaim(
        address indexed sellToken,
        address indexed buyToken,
        address indexed user,
        uint auctionIndex,
        uint amount,
        uint frtsIssued
    );

    event NewBuyerFundsClaim(
        address indexed sellToken,
        address indexed buyToken,
        address indexed user,
        uint auctionIndex,
        uint amount,
        uint frtsIssued
    );

    event NewTokenPair(
        address indexed sellToken,
        address indexed buyToken
    );

    event AuctionCleared(
        address indexed sellToken,
        address indexed buyToken,
        uint sellVolume,
        uint buyVolume,
        uint indexed auctionIndex
    );

    event Approval(
        address indexed token,
        bool approved
    );

    event AuctionStartScheduled(
        address indexed sellToken,
        address indexed buyToken,
        uint indexed auctionIndex,
        uint auctionStart
    );

    event Fee(
        address indexed primaryToken,
        address indexed secondarToken,
        address indexed user,
        uint auctionIndex,
        uint fee
    );
}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"token1","type":"address"},{"name":"token2","type":"address"}],"name":"getTokenOrder","outputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"auctionSellTokens","type":"address[]"},{"name":"auctionBuyTokens","type":"address[]"},{"name":"user","type":"address"}],"name":"getSellerBalancesOfCurrentAuctions","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"addressToCheck","type":"address[]"}],"name":"getApprovedAddressesOfList","outputs":[{"name":"","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMasterCopy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"user","type":"address"},{"name":"auctionIndex","type":"uint256"},{"name":"amount","type":"uint256"}],"name":"claimAndWithdraw","outputs":[{"name":"returned","type":"uint256"},{"name":"frtsIssued","type":"uint256"},{"name":"newBal","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"masterCopyCountdown","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"auctionStarts","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token1","type":"address"},{"name":"token2","type":"address"}],"name":"getAuctionIndex","outputs":[{"name":"auctionIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"updateMasterCopy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"int256"}],"name":"atleastZero","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"address"}],"name":"buyerBalances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ethUSDOracle","type":"address"}],"name":"initiateEthUsdOracleUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"deposit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token1","type":"address"},{"name":"token2","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"getPriceInPastAuction","outputs":[{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeToAdd","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"auctionIndex","type":"uint256"},{"name":"amount","type":"uint256"}],"name":"postSellOrder","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"auctionIndex","type":"uint256"},{"name":"amount","type":"uint256"}],"name":"postBuyOrder","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"auctioneer","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"user","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"claimSellerFunds","outputs":[{"name":"returned","type":"uint256"},{"name":"frtsIssued","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"amount","type":"uint256"}],"name":"depositAndSell","outputs":[{"name":"newBal","type":"uint256"},{"name":"auctionIndex","type":"uint256"},{"name":"newSellerBal","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address[]"},{"name":"approved","type":"bool"}],"name":"updateApprovalOfToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"approvedTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thresholdNewTokenPair","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newMasterCopy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ethUSDOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"add","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"auctionSellTokens","type":"address[]"},{"name":"auctionBuyTokens","type":"address[]"},{"name":"auctionIndices","type":"uint256[]"},{"name":"user","type":"address"}],"name":"claimTokensFromSeveralAuctionsAsSeller","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_auctioneer","type":"address"}],"name":"updateAuctioneer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"min","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"ethToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"closeTheoreticalClosedAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"frtToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"tokens","type":"address[]"}],"name":"getRunningTokenPairs","outputs":[{"name":"tokens1","type":"address[]"},{"name":"tokens2","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"address"}],"name":"claimedAmounts","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracleInterfaceCountdown","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"masterCopy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_frtToken","type":"address"},{"name":"_owlToken","type":"address"},{"name":"_auctioneer","type":"address"},{"name":"_ethToken","type":"address"},{"name":"_ethUSDOracle","type":"address"},{"name":"_thresholdNewTokenPair","type":"uint256"},{"name":"_thresholdNewAuction","type":"uint256"}],"name":"setupDutchExchange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"user","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"claimBuyerFunds","outputs":[{"name":"returned","type":"uint256"},{"name":"frtsIssued","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"sellVolumesNext","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"sellVolumesCurrent","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"sub","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"buyVolumes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"auctionSellTokens","type":"address[]"},{"name":"auctionBuyTokens","type":"address[]"},{"name":"user","type":"address"}],"name":"getBuyerBalancesOfCurrentAuctions","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"address"}],"name":"sellerBalances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_thresholdNewAuction","type":"uint256"}],"name":"updateThresholdNewAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"mul","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeToMul","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"newProposalEthUSDOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owlToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"auctionSellToken","type":"address"},{"name":"auctionBuyToken","type":"address"},{"name":"user","type":"address"},{"name":"lastNAuctions","type":"uint256"}],"name":"getIndicesWithClaimableTokensForBuyers","outputs":[{"name":"indices","type":"uint256[]"},{"name":"usersBalances","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"auctionSellTokens","type":"address[]"},{"name":"auctionBuyTokens","type":"address[]"},{"name":"auctionIndices","type":"uint256[]"},{"name":"user","type":"address"}],"name":"claimTokensFromSeveralAuctionsAsBuyer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token1","type":"address"},{"name":"token2","type":"address"}],"name":"getAuctionStart","outputs":[{"name":"auctionStart","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"user","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"getUnclaimedBuyerFunds","outputs":[{"name":"unclaimedBuyerFunds","type":"uint256"},{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_thresholdNewTokenPair","type":"uint256"}],"name":"updateThresholdNewTokenPair","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeToSub","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"token1","type":"address"},{"name":"token2","type":"address"},{"name":"token1Funding","type":"uint256"},{"name":"token2Funding","type":"uint256"},{"name":"initialClosingPriceNum","type":"uint256"},{"name":"initialClosingPriceDen","type":"uint256"}],"name":"addTokenPair","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"closingPrices","outputs":[{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"}],"name":"getFeeRatio","outputs":[{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"thresholdNewAuction","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"getPriceOfTokenInLastAuction","outputs":[{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"updateEthUSDOracle","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_masterCopy","type":"address"}],"name":"startMasterCopyCountdown","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"extraTokens","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"auctionSellToken","type":"address"},{"name":"auctionBuyToken","type":"address"},{"name":"user","type":"address"},{"name":"lastNAuctions","type":"uint256"}],"name":"getIndicesWithClaimableTokensForSellers","outputs":[{"name":"indices","type":"uint256[]"},{"name":"usersBalances","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"latestAuctionIndices","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"sellToken","type":"address"},{"name":"buyToken","type":"address"},{"name":"auctionIndex","type":"uint256"}],"name":"getCurrentAuctionPrice","outputs":[{"name":"num","type":"uint256"},{"name":"den","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"NewDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"priceOracleInterface","type":"address"}],"name":"NewOracleProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newMasterCopy","type":"address"}],"name":"NewMasterCopyProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"NewWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"NewSellOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"NewBuyOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"frtsIssued","type":"uint256"}],"name":"NewSellerFundsClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"frtsIssued","type":"uint256"}],"name":"NewBuyerFundsClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"}],"name":"NewTokenPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":false,"name":"sellVolume","type":"uint256"},{"indexed":false,"name":"buyVolume","type":"uint256"},{"indexed":true,"name":"auctionIndex","type":"uint256"}],"name":"AuctionCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"approved","type":"bool"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sellToken","type":"address"},{"indexed":true,"name":"buyToken","type":"address"},{"indexed":true,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"auctionStart","type":"uint256"}],"name":"AuctionStartScheduled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"primaryToken","type":"address"},{"indexed":true,"name":"secondarToken","type":"address"},{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"auctionIndex","type":"uint256"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"Fee","type":"event"}]

  Contract Creation Code Switch To Opcodes View
6060604052341561000f57600080fd5b6147a18061001e6000396000f3006060604052600436106103075763ffffffff60e060020a600035041662599e65811461030c57806301a521d61461035557806302ffc0b0146103de57806304e80e90146103fc57806306d58f2a1461042b5780630e7c0f80146104805780631006a41f146104a557806314584a9d146104ca5780632cef4dac146104ef5780633069046814610504578063377758071461051a578063403fbf541461054957806347e7ef24146105685780634bf8e7a21461058a5780634e30a66c146105ca57806359f96ae5146105f75780635e7f22c2146106225780635ec2c7bf1461064d57806365054e5514610660578063657a37ad1461068e57806365b0d711146106b65780636d1ea3fa146107095780636e6260fa146107285780636ea683601461073b578063706eb3ab1461074e578063771602f7146107615780637895dd211461077a578063796a8076146107bc5780637ae2b5c7146107db5780637bf1a627146107f4578063821b98f3146108075780638261eb1b1461082f57806384429579146108425780639fec8e96146108f9578063a48cef4a14610928578063a619486e1461093b578063acb103511461094e578063b02938501461098b578063b3c2083f146109b9578063b64c4905146109de578063b67d77c514610a03578063b8beafd614610a1c578063bc88adc414610a41578063c1a21bf314610a77578063c23f001f14610aa6578063c6af43f914610acb578063c8a4ac9c14610ae1578063cb10fa7614610afa578063cd04ccfc14610b13578063cd94a2a414610b26578063d3062b2414610b39578063d3cc8d1c14610b67578063dae595e514610ba9578063df6af7d114610bce578063e1c95bb914610bfc578063e31c71c414610c12578063e9f8cd7014610c2b578063ebcc0de114610c5c578063edd0b5cb14610c84578063ee93114c14610ca3578063f3fef3a314610cb6578063f41d97fc14610cd8578063f4279d1f14610cf7578063f625ee2814610d0a578063f79710fd14610d29578063f97ea6fc14610d51578063fac7abe314610d7f578063fdab1b7b14610da4575b600080fd5b341561031757600080fd5b610331600160a060020a0360043581169060243516610dcc565b604051600160a060020a039283168152911660208201526040908101905180910390f35b341561036057600080fd5b61038b6024600480358281019290820135918135918201910135600160a060020a0360443516610df5565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156103ca5780820151838201526020016103b2565b505050509050019250505060405180910390f35b34156103e957600080fd5b61038b6004803560248101910135610f49565b341561040757600080fd5b61040f610ff0565b604051600160a060020a03909116815260200160405180910390f35b341561043657600080fd5b61045c600160a060020a0360043581169060243581169060443516606435608435610fff565b60405180848152602001838152602001828152602001935050505060405180910390f35b341561048b57600080fd5b61049361102c565b60405190815260200160405180910390f35b34156104b057600080fd5b610493600160a060020a0360043581169060243516611032565b34156104d557600080fd5b610493600160a060020a036004358116906024351661104f565b34156104fa57600080fd5b61050261108a565b005b341561050f57600080fd5b6104936004356110ff565b341561052557600080fd5b610493600160a060020a036004358116906024358116906044359060643516611119565b341561055457600080fd5b610502600160a060020a0360043516611145565b341561057357600080fd5b610493600160a060020a03600435166024356111ed565b341561059557600080fd5b6105b2600160a060020a036004358116906024351660443561130c565b60405191825260208201526040908101905180910390f35b34156105d557600080fd5b6105e36004356024356114c6565b604051901515815260200160405180910390f35b341561060257600080fd5b6105b2600160a060020a03600435811690602435166044356064356114d4565b341561062d57600080fd5b610493600160a060020a0360043581169060243516604435606435611976565b341561065857600080fd5b61040f611e67565b341561066b57600080fd5b6105b2600160a060020a0360043581169060243581169060443516606435611e76565b341561069957600080fd5b61045c600160a060020a036004358116906024351660443561206d565b34156106c157600080fd5b610502600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965050505091351515915061209a9050565b341561071457600080fd5b6105e3600160a060020a0360043516612169565b341561073357600080fd5b61049361217e565b341561074657600080fd5b61040f612184565b341561075957600080fd5b61040f612193565b341561076c57600080fd5b6104936004356024356121a2565b341561078557600080fd5b6105026024600480358281019290820135918135808301929082013591604435918201910135600160a060020a03606435166121be565b34156107c757600080fd5b610502600160a060020a0360043516612259565b34156107e657600080fd5b6104936004356024356122b8565b34156107ff57600080fd5b61040f6122d0565b341561081257600080fd5b610502600160a060020a03600435811690602435166044356122df565b341561083a57600080fd5b61040f6123b3565b341561084d57600080fd5b61086060048035602481019101356123c2565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156108a457808201518382015260200161088c565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156108e35780820151838201526020016108cb565b5050505090500194505050505060405180910390f35b341561090457600080fd5b610493600160a060020a036004358116906024358116906044359060643516612582565b341561093357600080fd5b6104936125ae565b341561094657600080fd5b61040f6125b4565b341561095957600080fd5b610502600160a060020a036004358116906024358116906044358116906064358116906084351660a43560c4356125c3565b341561099657600080fd5b6105b2600160a060020a03600435811690602435811690604435166064356126b9565b34156109c457600080fd5b610493600160a060020a0360043581169060243516612b21565b34156109e957600080fd5b610493600160a060020a0360043581169060243516612b3e565b3415610a0e57600080fd5b610493600435602435612b5b565b3415610a2757600080fd5b610493600160a060020a0360043581169060243516612b78565b3415610a4c57600080fd5b61038b6024600480358281019290820135918135918201910135600160a060020a0360443516612b95565b3415610a8257600080fd5b610493600160a060020a036004358116906024358116906044359060643516612ca7565b3415610ab157600080fd5b610493600160a060020a0360043581169060243516612cd3565b3415610ad657600080fd5b610502600435612cf0565b3415610aec57600080fd5b610493600435602435612d10565b3415610b0557600080fd5b6105e3600435602435612d2c565b3415610b1e57600080fd5b61040f612d4e565b3415610b3157600080fd5b61040f612d5d565b3415610b4457600080fd5b610860600160a060020a0360043581169060243581169060443516606435612d6c565b3415610b7257600080fd5b6105026024600480358281019290820135918135808301929082013591604435918201910135600160a060020a0360643516612f08565b3415610bb457600080fd5b610493600160a060020a0360043581169060243516612f96565b3415610bd957600080fd5b61045c600160a060020a0360043581169060243581169060443516606435612fd1565b3415610c0757600080fd5b61050260043561308d565b3415610c1d57600080fd5b6105e36004356024356130ad565b3415610c3657600080fd5b610502600160a060020a036004358116906024351660443560643560843560a4356130b3565b3415610c6757600080fd5b6105b2600160a060020a036004358116906024351660443561333c565b3415610c8f57600080fd5b6105b2600160a060020a0360043516613366565b3415610cae57600080fd5b6104936134c9565b3415610cc157600080fd5b610493600160a060020a03600435166024356134cf565b3415610ce357600080fd5b6105b2600160a060020a03600435166135fb565b3415610d0257600080fd5b610502613643565b3415610d1557600080fd5b610502600160a060020a03600435166136b8565b3415610d3457600080fd5b610493600160a060020a0360043581169060243516604435613760565b3415610d5c57600080fd5b610860600160a060020a0360043581169060243581169060443516606435613783565b3415610d8a57600080fd5b610493600160a060020a036004358116906024351661391f565b3415610daf57600080fd5b6105b2600160a060020a036004358116906024351660443561393c565b60008083600160a060020a031683600160a060020a03161015610ded579192915b509192909150565b610dfd61474c565b600080610e0861474c565b879250859150600080838514610e1d57600080fd5b84604051805910610e2b5750595b90808252806020026020018201604052509250600091505b84821015610f3a57610e8d8b8b84818110610e5a57fe5b90506020020135600160a060020a03168a8a858181101515610e7857fe5b90506020020135600160a060020a031661104f565b9050601560008c8c85818110610e9f57fe5b90506020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008a8a858181101515610edf57fe5b600160a060020a0360209182029390930135831684528381019490945250604091820160009081208582528452828120918b1681529252902054838381518110610f2557fe5b60209081029091010152600190910190610e43565b50909998505050505050505050565b610f5161474c565b6000610f5b61474c565b839150600082604051805910610f6e5750595b90808252806020026020018201604052509150600090505b82811015610fe757600c6000878784818110610f9e57fe5b60209081029290920135600160a060020a03168352508101919091526040016000205460ff16828281518110610fd057fe5b911515602092830290910190910152600101610f86565b50949350505050565b600054600160a060020a031690565b600080600061101088888888611e76565b909350915061101f87856134cf565b9050955095509592505050565b60025481565b600e60209081526000928352604080842090915290825290205481565b600061105b8383610dcc565b600160a060020a039182166000908152600d602090815260408083209390941682529190915220549392505050565b60035433600160a060020a039081169116146110a557600080fd5b600154600160a060020a031615156110bc57600080fd5b6002544210156110cb57600080fd5b600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b60008082121561111157506000611114565b50805b919050565b601660209081526000948552604080862082529385528385208152918452828420909152825290205481565b60035433600160a060020a0390811691161461116057600080fd5b600160a060020a038116151561117557600080fd5b6006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790556111aa4262278d006121a2565b6007557f3f174cfd713408ca6e4620d1efcc241b23fc39aa7d4694bd98610d3384dc001c81604051600160a060020a03909116815260200160405180910390a150565b60008083600160a060020a03166323b872dd33308660405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561125157600080fd5b5af1151561125e57600080fd5b50505060405180519050151561127357600080fd5b600160a060020a03808516600090815260136020908152604080832033909416835292905220546112a490846121a2565b600160a060020a0380861660008181526013602090815260408083203390951683529390528290208390559192507f2cb77763bc1e8490c1a904905c4d74b4269919aca114464f4bb4d911e60de3649085905190815260200160405180910390a29392505050565b60008060008061131a61475e565b61132261475e565b87600160a060020a031689600160a060020a031614156113495760019550600194506114ba565b600087101561135757600080fd5b611361898961104f565b87111561136d57600080fd5b60009350600092505b82151561145b57600160a060020a038089166000908152600f60209081526040808320938d168352928152828220878b0383529052819020908051908101604090815282548252600190920154602080830191909152600160a060020a03808d166000908152600f8352848120918d168152908252838120888c03825290915282902090925090805190810160405281548152600190910154602082015291506000825111801561142b575060008260200151115b80611446575060008151118015611446575060008160200151115b1561145057600192505b600190930192611376565b8151158061146b57508160200151155b156114805780602001519550805194506114ba565b8051158061149057508060200151155b156114a55781519550816020015194506114ba565b81518160200151019550816020015181510194505b50505050935093915050565b808201829010155b92915050565b60008060008060008060008061153289601360008f600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020546122b8565b98506000891161154157600080fd5b61154b8c8c61104f565b95506000861161155a57600080fd5b6115648c8c612f96565b9450600185148061157457504285115b156115e25789151561158857859950611594565b89861461159457600080fd5b600160a060020a03808d166000908152601060209081526040808320938f16835292905220546c0c9f2c9cd04674edea40000000906115d3908b6121a2565b106115dd57600080fd5b61164c565b8915156115f457856001019950611603565b600186018a1461160357600080fd5b600160a060020a03808d166000908152601160209081526040808320938f16835292905220546c0c9f2c9cd04674edea4000000090611642908b6121a2565b1061164c57600080fd5b6116588c8c8c8c613acb565b600160a060020a03808e166000908152601360209081526040808320339094168352929052205490945061168c908a612b5b565b601360008e600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a031681526020019081526020016000208190555061175e601560008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002054856121a2565b925082601560008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c8152602001908152602001600020600033600160a060020a0316600160a060020a031681526020019081526020016000208190555060018514806117ef57504285115b1561187757600160a060020a03808d166000908152601060209081526040808320938f1683529290522054915061182682856121a2565b601060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020819055506118f5565b50600160a060020a03808c166000908152601160209081526040808320938e16835292905220546118a881856121a2565b601160008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020819055505b6001851415611908576119088c8c613bdd565b33600160a060020a03168b600160a060020a03168d600160a060020a03167f3681d6f6ad159bac260c32828859f6df545bbf841c6e70787bcf0acbc390512a8d8860405191825260208201526040908101905180910390a48983975097505b50505050505094509492505050565b600160a060020a038085166000908152600f60209081526040808320938716835292815282822085835290529081206001015481908190819081908190819081908190156119c357600080fd5b6119cd8d8d612f96565b9750428811156119dc57600080fd5b6119e68d8d61104f565b8b146119f157600080fd5b600188116119fe57600080fd5b6000601060008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002054111515611a5557600080fd5b601260008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020549650611af28a601360008f600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020546122b8565b99506c0c9f2c9cd04674edea40000000611b0c888c6121a2565b10611b1657600080fd5b601060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020549550611b6c8d8d8d61393c565b9095509350611b908785611b808989612d10565b811515611b8957fe5b04036110ff565b9250828a1015611bb75760008a1115611bb257611baf8c8e8d8d613acb565b91505b611bbe565b8299508291505b60008a1115611e4457600160a060020a03808d1660009081526013602090815260408083203390941683529290522054611bf8908b612b5b565b601360008e600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550611cca601660008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002054836121a2565b905080601660008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550611d9f601260008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002054836121a2565b601260008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a031681526020019081526020016000208190555033600160a060020a03168c600160a060020a03168e600160a060020a03167ff1751a362067564d5feb9ed26f1898bb14c17e1254e3724d454bc2ae80195c258e8660405191825260208201526040908101905180910390a45b828a10611e5757611e578d8d8d89613d20565b9c9b505050505050505050505050565b600354600160a060020a031681565b6000806000611e8361475e565b600080611e918a8a896122df565b600160a060020a03808b1660009081526015602090815260408083208d8516845282528083208b84528252808320938c1683529290529081205494508411611ed857600080fd5b600160a060020a03808b166000908152600f60209081526040808320938d1683529281528282208a835290528190209080519081016040528154815260019091015460208201529250825191508260200151905060008111611f3957600080fd5b80611f448584612d10565b811515611f4d57fe5b049550611f5e8a8a888a888d614073565b600160a060020a03808c1660009081526015602090815260408083208e8516845282528083208c84528252808320938d168352929052908120819055909550861115611ffb57600160a060020a03808a166000908152601360209081526040808320938c1683529290522054611fd490876121a2565b600160a060020a03808b166000908152601360209081526040808320938d16835292905220555b87600160a060020a031689600160a060020a03168b600160a060020a03167fa3ac9b53d029621ef95693b5f9b1d0b0da75029fe8530389271be02715e24c138a8a8a60405180848152602001838152602001828152602001935050505060405180910390a45050505094509492505050565b600080600061207c86856111ed565b925061208b86866000876114d4565b93979096509294509192505050565b60035460009033600160a060020a039081169116146120b857600080fd5b5060005b82518110156121645781600c60008584815181106120d657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff191691151591909117905582818151811061211457fe5b90602001906020020151600160a060020a03167fc091bf3abd3a42f670f8ad1a6ad5b849311210403e1d85d6ac31f43114d5ca6e83604051901515815260200160405180910390a26001016120bc565b505050565b600c6020526000908152604090205460ff1681565b60085481565b600154600160a060020a031681565b600554600160a060020a031681565b60006121ae83836114c6565b15156121b957600080fd5b500190565b85846000808284146121cf57600080fd5b8591508282146121de57600080fd5b5060005b8381101561224c576122428b8b838181106121f957fe5b90506020020135600160a060020a03168a8a84818110151561221757fe5b90506020020135600160a060020a0316878a8a86818110151561223657fe5b90506020020135611e76565b50506001016121e2565b5050505050505050505050565b60035433600160a060020a0390811691161461227457600080fd5b600160a060020a038116151561228957600080fd5b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000818310156122c95750816114ce565b50806114ce565b600454600160a060020a031681565b60008060008060006122f1878961104f565b8614801561232a5750600160a060020a038089166000908152600f60209081526040808320938b16835292815282822089835290522054155b156123a957600160a060020a038089166000818152601260209081526040808320948c1680845294825280832054938352601082528083209483529390529190912054909550935061237d88888861393c565b90935091506123918583611b808787612d10565b90508015156123a9576123a78888886000611976565b505b5050505050505050565b600a54600160a060020a031681565b6123ca61474c565b6123d261474c565b600080808080805b6000198901851015612447578460010193505b8884101561243c5760006124248b8b8881811061240657fe5b90506020020135600160a060020a03168c8c888181101515610e7857fe5b1115612431576001909501945b6001909301926123ed565b6001909401936123da565b856040518059106124555750595b90808252806020026020018201604052509750856040518059106124765750595b90808252806020026020018201604052509650600091505b60001989018210156125755750600181015b8881101561256a5760006124d78b8b858181106124b957fe5b90506020020135600160a060020a03168c8c858181101515610e7857fe5b1115612562578989838181106124e957fe5b90506020020135600160a060020a031688848151811061250557fe5b600160a060020a0390921660209283029091019091015289898281811061252857fe5b90506020020135600160a060020a031687848151811061254457fe5b600160a060020a039092166020928302909101909101526001909201915b6001016124a0565b60019091019061248e565b5050505050509250929050565b601760209081526000948552604080862082529385528385208152918452828420909152825290205481565b60075481565b600054600160a060020a031681565b600454600160a060020a0316156125d957600080fd5b600160a060020a03861615156125ee57600080fd5b600160a060020a038716151561260357600080fd5b600160a060020a038516151561261857600080fd5b600160a060020a038416151561262d57600080fd5b600160a060020a038316151561264257600080fd5b600a805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03998a1617909155600b8054821697891697909717909655600380548716958816959095179094556004805486169387169390931790925560058054909416941693909317909155600891909155600955565b60008060008060008060006126cf8b8b8a6122df565b6126db8b8b8b8b612fd1565b809650819750829950505050600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020600089815260200190815260200160002060010154600014156127cb57600160a060020a03808c1660009081526017602090815260408083208e8516845282528083208c84528252808320938d168352929052205461278e90886121a2565b600160a060020a03808d1660009081526017602090815260408083208f8516845282528083208d84528252808320938e1683529290522055612a4e565b601460008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a031681526020019081526020016000206000898152602001908152602001600020549250601660008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020600089815260200190815260200160002060008a600160a060020a0316600160a060020a03168152602001908152602001600020549150600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a0316815260200190815260200160002060008981526020019081526020016000206000015461290d8385612d10565b81151561291657fe5b04905061292387826121a2565b96506129478a8c876129358689612d10565b81151561293e57fe5b048b868e614073565b95506000601660008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002060008a815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020819055506000601760008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002060008a815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020819055505b6000871115612aae57600160a060020a03808c166000908152601360209081526040808320938d1683529290522054612a8790886121a2565b600160a060020a03808d166000908152601360209081526040808320938e16835292905220555b88600160a060020a03168a600160a060020a03168c600160a060020a03167f4d1c39fd1a9c74f88b9f90c7b439b7e5dc6f26b6ff280fd497fdec5c538aaf528b8b8b60405180848152602001838152602001828152602001935050505060405180910390a4505050505094509492505050565b601160209081526000928352604080842090915290825290205481565b601060209081526000928352604080842090915290825290205481565b6000612b6783836130ad565b1515612b7257600080fd5b50900390565b601260209081526000928352604080842090915290825290205481565b612b9d61474c565b600080612ba861474c565b879250859150600080838514612bbd57600080fd5b84604051805910612bcb5750595b90808252806020026020018201604052509250600091505b84821015610f3a57612bfa8b8b84818110610e5a57fe5b9050601660008c8c85818110612c0c57fe5b90506020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008a8a858181101515612c4c57fe5b600160a060020a0360209182029390930135831684528381019490945250604091820160009081208582528452828120918b1681529252902054838381518110612c9257fe5b60209081029091010152600190910190612be3565b601560209081526000948552604080862082529385528385208152918452828420909152825290205481565b601360209081526000928352604080842090915290825290205481565b60035433600160a060020a03908116911614612d0b57600080fd5b600955565b6000612d1c8383612d2c565b1515612d2757600080fd5b500290565b6000811580612d4757508282838502811515612d4457fe5b04145b9392505050565b600654600160a060020a031681565b600b54600160a060020a031681565b612d7461474c565b612d7c61474c565b600080600080600080612d8f8c8c61104f565b95508815612da257888603600101612da5565b60015b93508392505b858311612e0457600160a060020a03808d1660009081526016602090815260408083208f8516845282528083208784528252808320938e168352929052908120541115612df9576001909401935b600190920191612dab565b84604051805910612e125750595b9080825280602002602001820160405250975084604051805910612e335750595b908082528060200260200182016040525096508390505b85811161196757600160a060020a03808d1660009081526016602090815260408083208f8516845282528083208584528252808320938e168352929052908120541115612f005780888381518110612e9e57fe5b6020908102909101810191909152600160a060020a03808e1660009081526016835260408082208f8416835284528082208583528452808220928e16825291909252902054878381518110612eef57fe5b602090810290910101526001909101905b600101612e4a565b8584600080828414612f1957600080fd5b859150828214612f2857600080fd5b5060005b8381101561224c57612f8c8b8b83818110612f4357fe5b90506020020135600160a060020a03168a8a848181101515612f6157fe5b90506020020135600160a060020a0316878a8a868181101515612f8057fe5b905060200201356126b9565b5050600101612f2c565b6000612fa28383610dcc565b600160a060020a039182166000908152600e602090815260408083209390941682529190915220549392505050565b600080600080612fe1888861104f565b851115612fed57600080fd5b612ff888888761393c565b909350915082151561300d5760009350613082565b50600160a060020a0380881660008181526016602090815260408083208b86168085529083528184208a85528352818420958b16808552958352818420549484526017835281842090845282528083208984528252808320948352939052919091205461307f9084611b808486612d10565b93505b509450945094915050565b60035433600160a060020a039081169116146130a857600080fd5b600855565b90101590565b60008080600160a060020a0389811690891614156130d057600080fd5b8415156130dc57600080fd5b8315156130e857600080fd5b6130f2898961104f565b156130fc57600080fd5b670de0b6b3a7640000851061311057600080fd5b670de0b6b3a7640000841061312457600080fd5b61312e89896141a9565b600160a060020a03808a16600090815260136020908152604080832033909416835292905220546131609088906122b8565b600160a060020a03808a16600090815260136020908152604080832033909416835292905220549097506131959087906122b8565b95506c0c9f2c9cd04674edea4000000087106131b057600080fd5b6c0c9f2c9cd04674edea4000000086106131c957600080fd5b600554600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561320857600080fd5b5af1151561321557600080fd5b5050506040518051600454909350600160a060020a0390811692508a16821415905061324c576132458783612d10565b9250613281565b80600160a060020a031688600160a060020a03161415613270576132458683612d10565b61327e8989898985876141e5565b92505b60085483101561329057600080fd5b6040805190810160409081528682526020808301879052600160a060020a03808d166000908152600f8352838120918d16815290825282812081805290915220815181556020820151600190910155506040805190810160409081528582526020808301889052600160a060020a03808c166000908152600f8352838120918e16815290825282812081805290915220815181556020820151600190910155506123a78989898961426d565b600f6020908152600093845260408085208252928452828420905282529020805460019091015482565b600a54600090819081908190600160a060020a03166318160ddd6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133ae57600080fd5b5af115156133bb57600080fd5b5050506040518051600a54909350600160a060020a03169050638b525d0c8660405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561341857600080fd5b5af1151561342557600080fd5b5050506040518051905090508181620186a0021080613442575081155b15613454576001935060c892506134c2565b818161271002101561346d576001935060fa92506134c2565b81816103e802101561348757600393506103e892506134c2565b818160640210156134a057600193506101f492506134c2565b8181600a0210156134b957600193506103e892506134c2565b60009350600192505b5050915091565b60095481565b600160a060020a038083166000908152601360209081526040808320339094168352929052908120548161350384836122b8565b93506000841161351257600080fd5b84600160a060020a031663a9059cbb338660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561356657600080fd5b5af1151561357357600080fd5b50505060405180519050151561358857600080fd5b6135928285612b5b565b600160a060020a0380871660008181526013602090815260408083203390951683529390528290208390559192507f6e2e05fb6a732995d6952d9158ca6b75f11cc6bf5a4af943aa1eb475a249440b9086905190815260200160405180910390a2949350505050565b60045460009081908190613619908590600160a060020a031661104f565b600454909150613638908590600160a060020a0316600019840161130c565b909590945092505050565b60035433600160a060020a0390811691161461365e57600080fd5b600654600160a060020a0316151561367557600080fd5b60075442901061368457600080fd5b600680546005805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b60035433600160a060020a039081169116146136d357600080fd5b600160a060020a03811615156136e857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03831617905561371d4262278d006121a2565b6002557f36dceb79f427eda3edba9ac3c1d4db7a6e4d0b8637d97320847d93fa8e2f7a0481604051600160a060020a03909116815260200160405180910390a150565b601460209081526000938452604080852082529284528284209052825290205481565b61378b61474c565b61379361474c565b6000806000806000806137a68c8c61104f565b955088156137b9578886036001016137bc565b60015b93508392505b85831161381b57600160a060020a03808d1660009081526015602090815260408083208f8516845282528083208784528252808320938e168352929052908120541115613810576001909401935b6001909201916137c2565b846040518059106138295750595b908082528060200260200182016040525097508460405180591061384a5750595b908082528060200260200182016040525096508390505b85811161196757600160a060020a03808d1660009081526015602090815260408083208f8516845282528083208584528252808320938e16835292905290812054111561391757808883815181106138b557fe5b6020908102909101810191909152600160a060020a03808e1660009081526015835260408082208f8416835284528082208583528452808220928e1682529190925290205487838151811061390657fe5b602090810290910101526001909101905b600101613861565b600d60209081526000928352604080842090915290825290205481565b60008061394761475e565b600160a060020a038087166000908152600f60209081526040808320938916835292815282822087835290528181209091829182918051908101604052815481526001909101546020820190815290945051156139af578351846020015190965094506114ba565b6139b9898961104f565b8711156139cc57600095508594506114ba565b6139da898960018a0361130c565b90935091506139f36139ec8a8a612f96565b42036110ff565b9050613a0583826201518003026110ff565b9550613a158161a8c00183612d10565b600160a060020a03808b166000908152601260209081526040808320938d1683529290522054909550613a49908690612d10565b600160a060020a03808b166000908152601060209081526040808320938d1683529290522054613a7a908890612d10565b116114ba5750505050600160a060020a039485166000818152601260209081526040808320979098168083529681528782205492825260108152878220968252959095529490932054939492505050565b6000806000806000613adc33613366565b909450925082613aec8786612d10565b811515613af557fe5b0491506000821115613bc657613b0b8983614414565b600160a060020a03808b166000908152601460209081526040808320938d16835292815282822060018c018352905220549092509050613b4b81836121a2565b600160a060020a03808b1660008181526014602090815260408083208e861680855290835281842060018f01855290925291829020949094553390921692917f30c4d3fe752442ffa2415fd4e6398cb9e378bab963f042ce30ef4363b6ad93b6908b9087905191825260208201526040908101905180910390a45b613bd08683612b5b565b9998505050505050505050565b600554600090819081908190819081908190600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c2b57600080fd5b5af11515613c3857600080fd5b505050604051805190509650613c4d896135fb565b9096509450613c5b886135fb565b600160a060020a03808c166000908152601060209081526040808320938e168352929052205491955093508590613c9c90613c969089612d10565b89612d10565b811515613ca557fe5b600160a060020a03808b166000908152601060209081526040808320938f168352929052205491900492508390613ce090613c969087612d10565b811515613ce957fe5b04905060095482101580613cff57506009548110155b15613d1657613d118989610258614646565b6123a7565b6123a789896146e2565b600160a060020a0380851660008181526012602090815260408083209488168084529482528083205460108352818420858552835281842054958452600f835281842094845293825280832087845290915281206001015491929190808080613d898b8b612f96565b93506000881115613de55760408051908101604090815288825260208083018b9052600160a060020a03808f166000908152600f8352838120918f1681529082528281208d825290915220815181556020820151600190910155505b851580613df757508362015180014210155b80613e025750600085115b1561401757600160a060020a03808b166000908152601260209081526040808320938f1683529290522054925084158015613e3d5750600086115b15613ec457604080519081016040528084815260200187815250600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b8152602001908152602001600020600082015181556020820151600190910155505b5050600160a060020a03808a166000818152601160208181526040808420958e16808552958252808420549282528084209484529381528383205460108252848420958452949052918120829055909190821115613f4557600160a060020a03808c166000908152601160209081526040808320938e168352929052908120555b6000871115613f7757600160a060020a03808c166000908152601260209081526040808320938e168352929052908120555b600160a060020a03808b166000908152601060209081526040808320938f168352929052908120829055811115613fd157600160a060020a03808b166000908152601160209081526040808320938f168352929052908120555b600083111561400357600160a060020a03808b166000908152601260209081526040808320938f168352929052908120555b61400d8b8b6141a9565b6140178b8b613bdd565b888a600160a060020a03168c600160a060020a03167fb5806f8610464e96807c2b147620cc721c65309647f16cfccdf9fb7bd95152ac8b8b60405191825260208201526040908101905180910390a45050505050505050505050565b600160a060020a0386166000908152600c602052604081205481908190819060ff1680156140b95750600160a060020a0389166000908152600c602052604090205460ff165b1561419c57600454600160a060020a0390811693508a168314156140df5785935061412c565b82600160a060020a031689600160a060020a031614156141015787935061412c565b61410f8a8460018a0361130c565b90925090508061411f8784612d10565b81151561412857fe5b0493505b600084111561419c57600a54600160a060020a031663f0dda65c868660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561418b57600080fd5b5af1151561419857600080fd5b5050505b5050509695505050505050565b6141b38282610dcc565b600160a060020a039182166000908152600d602090815260408083209390941682529190915220805460010190555050565b60008060008060008060006141fa8d8a61104f565b1161420457600080fd5b60006142108c8a61104f565b1161421a57600080fd5b6142238c6135fb565b90955093506142318b6135fb565b9093509150614261846142448c88612d10565b81151561424d57fe5b0483858c0281151561425b57fe5b046121a2565b9050611e578188612d10565b600160a060020a0380851660009081526013602090815260408083203390941683529290529081205481906142a29085612b5b565b600160a060020a03808816600090815260136020818152604080842033861680865290835281852096909655938a168352908152828220938252929092529020546142ed9084612b5b565b600160a060020a03808716600090815260136020908152604080832033909416835292905220556143218686600187613acb565b91506143308587600186613acb565b600160a060020a0380881660008181526010602081815260408084208c87168086529083528185208a90559282528084208585528252808420879055601580835281852084865283528185206001808752908452828620339098168087529784528286208b9055938552825280842094845293815283832091835290815282822093825292909252902081905590506143cc8686615460614646565b84600160a060020a031686600160a060020a03167f6f4b2adffa0c3e90e47fdcd9d2c36f48b57eb3271dce519997271073dac17be960405160405180910390a3505050505050565b6000806000806000806000806144298a6135fb565b9097509550856144398a89612d10565b81151561444257fe5b6005549190049550600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561448657600080fd5b5af1151561449357600080fd5b5050506040518051905093506144a98585612d10565b600b5490935061452890600160a060020a031663dd62ed3e333060405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b151561450857600080fd5b5af1151561451557600080fd5b50505060405180519050600285046122b8565b600b5490925061459c90600160a060020a03166370a082313360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561457f57600080fd5b5af1151561458c57600080fd5b50505060405180519050836122b8565b9150600082111561463557600b54600160a060020a0316634417f4db338460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b15156145fd57600080fd5b5af1151561460a57600080fd5b50505082614618838b612d10565b81151561462157fe5b04905061462e8982612b5b565b9750614639565b8897505b5050505050505092915050565b6000806146538585610dcc565b600160a060020a038083166000818152600d6020908152604080832094861680845294825280832054848452600e835281842086855290925291829020428a0190819055959a5093985093955091935083929091907f20017e7b1ef8e7882103f55ff346ca3135c4afe13dff1da2f01b482aece766a59086905190815260200160405180910390a45050505050565b6146ec8282610dcc565b600160a060020a038083166000908152600e6020908152604080832093851683529290522054919350915060011461474857600160a060020a038083166000908152600e60209081526040808320938516835292905220600190555b5050565b60206040519081016040526000815290565b6040805190810160405260008082526020820152905600a165627a7a723058208234706d1c6efd546ff852e83c41531610f61e18cf7d16f7d8577228a5c5b49d0029

   Swarm Source:
bzzr://8234706d1c6efd546ff852e83c41531610f61e18cf7d16f7d8577228a5c5b49d

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.