Contract 0x9e5e05700045dc70fc42c125d4bd661c798d4ce9

Contract Overview

Balance:
0 Ether

Latest 25 internal transaction, Click here to view more Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0x4b11866a6dd7d514e0c3362ef8a46ccb7cd0dc7676d9aa048025be376ce3be9a393665923 days 17 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x4b11866a6dd7d514e0c3362ef8a46ccb7cd0dc7676d9aa048025be376ce3be9a393665923 days 17 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xfd18aed4ea835b89c8a65c69fcc936c92420d25e4b6d65b1f1ce17a89f3c3a08391413227 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xfd18aed4ea835b89c8a65c69fcc936c92420d25e4b6d65b1f1ce17a89f3c3a08391413227 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xacb31aee7f73bf78d286521b08da508cebfcf35d56a5ffb7faf4304a0f453651391411227 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xacb31aee7f73bf78d286521b08da508cebfcf35d56a5ffb7faf4304a0f453651391411227 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x9fa23dabbaa91d048b1e3fd613a1faa65c85c7e09cd2300fc167aea55e340571391407927 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x9fa23dabbaa91d048b1e3fd613a1faa65c85c7e09cd2300fc167aea55e340571391407927 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xe54b1f3286bad44df10c3da121cfc53a472366dfcb34e3e4911ffb3a04b9a04c391407327 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xb02bb78d13a78e9e9665b9772d990c08a04c4e5df9604b2692beab28976947fb385657437 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x94fcc48a5da5271a45715e43861728322efd15343223641fda12e6896ca9a144385601737 days 17 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xc5f32c03b3ce6886d99383f7d6138f91b51ed30d7d14accfc2e686ea900d9d0a385172438 days 11 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x67c72abfc516b1bb6895686d05b3f8b87ccc92efe3bb161a39c7717697174f08385079638 days 15 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xe05a1aa2588b704f2a806f8f393f750cd0615e07e0c6f8f22c64b5b3d32372c2385010838 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xf010aaf758f9a8b228dc93600b0f76b2f8727189c8f163c0e78aca3217f73680384993438 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x581d0d9ffcc255da68fe46b1a5a5a2adaf32cff4918aefb5c00b26b5d1cd2e8c384993238 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xf2f5b1f188b7ea6798751992c758e378d99fad56eb8833392d3e1a350548835b384992238 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x05647a01fe0eae7e5ad935516455e12f800edab6cd25461c4164bfa06cf04244384992038 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x0cc79ec82a7964c02327644a6ed1a1bc21be794e4c221bfa58aea2d925bde18b384990938 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xac7c324e004c6cfb2c7b8a751b2c9cebb281cf89572dc22f8e96f16654b13ead384990838 days 18 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x58b22332e05d4dea283d0554e79cc07e934974003aa74a1ab94d6184c26b0522384985438 days 19 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x654104db693d200e61fb8e5ef0ac1f919d2e5e9f11b9fc5c67599ccf39dd5a41383479341 days 9 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0xc072b963fc412bab4f29e0538fb7b4e9cfb992ef63ad6ff0ac139cc47aa38e4f383479041 days 9 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x958cd2ed416c2deb983ec2aac7bf287099b53f4e44c845218543e712a42870e8383478841 days 9 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
0x5b54e77e5dfebb528165710f8d9d95ea11ab52da6bd56f84c1c5a674cee74527383478341 days 9 hrs ago0x4e69969d9270ff55fc7c5043b074d4e45f7955870x9e5e05700045dc70fc42c125d4bd661c798d4ce90 Ether
[ Download CSV Export 

Contract Source Code Verified (Exact Match)

Contract Name:
DutchExchange

Compiler Version
v0.4.21+commit.dfe3193c

Optimization Enabled:
Yes

Runs (Optimizer):
200

Contract Source Code

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

6060604052341561000f57600080fd5b6147a18061001e6000396000f3006060604052600436106103075763ffffffff60e060020a600035041662599e65811461030c57806301a521d61461035557806302ffc0b0146103de57806304e80e90146103fc57806306d58f2a1461042b5780630e7c0f80146104805780631006a41f146104a557806314584a9d146104ca5780632cef4dac146104ef5780633069046814610504578063377758071461051a578063403fbf541461054957806347e7ef24146105685780634bf8e7a21461058a5780634e30a66c146105ca57806359f96ae5146105f75780635e7f22c2146106225780635ec2c7bf1461064d57806365054e5514610660578063657a37ad1461068e57806365b0d711146106b65780636d1ea3fa146107095780636e6260fa146107285780636ea683601461073b578063706eb3ab1461074e578063771602f7146107615780637895dd211461077a578063796a8076146107bc5780637ae2b5c7146107db5780637bf1a627146107f4578063821b98f3146108075780638261eb1b1461082f57806384429579146108425780639fec8e96146108f9578063a48cef4a14610928578063a619486e1461093b578063acb103511461094e578063b02938501461098b578063b3c2083f146109b9578063b64c4905146109de578063b67d77c514610a03578063b8beafd614610a1c578063bc88adc414610a41578063c1a21bf314610a77578063c23f001f14610aa6578063c6af43f914610acb578063c8a4ac9c14610ae1578063cb10fa7614610afa578063cd04ccfc14610b13578063cd94a2a414610b26578063d3062b2414610b39578063d3cc8d1c14610b67578063dae595e514610ba9578063df6af7d114610bce578063e1c95bb914610bfc578063e31c71c414610c12578063e9f8cd7014610c2b578063ebcc0de114610c5c578063edd0b5cb14610c84578063ee93114c14610ca3578063f3fef3a314610cb6578063f41d97fc14610cd8578063f4279d1f14610cf7578063f625ee2814610d0a578063f79710fd14610d29578063f97ea6fc14610d51578063fac7abe314610d7f578063fdab1b7b14610da4575b600080fd5b341561031757600080fd5b610331600160a060020a0360043581169060243516610dcc565b604051600160a060020a039283168152911660208201526040908101905180910390f35b341561036057600080fd5b61038b6024600480358281019290820135918135918201910135600160a060020a0360443516610df5565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156103ca5780820151838201526020016103b2565b505050509050019250505060405180910390f35b34156103e957600080fd5b61038b6004803560248101910135610f49565b341561040757600080fd5b61040f610ff0565b604051600160a060020a03909116815260200160405180910390f35b341561043657600080fd5b61045c600160a060020a0360043581169060243581169060443516606435608435610fff565b60405180848152602001838152602001828152602001935050505060405180910390f35b341561048b57600080fd5b61049361102c565b60405190815260200160405180910390f35b34156104b057600080fd5b610493600160a060020a0360043581169060243516611032565b34156104d557600080fd5b610493600160a060020a036004358116906024351661104f565b34156104fa57600080fd5b61050261108a565b005b341561050f57600080fd5b6104936004356110ff565b341561052557600080fd5b610493600160a060020a036004358116906024358116906044359060643516611119565b341561055457600080fd5b610502600160a060020a0360043516611145565b341561057357600080fd5b610493600160a060020a03600435166024356111ed565b341561059557600080fd5b6105b2600160a060020a036004358116906024351660443561130c565b60405191825260208201526040908101905180910390f35b34156105d557600080fd5b6105e36004356024356114c6565b604051901515815260200160405180910390f35b341561060257600080fd5b6105b2600160a060020a03600435811690602435166044356064356114d4565b341561062d57600080fd5b610493600160a060020a0360043581169060243516604435606435611976565b341561065857600080fd5b61040f611e67565b341561066b57600080fd5b6105b2600160a060020a0360043581169060243581169060443516606435611e76565b341561069957600080fd5b61045c600160a060020a036004358116906024351660443561206d565b34156106c157600080fd5b610502600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965050505091351515915061209a9050565b341561071457600080fd5b6105e3600160a060020a0360043516612169565b341561073357600080fd5b61049361217e565b341561074657600080fd5b61040f612184565b341561075957600080fd5b61040f612193565b341561076c57600080fd5b6104936004356024356121a2565b341561078557600080fd5b6105026024600480358281019290820135918135808301929082013591604435918201910135600160a060020a03606435166121be565b34156107c757600080fd5b610502600160a060020a0360043516612259565b34156107e657600080fd5b6104936004356024356122b8565b34156107ff57600080fd5b61040f6122d0565b341561081257600080fd5b610502600160a060020a03600435811690602435166044356122df565b341561083a57600080fd5b61040f6123b3565b341561084d57600080fd5b61086060048035602481019101356123c2565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156108a457808201518382015260200161088c565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156108e35780820151838201526020016108cb565b5050505090500194505050505060405180910390f35b341561090457600080fd5b610493600160a060020a036004358116906024358116906044359060643516612582565b341561093357600080fd5b6104936125ae565b341561094657600080fd5b61040f6125b4565b341561095957600080fd5b610502600160a060020a036004358116906024358116906044358116906064358116906084351660a43560c4356125c3565b341561099657600080fd5b6105b2600160a060020a03600435811690602435811690604435166064356126b9565b34156109c457600080fd5b610493600160a060020a0360043581169060243516612b21565b34156109e957600080fd5b610493600160a060020a0360043581169060243516612b3e565b3415610a0e57600080fd5b610493600435602435612b5b565b3415610a2757600080fd5b610493600160a060020a0360043581169060243516612b78565b3415610a4c57600080fd5b61038b6024600480358281019290820135918135918201910135600160a060020a0360443516612b95565b3415610a8257600080fd5b610493600160a060020a036004358116906024358116906044359060643516612ca7565b3415610ab157600080fd5b610493600160a060020a0360043581169060243516612cd3565b3415610ad657600080fd5b610502600435612cf0565b3415610aec57600080fd5b610493600435602435612d10565b3415610b0557600080fd5b6105e3600435602435612d2c565b3415610b1e57600080fd5b61040f612d4e565b3415610b3157600080fd5b61040f612d5d565b3415610b4457600080fd5b610860600160a060020a0360043581169060243581169060443516606435612d6c565b3415610b7257600080fd5b6105026024600480358281019290820135918135808301929082013591604435918201910135600160a060020a0360643516612f08565b3415610bb457600080fd5b610493600160a060020a0360043581169060243516612f96565b3415610bd957600080fd5b61045c600160a060020a0360043581169060243581169060443516606435612fd1565b3415610c0757600080fd5b61050260043561308d565b3415610c1d57600080fd5b6105e36004356024356130ad565b3415610c3657600080fd5b610502600160a060020a036004358116906024351660443560643560843560a4356130b3565b3415610c6757600080fd5b6105b2600160a060020a036004358116906024351660443561333c565b3415610c8f57600080fd5b6105b2600160a060020a0360043516613366565b3415610cae57600080fd5b6104936134c9565b3415610cc157600080fd5b610493600160a060020a03600435166024356134cf565b3415610ce357600080fd5b6105b2600160a060020a03600435166135fb565b3415610d0257600080fd5b610502613643565b3415610d1557600080fd5b610502600160a060020a03600435166136b8565b3415610d3457600080fd5b610493600160a060020a0360043581169060243516604435613760565b3415610d5c57600080fd5b610860600160a060020a0360043581169060243581169060443516606435613783565b3415610d8a57600080fd5b610493600160a060020a036004358116906024351661391f565b3415610daf57600080fd5b6105b2600160a060020a036004358116906024351660443561393c565b60008083600160a060020a031683600160a060020a03161015610ded579192915b509192909150565b610dfd61474c565b600080610e0861474c565b879250859150600080838514610e1d57600080fd5b84604051805910610e2b5750595b90808252806020026020018201604052509250600091505b84821015610f3a57610e8d8b8b84818110610e5a57fe5b90506020020135600160a060020a03168a8a858181101515610e7857fe5b90506020020135600160a060020a031661104f565b9050601560008c8c85818110610e9f57fe5b90506020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008a8a858181101515610edf57fe5b600160a060020a0360209182029390930135831684528381019490945250604091820160009081208582528452828120918b1681529252902054838381518110610f2557fe5b60209081029091010152600190910190610e43565b50909998505050505050505050565b610f5161474c565b6000610f5b61474c565b839150600082604051805910610f6e5750595b90808252806020026020018201604052509150600090505b82811015610fe757600c6000878784818110610f9e57fe5b60209081029290920135600160a060020a03168352508101919091526040016000205460ff16828281518110610fd057fe5b911515602092830290910190910152600101610f86565b50949350505050565b600054600160a060020a031690565b600080600061101088888888611e76565b909350915061101f87856134cf565b9050955095509592505050565b60025481565b600e60209081526000928352604080842090915290825290205481565b600061105b8383610dcc565b600160a060020a039182166000908152600d602090815260408083209390941682529190915220549392505050565b60035433600160a060020a039081169116146110a557600080fd5b600154600160a060020a031615156110bc57600080fd5b6002544210156110cb57600080fd5b600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b60008082121561111157506000611114565b50805b919050565b601660209081526000948552604080862082529385528385208152918452828420909152825290205481565b60035433600160a060020a0390811691161461116057600080fd5b600160a060020a038116151561117557600080fd5b6006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790556111aa4262278d006121a2565b6007557f3f174cfd713408ca6e4620d1efcc241b23fc39aa7d4694bd98610d3384dc001c81604051600160a060020a03909116815260200160405180910390a150565b60008083600160a060020a03166323b872dd33308660405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561125157600080fd5b5af1151561125e57600080fd5b50505060405180519050151561127357600080fd5b600160a060020a03808516600090815260136020908152604080832033909416835292905220546112a490846121a2565b600160a060020a0380861660008181526013602090815260408083203390951683529390528290208390559192507f2cb77763bc1e8490c1a904905c4d74b4269919aca114464f4bb4d911e60de3649085905190815260200160405180910390a29392505050565b60008060008061131a61475e565b61132261475e565b87600160a060020a031689600160a060020a031614156113495760019550600194506114ba565b600087101561135757600080fd5b611361898961104f565b87111561136d57600080fd5b60009350600092505b82151561145b57600160a060020a038089166000908152600f60209081526040808320938d168352928152828220878b0383529052819020908051908101604090815282548252600190920154602080830191909152600160a060020a03808d166000908152600f8352848120918d168152908252838120888c03825290915282902090925090805190810160405281548152600190910154602082015291506000825111801561142b575060008260200151115b80611446575060008151118015611446575060008160200151115b1561145057600192505b600190930192611376565b8151158061146b57508160200151155b156114805780602001519550805194506114ba565b8051158061149057508060200151155b156114a55781519550816020015194506114ba565b81518160200151019550816020015181510194505b50505050935093915050565b808201829010155b92915050565b60008060008060008060008061153289601360008f600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020546122b8565b98506000891161154157600080fd5b61154b8c8c61104f565b95506000861161155a57600080fd5b6115648c8c612f96565b9450600185148061157457504285115b156115e25789151561158857859950611594565b89861461159457600080fd5b600160a060020a03808d166000908152601060209081526040808320938f16835292905220546c0c9f2c9cd04674edea40000000906115d3908b6121a2565b106115dd57600080fd5b61164c565b8915156115f457856001019950611603565b600186018a1461160357600080fd5b600160a060020a03808d166000908152601160209081526040808320938f16835292905220546c0c9f2c9cd04674edea4000000090611642908b6121a2565b1061164c57600080fd5b6116588c8c8c8c613acb565b600160a060020a03808e166000908152601360209081526040808320339094168352929052205490945061168c908a612b5b565b601360008e600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a031681526020019081526020016000208190555061175e601560008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002054856121a2565b925082601560008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c8152602001908152602001600020600033600160a060020a0316600160a060020a031681526020019081526020016000208190555060018514806117ef57504285115b1561187757600160a060020a03808d166000908152601060209081526040808320938f1683529290522054915061182682856121a2565b601060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020819055506118f5565b50600160a060020a03808c166000908152601160209081526040808320938e16835292905220546118a881856121a2565b601160008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020819055505b6001851415611908576119088c8c613bdd565b33600160a060020a03168b600160a060020a03168d600160a060020a03167f3681d6f6ad159bac260c32828859f6df545bbf841c6e70787bcf0acbc390512a8d8860405191825260208201526040908101905180910390a48983975097505b50505050505094509492505050565b600160a060020a038085166000908152600f60209081526040808320938716835292815282822085835290529081206001015481908190819081908190819081908190156119c357600080fd5b6119cd8d8d612f96565b9750428811156119dc57600080fd5b6119e68d8d61104f565b8b146119f157600080fd5b600188116119fe57600080fd5b6000601060008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002054111515611a5557600080fd5b601260008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020549650611af28a601360008f600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020546122b8565b99506c0c9f2c9cd04674edea40000000611b0c888c6121a2565b10611b1657600080fd5b601060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a03168152602001908152602001600020549550611b6c8d8d8d61393c565b9095509350611b908785611b808989612d10565b811515611b8957fe5b04036110ff565b9250828a1015611bb75760008a1115611bb257611baf8c8e8d8d613acb565b91505b611bbe565b8299508291505b60008a1115611e4457600160a060020a03808d1660009081526013602090815260408083203390941683529290522054611bf8908b612b5b565b601360008e600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550611cca601660008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002054836121a2565b905080601660008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002060008d8152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550611d9f601260008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a0316815260200190815260200160002054836121a2565b601260008f600160a060020a0316600160a060020a0316815260200190815260200160002060008e600160a060020a0316600160a060020a031681526020019081526020016000208190555033600160a060020a03168c600160a060020a03168e600160a060020a03167ff1751a362067564d5feb9ed26f1898bb14c17e1254e3724d454bc2ae80195c258e8660405191825260208201526040908101905180910390a45b828a10611e5757611e578d8d8d89613d20565b9c9b505050505050505050505050565b600354600160a060020a031681565b6000806000611e8361475e565b600080611e918a8a896122df565b600160a060020a03808b1660009081526015602090815260408083208d8516845282528083208b84528252808320938c1683529290529081205494508411611ed857600080fd5b600160a060020a03808b166000908152600f60209081526040808320938d1683529281528282208a835290528190209080519081016040528154815260019091015460208201529250825191508260200151905060008111611f3957600080fd5b80611f448584612d10565b811515611f4d57fe5b049550611f5e8a8a888a888d614073565b600160a060020a03808c1660009081526015602090815260408083208e8516845282528083208c84528252808320938d168352929052908120819055909550861115611ffb57600160a060020a03808a166000908152601360209081526040808320938c1683529290522054611fd490876121a2565b600160a060020a03808b166000908152601360209081526040808320938d16835292905220555b87600160a060020a031689600160a060020a03168b600160a060020a03167fa3ac9b53d029621ef95693b5f9b1d0b0da75029fe8530389271be02715e24c138a8a8a60405180848152602001838152602001828152602001935050505060405180910390a45050505094509492505050565b600080600061207c86856111ed565b925061208b86866000876114d4565b93979096509294509192505050565b60035460009033600160a060020a039081169116146120b857600080fd5b5060005b82518110156121645781600c60008584815181106120d657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff191691151591909117905582818151811061211457fe5b90602001906020020151600160a060020a03167fc091bf3abd3a42f670f8ad1a6ad5b849311210403e1d85d6ac31f43114d5ca6e83604051901515815260200160405180910390a26001016120bc565b505050565b600c6020526000908152604090205460ff1681565b60085481565b600154600160a060020a031681565b600554600160a060020a031681565b60006121ae83836114c6565b15156121b957600080fd5b500190565b85846000808284146121cf57600080fd5b8591508282146121de57600080fd5b5060005b8381101561224c576122428b8b838181106121f957fe5b90506020020135600160a060020a03168a8a84818110151561221757fe5b90506020020135600160a060020a0316878a8a86818110151561223657fe5b90506020020135611e76565b50506001016121e2565b5050505050505050505050565b60035433600160a060020a0390811691161461227457600080fd5b600160a060020a038116151561228957600080fd5b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000818310156122c95750816114ce565b50806114ce565b600454600160a060020a031681565b60008060008060006122f1878961104f565b8614801561232a5750600160a060020a038089166000908152600f60209081526040808320938b16835292815282822089835290522054155b156123a957600160a060020a038089166000818152601260209081526040808320948c1680845294825280832054938352601082528083209483529390529190912054909550935061237d88888861393c565b90935091506123918583611b808787612d10565b90508015156123a9576123a78888886000611976565b505b5050505050505050565b600a54600160a060020a031681565b6123ca61474c565b6123d261474c565b600080808080805b6000198901851015612447578460010193505b8884101561243c5760006124248b8b8881811061240657fe5b90506020020135600160a060020a03168c8c888181101515610e7857fe5b1115612431576001909501945b6001909301926123ed565b6001909401936123da565b856040518059106124555750595b90808252806020026020018201604052509750856040518059106124765750595b90808252806020026020018201604052509650600091505b60001989018210156125755750600181015b8881101561256a5760006124d78b8b858181106124b957fe5b90506020020135600160a060020a03168c8c858181101515610e7857fe5b1115612562578989838181106124e957fe5b90506020020135600160a060020a031688848151811061250557fe5b600160a060020a0390921660209283029091019091015289898281811061252857fe5b90506020020135600160a060020a031687848151811061254457fe5b600160a060020a039092166020928302909101909101526001909201915b6001016124a0565b60019091019061248e565b5050505050509250929050565b601760209081526000948552604080862082529385528385208152918452828420909152825290205481565b60075481565b600054600160a060020a031681565b600454600160a060020a0316156125d957600080fd5b600160a060020a03861615156125ee57600080fd5b600160a060020a038716151561260357600080fd5b600160a060020a038516151561261857600080fd5b600160a060020a038416151561262d57600080fd5b600160a060020a038316151561264257600080fd5b600a805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03998a1617909155600b8054821697891697909717909655600380548716958816959095179094556004805486169387169390931790925560058054909416941693909317909155600891909155600955565b60008060008060008060006126cf8b8b8a6122df565b6126db8b8b8b8b612fd1565b809650819750829950505050600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020600089815260200190815260200160002060010154600014156127cb57600160a060020a03808c1660009081526017602090815260408083208e8516845282528083208c84528252808320938d168352929052205461278e90886121a2565b600160a060020a03808d1660009081526017602090815260408083208f8516845282528083208d84528252808320938e1683529290522055612a4e565b601460008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a031681526020019081526020016000206000898152602001908152602001600020549250601660008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020600089815260200190815260200160002060008a600160a060020a0316600160a060020a03168152602001908152602001600020549150600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a0316815260200190815260200160002060008981526020019081526020016000206000015461290d8385612d10565b81151561291657fe5b04905061292387826121a2565b96506129478a8c876129358689612d10565b81151561293e57fe5b048b868e614073565b95506000601660008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002060008a815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020819055506000601760008d600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002060008a815260200190815260200160002060008b600160a060020a0316600160a060020a03168152602001908152602001600020819055505b6000871115612aae57600160a060020a03808c166000908152601360209081526040808320938d1683529290522054612a8790886121a2565b600160a060020a03808d166000908152601360209081526040808320938e16835292905220555b88600160a060020a03168a600160a060020a03168c600160a060020a03167f4d1c39fd1a9c74f88b9f90c7b439b7e5dc6f26b6ff280fd497fdec5c538aaf528b8b8b60405180848152602001838152602001828152602001935050505060405180910390a4505050505094509492505050565b601160209081526000928352604080842090915290825290205481565b601060209081526000928352604080842090915290825290205481565b6000612b6783836130ad565b1515612b7257600080fd5b50900390565b601260209081526000928352604080842090915290825290205481565b612b9d61474c565b600080612ba861474c565b879250859150600080838514612bbd57600080fd5b84604051805910612bcb5750595b90808252806020026020018201604052509250600091505b84821015610f3a57612bfa8b8b84818110610e5a57fe5b9050601660008c8c85818110612c0c57fe5b90506020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008a8a858181101515612c4c57fe5b600160a060020a0360209182029390930135831684528381019490945250604091820160009081208582528452828120918b1681529252902054838381518110612c9257fe5b60209081029091010152600190910190612be3565b601560209081526000948552604080862082529385528385208152918452828420909152825290205481565b601360209081526000928352604080842090915290825290205481565b60035433600160a060020a03908116911614612d0b57600080fd5b600955565b6000612d1c8383612d2c565b1515612d2757600080fd5b500290565b6000811580612d4757508282838502811515612d4457fe5b04145b9392505050565b600654600160a060020a031681565b600b54600160a060020a031681565b612d7461474c565b612d7c61474c565b600080600080600080612d8f8c8c61104f565b95508815612da257888603600101612da5565b60015b93508392505b858311612e0457600160a060020a03808d1660009081526016602090815260408083208f8516845282528083208784528252808320938e168352929052908120541115612df9576001909401935b600190920191612dab565b84604051805910612e125750595b9080825280602002602001820160405250975084604051805910612e335750595b908082528060200260200182016040525096508390505b85811161196757600160a060020a03808d1660009081526016602090815260408083208f8516845282528083208584528252808320938e168352929052908120541115612f005780888381518110612e9e57fe5b6020908102909101810191909152600160a060020a03808e1660009081526016835260408082208f8416835284528082208583528452808220928e16825291909252902054878381518110612eef57fe5b602090810290910101526001909101905b600101612e4a565b8584600080828414612f1957600080fd5b859150828214612f2857600080fd5b5060005b8381101561224c57612f8c8b8b83818110612f4357fe5b90506020020135600160a060020a03168a8a848181101515612f6157fe5b90506020020135600160a060020a0316878a8a868181101515612f8057fe5b905060200201356126b9565b5050600101612f2c565b6000612fa28383610dcc565b600160a060020a039182166000908152600e602090815260408083209390941682529190915220549392505050565b600080600080612fe1888861104f565b851115612fed57600080fd5b612ff888888761393c565b909350915082151561300d5760009350613082565b50600160a060020a0380881660008181526016602090815260408083208b86168085529083528184208a85528352818420958b16808552958352818420549484526017835281842090845282528083208984528252808320948352939052919091205461307f9084611b808486612d10565b93505b509450945094915050565b60035433600160a060020a039081169116146130a857600080fd5b600855565b90101590565b60008080600160a060020a0389811690891614156130d057600080fd5b8415156130dc57600080fd5b8315156130e857600080fd5b6130f2898961104f565b156130fc57600080fd5b670de0b6b3a7640000851061311057600080fd5b670de0b6b3a7640000841061312457600080fd5b61312e89896141a9565b600160a060020a03808a16600090815260136020908152604080832033909416835292905220546131609088906122b8565b600160a060020a03808a16600090815260136020908152604080832033909416835292905220549097506131959087906122b8565b95506c0c9f2c9cd04674edea4000000087106131b057600080fd5b6c0c9f2c9cd04674edea4000000086106131c957600080fd5b600554600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561320857600080fd5b5af1151561321557600080fd5b5050506040518051600454909350600160a060020a0390811692508a16821415905061324c576132458783612d10565b9250613281565b80600160a060020a031688600160a060020a03161415613270576132458683612d10565b61327e8989898985876141e5565b92505b60085483101561329057600080fd5b6040805190810160409081528682526020808301879052600160a060020a03808d166000908152600f8352838120918d16815290825282812081805290915220815181556020820151600190910155506040805190810160409081528582526020808301889052600160a060020a03808c166000908152600f8352838120918e16815290825282812081805290915220815181556020820151600190910155506123a78989898961426d565b600f6020908152600093845260408085208252928452828420905282529020805460019091015482565b600a54600090819081908190600160a060020a03166318160ddd6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156133ae57600080fd5b5af115156133bb57600080fd5b5050506040518051600a54909350600160a060020a03169050638b525d0c8660405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561341857600080fd5b5af1151561342557600080fd5b5050506040518051905090508181620186a0021080613442575081155b15613454576001935060c892506134c2565b818161271002101561346d576001935060fa92506134c2565b81816103e802101561348757600393506103e892506134c2565b818160640210156134a057600193506101f492506134c2565b8181600a0210156134b957600193506103e892506134c2565b60009350600192505b5050915091565b60095481565b600160a060020a038083166000908152601360209081526040808320339094168352929052908120548161350384836122b8565b93506000841161351257600080fd5b84600160a060020a031663a9059cbb338660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561356657600080fd5b5af1151561357357600080fd5b50505060405180519050151561358857600080fd5b6135928285612b5b565b600160a060020a0380871660008181526013602090815260408083203390951683529390528290208390559192507f6e2e05fb6a732995d6952d9158ca6b75f11cc6bf5a4af943aa1eb475a249440b9086905190815260200160405180910390a2949350505050565b60045460009081908190613619908590600160a060020a031661104f565b600454909150613638908590600160a060020a0316600019840161130c565b909590945092505050565b60035433600160a060020a0390811691161461365e57600080fd5b600654600160a060020a0316151561367557600080fd5b60075442901061368457600080fd5b600680546005805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b60035433600160a060020a039081169116146136d357600080fd5b600160a060020a03811615156136e857600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03831617905561371d4262278d006121a2565b6002557f36dceb79f427eda3edba9ac3c1d4db7a6e4d0b8637d97320847d93fa8e2f7a0481604051600160a060020a03909116815260200160405180910390a150565b601460209081526000938452604080852082529284528284209052825290205481565b61378b61474c565b61379361474c565b6000806000806000806137a68c8c61104f565b955088156137b9578886036001016137bc565b60015b93508392505b85831161381b57600160a060020a03808d1660009081526015602090815260408083208f8516845282528083208784528252808320938e168352929052908120541115613810576001909401935b6001909201916137c2565b846040518059106138295750595b908082528060200260200182016040525097508460405180591061384a5750595b908082528060200260200182016040525096508390505b85811161196757600160a060020a03808d1660009081526015602090815260408083208f8516845282528083208584528252808320938e16835292905290812054111561391757808883815181106138b557fe5b6020908102909101810191909152600160a060020a03808e1660009081526015835260408082208f8416835284528082208583528452808220928e1682529190925290205487838151811061390657fe5b602090810290910101526001909101905b600101613861565b600d60209081526000928352604080842090915290825290205481565b60008061394761475e565b600160a060020a038087166000908152600f60209081526040808320938916835292815282822087835290528181209091829182918051908101604052815481526001909101546020820190815290945051156139af578351846020015190965094506114ba565b6139b9898961104f565b8711156139cc57600095508594506114ba565b6139da898960018a0361130c565b90935091506139f36139ec8a8a612f96565b42036110ff565b9050613a0583826201518003026110ff565b9550613a158161a8c00183612d10565b600160a060020a03808b166000908152601260209081526040808320938d1683529290522054909550613a49908690612d10565b600160a060020a03808b166000908152601060209081526040808320938d1683529290522054613a7a908890612d10565b116114ba5750505050600160a060020a039485166000818152601260209081526040808320979098168083529681528782205492825260108152878220968252959095529490932054939492505050565b6000806000806000613adc33613366565b909450925082613aec8786612d10565b811515613af557fe5b0491506000821115613bc657613b0b8983614414565b600160a060020a03808b166000908152601460209081526040808320938d16835292815282822060018c018352905220549092509050613b4b81836121a2565b600160a060020a03808b1660008181526014602090815260408083208e861680855290835281842060018f01855290925291829020949094553390921692917f30c4d3fe752442ffa2415fd4e6398cb9e378bab963f042ce30ef4363b6ad93b6908b9087905191825260208201526040908101905180910390a45b613bd08683612b5b565b9998505050505050505050565b600554600090819081908190819081908190600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515613c2b57600080fd5b5af11515613c3857600080fd5b505050604051805190509650613c4d896135fb565b9096509450613c5b886135fb565b600160a060020a03808c166000908152601060209081526040808320938e168352929052205491955093508590613c9c90613c969089612d10565b89612d10565b811515613ca557fe5b600160a060020a03808b166000908152601060209081526040808320938f168352929052205491900492508390613ce090613c969087612d10565b811515613ce957fe5b04905060095482101580613cff57506009548110155b15613d1657613d118989610258614646565b6123a7565b6123a789896146e2565b600160a060020a0380851660008181526012602090815260408083209488168084529482528083205460108352818420858552835281842054958452600f835281842094845293825280832087845290915281206001015491929190808080613d898b8b612f96565b93506000881115613de55760408051908101604090815288825260208083018b9052600160a060020a03808f166000908152600f8352838120918f1681529082528281208d825290915220815181556020820151600190910155505b851580613df757508362015180014210155b80613e025750600085115b1561401757600160a060020a03808b166000908152601260209081526040808320938f1683529290522054925084158015613e3d5750600086115b15613ec457604080519081016040528084815260200187815250600f60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b8152602001908152602001600020600082015181556020820151600190910155505b5050600160a060020a03808a166000818152601160208181526040808420958e16808552958252808420549282528084209484529381528383205460108252848420958452949052918120829055909190821115613f4557600160a060020a03808c166000908152601160209081526040808320938e168352929052908120555b6000871115613f7757600160a060020a03808c166000908152601260209081526040808320938e168352929052908120555b600160a060020a03808b166000908152601060209081526040808320938f168352929052908120829055811115613fd157600160a060020a03808b166000908152601160209081526040808320938f168352929052908120555b600083111561400357600160a060020a03808b166000908152601260209081526040808320938f168352929052908120555b61400d8b8b6141a9565b6140178b8b613bdd565b888a600160a060020a03168c600160a060020a03167fb5806f8610464e96807c2b147620cc721c65309647f16cfccdf9fb7bd95152ac8b8b60405191825260208201526040908101905180910390a45050505050505050505050565b600160a060020a0386166000908152600c602052604081205481908190819060ff1680156140b95750600160a060020a0389166000908152600c602052604090205460ff165b1561419c57600454600160a060020a0390811693508a168314156140df5785935061412c565b82600160a060020a031689600160a060020a031614156141015787935061412c565b61410f8a8460018a0361130c565b90925090508061411f8784612d10565b81151561412857fe5b0493505b600084111561419c57600a54600160a060020a031663f0dda65c868660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561418b57600080fd5b5af1151561419857600080fd5b5050505b5050509695505050505050565b6141b38282610dcc565b600160a060020a039182166000908152600d602090815260408083209390941682529190915220805460010190555050565b60008060008060008060006141fa8d8a61104f565b1161420457600080fd5b60006142108c8a61104f565b1161421a57600080fd5b6142238c6135fb565b90955093506142318b6135fb565b9093509150614261846142448c88612d10565b81151561424d57fe5b0483858c0281151561425b57fe5b046121a2565b9050611e578188612d10565b600160a060020a0380851660009081526013602090815260408083203390941683529290529081205481906142a29085612b5b565b600160a060020a03808816600090815260136020818152604080842033861680865290835281852096909655938a168352908152828220938252929092529020546142ed9084612b5b565b600160a060020a03808716600090815260136020908152604080832033909416835292905220556143218686600187613acb565b91506143308587600186613acb565b600160a060020a0380881660008181526010602081815260408084208c87168086529083528185208a90559282528084208585528252808420879055601580835281852084865283528185206001808752908452828620339098168087529784528286208b9055938552825280842094845293815283832091835290815282822093825292909252902081905590506143cc8686615460614646565b84600160a060020a031686600160a060020a03167f6f4b2adffa0c3e90e47fdcd9d2c36f48b57eb3271dce519997271073dac17be960405160405180910390a3505050505050565b6000806000806000806000806144298a6135fb565b9097509550856144398a89612d10565b81151561444257fe5b6005549190049550600160a060020a031663a3ca17b26040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561448657600080fd5b5af1151561449357600080fd5b5050506040518051905093506144a98585612d10565b600b5490935061452890600160a060020a031663dd62ed3e333060405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b151561450857600080fd5b5af1151561451557600080fd5b50505060405180519050600285046122b8565b600b5490925061459c90600160a060020a03166370a082313360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561457f57600080fd5b5af1151561458c57600080fd5b50505060405180519050836122b8565b9150600082111561463557600b54600160a060020a0316634417f4db338460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b15156145fd57600080fd5b5af1151561460a57600080fd5b50505082614618838b612d10565b81151561462157fe5b04905061462e8982612b5b565b9750614639565b8897505b5050505050505092915050565b6000806146538585610dcc565b600160a060020a038083166000818152600d6020908152604080832094861680845294825280832054848452600e835281842086855290925291829020428a0190819055959a5093985093955091935083929091907f20017e7b1ef8e7882103f55ff346ca3135c4afe13dff1da2f01b482aece766a59086905190815260200160405180910390a45050505050565b6146ec8282610dcc565b600160a060020a038083166000908152600e6020908152604080832093851683529290522054919350915060011461474857600160a060020a038083166000908152600e60209081526040808320938516835292905220600190555b5050565b60206040519081016040526000815290565b6040805190810160405260008082526020820152905600a165627a7a723058208234706d1c6efd546ff852e83c41531610f61e18cf7d16f7d8577228a5c5b49d0029

Swarm Source

bzzr://8234706d1c6efd546ff852e83c41531610f61e18cf7d16f7d8577228a5c5b49d
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward