Contract 0x8cf1cab422a0b6b554077a361f8419cdf122a9f9

TxHash Block Age From To Value [TxFee]
0xe579dd8ec23908f7ac6bf143505cefbb76107e9f440244767eec3f983251fc5d1043916120 days 17 hrs ago0x5581364f1350b82ed4e25874f3727395bf6ce490 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000025596
0x8d4fb84337fc35967243228f30811a18cba450f96de6b11c97fa9713a9927f541043914720 days 18 hrs ago0x5581364f1350b82ed4e25874f3727395bf6ce490 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000025596
0x7565ee9bfff31d31a354a9f141848a905931f63439171d75d28be5cf539186a21037709829 days 19 hrs ago0x273fe091e7269d5ad7580beaa71283996f2d3741 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000025596
0xa72b9ccd48e6e3a3b3c0833515aa4faddbe25e8e4767ca0bd85393357aa604391036692131 days 5 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026527
0x1f371823cdafd176ecd4129a71f0f2460982a88586457479caa6388d71e756471036690631 days 6 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026527
0x8923d2d35d9a52d9d689b0c35db8ad2b1fa76eb77b504a62036a5decf7ad87981036689331 days 6 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026527
0x0f8751e6711ad35011c9822b50ede432ea13736906526212c81ff8b21cb4256e1036656831 days 7 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026591
0x30003fc4f3caf22ebe30569652af70bb71bee5332cf1ac91fba704ca9719df501036656031 days 7 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026655
0x769d2a95def4e6dc1170c1313e3faa082604aea79fd3235f4642473752e1ba8e1036655331 days 7 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026527
0x32cc36d8fa0b0d7ee32e142c284ac9fb745eecba68e9cbc70c8475852c6eac361036655131 days 7 hrs ago0xe4bbdf7b3d127af95e4bf577e7828346b7849cf4 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000026527
0x17f9533ad042aaf905adf96b141487cdc92590ff9ffd242f9059af83932462a01017449453 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000057393
0xd77b3c19075e32bab619229e7aafe1f456ddbced8d5377a99f782b526088bc0e1017449353 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059493
0xf4f6b2b890780ffdd9a962d16c4c91ec11ea43095c20120d4ff4ac18a08a50f11017449153 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0x73643d35ba332b219e674c54b9404b9f7fe5ec032a32d6ea16b85fc078eb63da1017449153 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0xa8eb788e5beb44b9a02f52965836f0c2a1ebe6c2fec6c5b7f8cd1fec3fa1cfad1017449053 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000057393
0xc4820824eda4021a374a9a4602dee1a331955072e0f9cbe95df3d388e099db261017448953 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0xe6f14bfaa14256b9475e30316f005dc6cfebc2e7699974dd1f1d4bd5c22485cc1017448953 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0x9e9653870bc196b11e9ba67a7b583c97dd2caf847bb87906fc625dd67df9a63b1017448753 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0x9a520d2885a72b3312c5d299074bc4dd6e2a36ce398fb1fd64a1cd57bc8aec3f1017448653 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0x3185603fbaf72e7e3470265bff9165843c1693fce986924db762c50b71e5f2b01017448653 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059525
0xc3b21320e7a57528699060f2a860b1f8480d8ef48902ea8032fbe04cb0ac2a261017448353 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000057103
0x95fc460bcb87df91318a44e6337aac127f36e851a198567b4176f4b54e150e001017448153 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000057416
0xa49f6631bbbe569cacf9d034abc386e35dd5bc4b0768fb42f273833227ea77d61017448153 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059549
0x0f0a324ba8e5c00ca50a2a23f5fb7dbac8fcce4334a5e169802a8f8e8f886bef1017448053 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000057103
0xa0d050ada6237e3468dcde3c249463c04d14e68ed67c8e1478efe9f4b55a44c41017447953 days 2 hrs ago0xdb33dfd3d61308c33c63209845dad3e6bfb2c674 IN  0x8cf1cab422a0b6b554077a361f8419cdf122a9f90 Ether0.000059236
[ Download CSV Export 

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

Parent TxHash Block Age From To Value
0x17f9533ad042aaf905adf96b141487cdc92590ff9ffd242f9059af83932462a01017449453 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xaaf64bfcc32d0f15873a02163e7e500671a4ffcd0 Ether
0xd77b3c19075e32bab619229e7aafe1f456ddbced8d5377a99f782b526088bc0e1017449353 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xaaf64bfcc32d0f15873a02163e7e500671a4ffcd0 Ether
0xf4f6b2b890780ffdd9a962d16c4c91ec11ea43095c20120d4ff4ac18a08a50f11017449153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xaaf64bfcc32d0f15873a02163e7e500671a4ffcd0 Ether
0x73643d35ba332b219e674c54b9404b9f7fe5ec032a32d6ea16b85fc078eb63da1017449153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xaaf64bfcc32d0f15873a02163e7e500671a4ffcd0 Ether
0xa8eb788e5beb44b9a02f52965836f0c2a1ebe6c2fec6c5b7f8cd1fec3fa1cfad1017449053 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0xc4820824eda4021a374a9a4602dee1a331955072e0f9cbe95df3d388e099db261017448953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0xe6f14bfaa14256b9475e30316f005dc6cfebc2e7699974dd1f1d4bd5c22485cc1017448953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0x9e9653870bc196b11e9ba67a7b583c97dd2caf847bb87906fc625dd67df9a63b1017448753 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0x9a520d2885a72b3312c5d299074bc4dd6e2a36ce398fb1fd64a1cd57bc8aec3f1017448653 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0x3185603fbaf72e7e3470265bff9165843c1693fce986924db762c50b71e5f2b01017448653 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xc4375b7de8af5a38a93548eb8453a498222c4ff20 Ether
0xc3b21320e7a57528699060f2a860b1f8480d8ef48902ea8032fbe04cb0ac2a261017448353 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0x95fc460bcb87df91318a44e6337aac127f36e851a198567b4176f4b54e150e001017448153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90x7352c20e00d3c89037a8959699741c341771ed590 Ether
0xa49f6631bbbe569cacf9d034abc386e35dd5bc4b0768fb42f273833227ea77d61017448153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90x7352c20e00d3c89037a8959699741c341771ed590 Ether
0x0f0a324ba8e5c00ca50a2a23f5fb7dbac8fcce4334a5e169802a8f8e8f886bef1017448053 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0xa0d050ada6237e3468dcde3c249463c04d14e68ed67c8e1478efe9f4b55a44c41017447953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0xd47c403a83a2798e826a2897c47b1ea30f0163b306315fc0111c4bb5fc1a45dc1017447953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0xc446ed78c7f5df28dd6fb2b5f680edba2e42ee814cba4bdf2ac4fbccbc8e3e9f1017447753 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0x620c040a97b7192ff6e108048d2a3ed9d3f393f49f36319ac8fa9d3ae56fc0721017447553 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0xaf5b58662c162346b1c91376ce48f670ac5d32df37e50a39f5ffac86db47b0a41017447453 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xf7d57c676ac2bc4997ca5d4d34adc0d072213d290 Ether
0x9ed0116dcf83d30fa59b3ba910fcad6d9b89d8f938f32ca3cfe9ee6fb94bc8671017447453 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xf7d57c676ac2bc4997ca5d4d34adc0d072213d290 Ether
0xa4d5c0fc2beea426af42bcb13235fc4b42c580db2ef0f9ddd7b4d4c1ac47bd6c1017447253 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xf7d57c676ac2bc4997ca5d4d34adc0d072213d290 Ether
0xf73df03a3b88a72ce0fe53313b55e407d5f2522e619779359c6d469ff1da7af31017447153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xf7d57c676ac2bc4997ca5d4d34adc0d072213d290 Ether
0xd63161a133b388b5e101b94d0083f9da55bd4639e333ec988a772ea7036554331017447153 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0x69cda7433fd444d72bd127f70819cb5ff7c3a41f1db2ef720fd3554125f9b5c31017446953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
0x7c4f0ac020c350f7a63fff5fe9cbfd9bfdf6d2cdc88060bf9ff3efeaf3f8fe021017446953 days 2 hrs ago0x8cf1cab422a0b6b554077a361f8419cdf122a9f90xd0a1e359811322d97991e03f863a0c30c2cf029c0 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0x6b114a72f9f026f2049aa8a1c5c62bb4e44a883c
Contract Name: MatchingMarket
Compiler Version: v0.4.19+commit.c4cbbb05
Optimization Enabled: Yes
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.18;

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);
        }
    }
}

contract DSMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x);
    }
    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x);
    }
    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x);
    }

    function min(uint x, uint y) internal pure returns (uint z) {
        return x <= y ? x : y;
    }
    function max(uint x, uint y) internal pure returns (uint z) {
        return x >= y ? x : y;
    }
    function imin(int x, int y) internal pure returns (int z) {
        return x <= y ? x : y;
    }
    function imax(int x, int y) internal pure returns (int z) {
        return x >= y ? x : y;
    }

    uint constant WAD = 10 ** 18;
    uint constant RAY = 10 ** 27;

    function wmul(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, y), WAD / 2) / WAD;
    }
    function rmul(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, y), RAY / 2) / RAY;
    }
    function wdiv(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, WAD), y / 2) / y;
    }
    function rdiv(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, RAY), y / 2) / y;
    }

    // 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].
    //
    function rpow(uint x, uint n) internal pure returns (uint z) {
        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);
            }
        }
    }
}

contract ERC20Events {
    event Approval(address indexed src, address indexed guy, uint wad);
    event Transfer(address indexed src, address indexed dst, uint wad);
}

contract ERC20 is ERC20Events {
    function totalSupply() public view returns (uint);
    function balanceOf(address guy) public view returns (uint);
    function allowance(address src, address guy) public view returns (uint);

    function approve(address guy, uint wad) public returns (bool);
    function transfer(address dst, uint wad) public returns (bool);
    function transferFrom(
        address src, address dst, uint wad
    ) public returns (bool);
}

contract EventfulMarket {
    event LogItemUpdate(uint id);
    event LogTrade(uint pay_amt, address indexed pay_gem,
                   uint buy_amt, address indexed buy_gem);

    event LogMake(
        bytes32  indexed  id,
        bytes32  indexed  pair,
        address  indexed  maker,
        ERC20             pay_gem,
        ERC20             buy_gem,
        uint128           pay_amt,
        uint128           buy_amt,
        uint64            timestamp
    );

    event LogBump(
        bytes32  indexed  id,
        bytes32  indexed  pair,
        address  indexed  maker,
        ERC20             pay_gem,
        ERC20             buy_gem,
        uint128           pay_amt,
        uint128           buy_amt,
        uint64            timestamp
    );

    event LogTake(
        bytes32           id,
        bytes32  indexed  pair,
        address  indexed  maker,
        ERC20             pay_gem,
        ERC20             buy_gem,
        address  indexed  taker,
        uint128           take_amt,
        uint128           give_amt,
        uint64            timestamp
    );

    event LogKill(
        bytes32  indexed  id,
        bytes32  indexed  pair,
        address  indexed  maker,
        ERC20             pay_gem,
        ERC20             buy_gem,
        uint128           pay_amt,
        uint128           buy_amt,
        uint64            timestamp
    );
}

contract SimpleMarket is EventfulMarket, DSMath {

    uint public last_offer_id;

    mapping (uint => OfferInfo) public offers;

    bool locked;

    struct OfferInfo {
        uint     pay_amt;
        ERC20    pay_gem;
        uint     buy_amt;
        ERC20    buy_gem;
        address  owner;
        uint64   timestamp;
    }

    modifier can_buy(uint id) {
        require(isActive(id));
        _;
    }

    modifier can_cancel(uint id) {
        require(isActive(id));
        require(getOwner(id) == msg.sender);
        _;
    }

    modifier can_offer {
        _;
    }

    modifier synchronized {
        require(!locked);
        locked = true;
        _;
        locked = false;
    }

    function isActive(uint id) public constant returns (bool active) {
        return offers[id].timestamp > 0;
    }

    function getOwner(uint id) public constant returns (address owner) {
        return offers[id].owner;
    }

    function getOffer(uint id) public constant returns (uint, ERC20, uint, ERC20) {
      var offer = offers[id];
      return (offer.pay_amt, offer.pay_gem,
              offer.buy_amt, offer.buy_gem);
    }

    // ---- Public entrypoints ---- //

    function bump(bytes32 id_)
        public
        can_buy(uint256(id_))
    {
        var id = uint256(id_);
        LogBump(
            id_,
            keccak256(offers[id].pay_gem, offers[id].buy_gem),
            offers[id].owner,
            offers[id].pay_gem,
            offers[id].buy_gem,
            uint128(offers[id].pay_amt),
            uint128(offers[id].buy_amt),
            offers[id].timestamp
        );
    }

    // Accept given `quantity` of an offer. Transfers funds from caller to
    // offer maker, and from market to caller.
    function buy(uint id, uint quantity)
        public
        can_buy(id)
        synchronized
        returns (bool)
    {
        OfferInfo memory offer = offers[id];
        uint spend = mul(quantity, offer.buy_amt) / offer.pay_amt;

        require(uint128(spend) == spend);
        require(uint128(quantity) == quantity);

        // For backwards semantic compatibility.
        if (quantity == 0 || spend == 0 ||
            quantity > offer.pay_amt || spend > offer.buy_amt)
        {
            return false;
        }

        offers[id].pay_amt = sub(offer.pay_amt, quantity);
        offers[id].buy_amt = sub(offer.buy_amt, spend);
        require( offer.buy_gem.transferFrom(msg.sender, offer.owner, spend) );
        require( offer.pay_gem.transfer(msg.sender, quantity) );

        LogItemUpdate(id);
        LogTake(
            bytes32(id),
            keccak256(offer.pay_gem, offer.buy_gem),
            offer.owner,
            offer.pay_gem,
            offer.buy_gem,
            msg.sender,
            uint128(quantity),
            uint128(spend),
            uint64(now)
        );
        LogTrade(quantity, offer.pay_gem, spend, offer.buy_gem);

        if (offers[id].pay_amt == 0) {
          delete offers[id];
        }

        return true;
    }

    // Cancel an offer. Refunds offer maker.
    function cancel(uint id)
        public
        can_cancel(id)
        synchronized
        returns (bool success)
    {
        // read-only offer. Modify an offer by directly accessing offers[id]
        OfferInfo memory offer = offers[id];
        delete offers[id];

        require( offer.pay_gem.transfer(offer.owner, offer.pay_amt) );

        LogItemUpdate(id);
        LogKill(
            bytes32(id),
            keccak256(offer.pay_gem, offer.buy_gem),
            offer.owner,
            offer.pay_gem,
            offer.buy_gem,
            uint128(offer.pay_amt),
            uint128(offer.buy_amt),
            uint64(now)
        );

        success = true;
    }

    function kill(bytes32 id)
        public
    {
        require(cancel(uint256(id)));
    }

    function make(
        ERC20    pay_gem,
        ERC20    buy_gem,
        uint128  pay_amt,
        uint128  buy_amt
    )
        public
        returns (bytes32 id)
    {
        return bytes32(offer(pay_amt, pay_gem, buy_amt, buy_gem));
    }

    // Make a new offer. Takes funds from the caller into market escrow.
    function offer(uint pay_amt, ERC20 pay_gem, uint buy_amt, ERC20 buy_gem)
        public
        can_offer
        synchronized
        returns (uint id)
    {
        require(uint128(pay_amt) == pay_amt);
        require(uint128(buy_amt) == buy_amt);
        require(pay_amt > 0);
        require(pay_gem != ERC20(0x0));
        require(buy_amt > 0);
        require(buy_gem != ERC20(0x0));
        require(pay_gem != buy_gem);

        OfferInfo memory info;
        info.pay_amt = pay_amt;
        info.pay_gem = pay_gem;
        info.buy_amt = buy_amt;
        info.buy_gem = buy_gem;
        info.owner = msg.sender;
        info.timestamp = uint64(now);
        id = _next_id();
        offers[id] = info;

        require( pay_gem.transferFrom(msg.sender, this, pay_amt) );

        LogItemUpdate(id);
        LogMake(
            bytes32(id),
            keccak256(pay_gem, buy_gem),
            msg.sender,
            pay_gem,
            buy_gem,
            uint128(pay_amt),
            uint128(buy_amt),
            uint64(now)
        );
    }

    function take(bytes32 id, uint128 maxTakeAmount)
        public
    {
        require(buy(uint256(id), maxTakeAmount));
    }

    function _next_id()
        internal
        returns (uint)
    {
        last_offer_id++; return last_offer_id;
    }
}

// Simple Market with a market lifetime. When the close_time has been reached,
// offers can only be cancelled (offer and buy will throw).

contract ExpiringMarket is DSAuth, SimpleMarket {
    uint64 public close_time;
    bool public stopped;

    // after close_time has been reached, no new offers are allowed
    modifier can_offer {
        require(!isClosed());
        _;
    }

    // after close, no new buys are allowed
    modifier can_buy(uint id) {
        require(isActive(id));
        require(!isClosed());
        _;
    }

    // after close, anyone can cancel an offer
    modifier can_cancel(uint id) {
        require(isActive(id));
        require(isClosed() || (msg.sender == getOwner(id)));
        _;
    }

    function ExpiringMarket(uint64 _close_time)
        public
    {
        close_time = _close_time;
    }

    function isClosed() public constant returns (bool closed) {
        return stopped || getTime() > close_time;
    }

    function getTime() public constant returns (uint64) {
        return uint64(now);
    }

    function stop() public auth {
        stopped = true;
    }
}

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);

        _;
    }
}

contract MatchingEvents {
    event LogBuyEnabled(bool isEnabled);
    event LogMinSell(address pay_gem, uint min_amount);
    event LogMatchingEnabled(bool isEnabled);
    event LogUnsortedOffer(uint id);
    event LogSortedOffer(uint id);
    event LogAddTokenPairWhitelist(ERC20 baseToken, ERC20 quoteToken);
    event LogRemTokenPairWhitelist(ERC20 baseToken, ERC20 quoteToken);
    event LogInsert(address keeper, uint id);
    event LogDelete(address keeper, uint id);
}

contract MatchingMarket is MatchingEvents, ExpiringMarket, DSNote {
    bool public buyEnabled = true;      //buy enabled
    bool public matchingEnabled = true; //true: enable matching,
                                         //false: revert to expiring market
    struct sortInfo {
        uint next;  //points to id of next higher offer
        uint prev;  //points to id of previous lower offer
        uint delb;  //the blocknumber where this entry was marked for delete
    }
    mapping(uint => sortInfo) public _rank;                     //doubly linked lists of sorted offer ids
    mapping(address => mapping(address => uint)) public _best;  //id of the highest offer for a token pair
    mapping(address => mapping(address => uint)) public _span;  //number of offers stored for token pair in sorted orderbook
    mapping(address => uint) public _dust;                      //minimum sell amount for a token to avoid dust offers
    mapping(uint => uint) public _near;         //next unsorted offer id
    mapping(bytes32 => bool) public _menu;      //whitelist tracking which token pairs can be traded
    uint _head;                                 //first unsorted offer id

    //check if token pair is enabled
    modifier isWhitelist(ERC20 buy_gem, ERC20 pay_gem) {
        require(_menu[keccak256(buy_gem, pay_gem)] || _menu[keccak256(pay_gem, buy_gem)]);
        _;
    }

    function MatchingMarket(uint64 close_time) ExpiringMarket(close_time) public {
    }

    // ---- Public entrypoints ---- //

    function make(
        ERC20    pay_gem,
        ERC20    buy_gem,
        uint128  pay_amt,
        uint128  buy_amt
    )
        public
        returns (bytes32)
    {
        return bytes32(offer(pay_amt, pay_gem, buy_amt, buy_gem));
    }

    function take(bytes32 id, uint128 maxTakeAmount) public {
        require(buy(uint256(id), maxTakeAmount));
    }

    function kill(bytes32 id) public {
        require(cancel(uint256(id)));
    }

    // Make a new offer. Takes funds from the caller into market escrow.
    //
    // If matching is enabled:
    //     * creates new offer without putting it in
    //       the sorted list.
    //     * available to authorized contracts only!
    //     * keepers should call insert(id,pos)
    //       to put offer in the sorted list.
    //
    // If matching is disabled:
    //     * calls expiring market's offer().
    //     * available to everyone without authorization.
    //     * no sorting is done.
    //
    function offer(
        uint pay_amt,    //maker (ask) sell how much
        ERC20 pay_gem,   //maker (ask) sell which token
        uint buy_amt,    //taker (ask) buy how much
        ERC20 buy_gem    //taker (ask) buy which token
    )
        public
        isWhitelist(pay_gem, buy_gem)
        /* NOT synchronized!!! */
        returns (uint)
    {
        var fn = matchingEnabled ? _offeru : super.offer;
        return fn(pay_amt, pay_gem, buy_amt, buy_gem);
    }

    // Make a new offer. Takes funds from the caller into market escrow.
    function offer(
        uint pay_amt,    //maker (ask) sell how much
        ERC20 pay_gem,   //maker (ask) sell which token
        uint buy_amt,    //maker (ask) buy how much
        ERC20 buy_gem,   //maker (ask) buy which token
        uint pos         //position to insert offer, 0 should be used if unknown
    )
        public
        isWhitelist(pay_gem, buy_gem)
        /*NOT synchronized!!! */
        can_offer
        returns (uint)
    {
        return offer(pay_amt, pay_gem, buy_amt, buy_gem, pos, false);
    }

    function offer(
        uint pay_amt,    //maker (ask) sell how much
        ERC20 pay_gem,   //maker (ask) sell which token
        uint buy_amt,    //maker (ask) buy how much
        ERC20 buy_gem,   //maker (ask) buy which token
        uint pos,        //position to insert offer, 0 should be used if unknown
        bool rounding    //match "close enough" orders?
    )
        public
        isWhitelist(pay_gem, buy_gem)
        /*NOT synchronized!!! */
        can_offer
        returns (uint)
    {
        require(_dust[pay_gem] <= pay_amt);

        if (matchingEnabled) {
          return _matcho(pay_amt, pay_gem, buy_amt, buy_gem, pos, rounding);
        }
        return super.offer(pay_amt, pay_gem, buy_amt, buy_gem);
    }

    //Transfers funds from caller to offer maker, and from market to caller.
    function buy(uint id, uint amount)
        public
        /*NOT synchronized!!! */
        can_buy(id)
        returns (bool)
    {
        var fn = matchingEnabled ? _buys : super.buy;
        return fn(id, amount);
    }

    // Cancel an offer. Refunds offer maker.
    function cancel(uint id)
        public
        /*NOT synchronized!!! */
        can_cancel(id)
        returns (bool success)
    {
        if (matchingEnabled) {
            if (isOfferSorted(id)) {
                require(_unsort(id));
            } else {
                require(_hide(id));
            }
        }
        return super.cancel(id);    //delete the offer.
    }

    //insert offer into the sorted list
    //keepers need to use this function
    function insert(
        uint id,   //maker (ask) id
        uint pos   //position to insert into
    )
        public
        returns (bool)
    {
        require(!isOfferSorted(id));    //make sure offers[id] is not yet sorted
        require(isActive(id));          //make sure offers[id] is active

        _hide(id);                      //remove offer from unsorted offers list
        _sort(id, pos);                 //put offer into the sorted offers list
        LogInsert(msg.sender, id);
        return true;
    }

    //deletes _rank [id]
    //  Function should be called by keepers.
    function del_rank(uint id)
        public
    returns (bool)
    {
        require(!isActive(id) && _rank[id].delb != 0 && _rank[id].delb < block.number - 10);
        delete _rank[id];
        LogDelete(msg.sender, id);
        return true;
    }

    //returns true if token is succesfully added to whitelist
    //  Function is used to add a token pair to the whitelist
    //  All incoming offers are checked against the whitelist.
    function addTokenPairWhitelist(
        ERC20 baseToken,
        ERC20 quoteToken
    )
        public
        auth
        note
    returns (bool)
    {
        require(!isTokenPairWhitelisted(baseToken, quoteToken));
        require(address(baseToken) != 0x0 && address(quoteToken) != 0x0);

        _menu[keccak256(baseToken, quoteToken)] = true;
        LogAddTokenPairWhitelist(baseToken, quoteToken);
        return true;
    }

    //returns true if token is successfully removed from whitelist
    //  Function is used to remove a token pair from the whitelist.
    //  All incoming offers are checked against the whitelist.
    function remTokenPairWhitelist(
        ERC20 baseToken,
        ERC20 quoteToken
    )
        public
        auth
        note
    returns (bool)
    {
        require(isTokenPairWhitelisted(baseToken, quoteToken));

        delete _menu[keccak256(baseToken, quoteToken)];
        delete _menu[keccak256(quoteToken, baseToken)];
        LogRemTokenPairWhitelist(baseToken, quoteToken);
        return true;
    }

    function isTokenPairWhitelisted(
        ERC20 baseToken,
        ERC20 quoteToken
    )
        public
        constant
        returns (bool)
    {
        return (_menu[keccak256(baseToken, quoteToken)] || _menu[keccak256(quoteToken, baseToken)]);
    }

    //set the minimum sell amount for a token
    //    Function is used to avoid "dust offers" that have
    //    very small amount of tokens to sell, and it would
    //    cost more gas to accept the offer, than the value
    //    of tokens received.
    function setMinSell(
        ERC20 pay_gem,     //token to assign minimum sell amount to
        uint dust          //maker (ask) minimum sell amount
    )
        public
        auth
        note
        returns (bool)
    {
        _dust[pay_gem] = dust;
        LogMinSell(pay_gem, dust);
        return true;
    }

    //returns the minimum sell amount for an offer
    function getMinSell(
        ERC20 pay_gem      //token for which minimum sell amount is queried
    )
        public
        constant
        returns (uint)
    {
        return _dust[pay_gem];
    }

    //set buy functionality enabled/disabled
    function setBuyEnabled(bool buyEnabled_) public auth returns (bool) {
        buyEnabled = buyEnabled_;
        LogBuyEnabled(buyEnabled);
        return true;
    }

    //set matching enabled/disabled
    //    If matchingEnabled true(default), then inserted offers are matched.
    //    Except the ones inserted by contracts, because those end up
    //    in the unsorted list of offers, that must be later sorted by
    //    keepers using insert().
    //    If matchingEnabled is false then MatchingMarket is reverted to ExpiringMarket,
    //    and matching is not done, and sorted lists are disabled.
    function setMatchingEnabled(bool matchingEnabled_) public auth returns (bool) {
        matchingEnabled = matchingEnabled_;
        LogMatchingEnabled(matchingEnabled);
        return true;
    }

    //return the best offer for a token pair
    //      the best offer is the lowest one if it's an ask,
    //      and highest one if it's a bid offer
    function getBestOffer(ERC20 sell_gem, ERC20 buy_gem) public constant returns(uint) {
        return _best[sell_gem][buy_gem];
    }

    //return the next worse offer in the sorted list
    //      the worse offer is the higher one if its an ask,
    //      a lower one if its a bid offer,
    //      and in both cases the newer one if they're equal.
    function getWorseOffer(uint id) public constant returns(uint) {
        return _rank[id].prev;
    }

    //return the next better offer in the sorted list
    //      the better offer is in the lower priced one if its an ask,
    //      the next higher priced one if its a bid offer
    //      and in both cases the older one if they're equal.
    function getBetterOffer(uint id) public constant returns(uint) {

        return _rank[id].next;
    }

    //return the amount of better offers for a token pair
    function getOfferCount(ERC20 sell_gem, ERC20 buy_gem) public constant returns(uint) {
        return _span[sell_gem][buy_gem];
    }

    //get the first unsorted offer that was inserted by a contract
    //      Contracts can't calculate the insertion position of their offer because it is not an O(1) operation.
    //      Their offers get put in the unsorted list of offers.
    //      Keepers can calculate the insertion position offchain and pass it to the insert() function to insert
    //      the unsorted offer into the sorted list. Unsorted offers will not be matched, but can be bought with buy().
    function getFirstUnsortedOffer() public constant returns(uint) {
        return _head;
    }

    //get the next unsorted offer
    //      Can be used to cycle through all the unsorted offers.
    function getNextUnsortedOffer(uint id) public constant returns(uint) {
        return _near[id];
    }

    function isOfferSorted(uint id) public constant returns(bool) {
        return _rank[id].next != 0
               || _rank[id].prev != 0
               || _best[offers[id].pay_gem][offers[id].buy_gem] == id;
    }

    function sellAllAmount(ERC20 pay_gem, uint pay_amt, ERC20 buy_gem, uint min_fill_amount)
        public
        returns (uint fill_amt)
    {
        uint offerId;
        while (pay_amt > 0) {                           //while there is amount to sell
            offerId = getBestOffer(buy_gem, pay_gem);   //Get the best offer for the token pair
            require(offerId != 0);                      //Fails if there are not more offers

            // There is a chance that pay_amt is smaller than 1 wei of the other token
            if (pay_amt * 1 ether < wdiv(offers[offerId].buy_amt, offers[offerId].pay_amt)) {
                break;                                  //We consider that all amount is sold
            }
            if (pay_amt >= offers[offerId].buy_amt) {                       //If amount to sell is higher or equal than current offer amount to buy
                fill_amt = add(fill_amt, offers[offerId].pay_amt);          //Add amount bought to acumulator
                pay_amt = sub(pay_amt, offers[offerId].buy_amt);            //Decrease amount to sell
                take(bytes32(offerId), uint128(offers[offerId].pay_amt));   //We take the whole offer
            } else { // if lower
                var baux = rmul(pay_amt * 10 ** 9, rdiv(offers[offerId].pay_amt, offers[offerId].buy_amt)) / 10 ** 9;
                fill_amt = add(fill_amt, baux);         //Add amount bought to acumulator
                take(bytes32(offerId), uint128(baux));  //We take the portion of the offer that we need
                pay_amt = 0;                            //All amount is sold
            }
        }
        require(fill_amt >= min_fill_amount);
    }

    function buyAllAmount(ERC20 buy_gem, uint buy_amt, ERC20 pay_gem, uint max_fill_amount)
        public
        returns (uint fill_amt)
    {
        uint offerId;
        while (buy_amt > 0) {                           //Meanwhile there is amount to buy
            offerId = getBestOffer(buy_gem, pay_gem);   //Get the best offer for the token pair
            require(offerId != 0);

            // There is a chance that buy_amt is smaller than 1 wei of the other token
            if (buy_amt * 1 ether < wdiv(offers[offerId].pay_amt, offers[offerId].buy_amt)) {
                break;                                  //We consider that all amount is sold
            }
            if (buy_amt >= offers[offerId].pay_amt) {                       //If amount to buy is higher or equal than current offer amount to sell
                fill_amt = add(fill_amt, offers[offerId].buy_amt);          //Add amount sold to acumulator
                buy_amt = sub(buy_amt, offers[offerId].pay_amt);            //Decrease amount to buy
                take(bytes32(offerId), uint128(offers[offerId].pay_amt));   //We take the whole offer
            } else {                                                        //if lower
                fill_amt = add(fill_amt, rmul(buy_amt * 10 ** 9, rdiv(offers[offerId].buy_amt, offers[offerId].pay_amt)) / 10 ** 9); //Add amount sold to acumulator
                take(bytes32(offerId), uint128(buy_amt));                   //We take the portion of the offer that we need
                buy_amt = 0;                                                //All amount is bought
            }
        }
        require(fill_amt <= max_fill_amount);
    }

    function getBuyAmount(ERC20 buy_gem, ERC20 pay_gem, uint pay_amt) public constant returns (uint fill_amt) {
        var offerId = getBestOffer(buy_gem, pay_gem);           //Get best offer for the token pair
        while (pay_amt > offers[offerId].buy_amt) {
            fill_amt = add(fill_amt, offers[offerId].pay_amt);  //Add amount to buy accumulator
            pay_amt = sub(pay_amt, offers[offerId].buy_amt);    //Decrease amount to pay
            if (pay_amt > 0) {                                  //If we still need more offers
                offerId = getWorseOffer(offerId);               //We look for the next best offer
                require(offerId != 0);                          //Fails if there are not enough offers to complete
            }
        }
        fill_amt = add(fill_amt, rmul(pay_amt * 10 ** 9, rdiv(offers[offerId].pay_amt, offers[offerId].buy_amt)) / 10 ** 9); //Add proportional amount of last offer to buy accumulator
    }

    function getPayAmount(ERC20 pay_gem, ERC20 buy_gem, uint buy_amt) public constant returns (uint fill_amt) {
        var offerId = getBestOffer(buy_gem, pay_gem);           //Get best offer for the token pair
        while (buy_amt > offers[offerId].pay_amt) {
            fill_amt = add(fill_amt, offers[offerId].buy_amt);  //Add amount to pay accumulator
            buy_amt = sub(buy_amt, offers[offerId].pay_amt);    //Decrease amount to buy
            if (buy_amt > 0) {                                  //If we still need more offers
                offerId = getWorseOffer(offerId);               //We look for the next best offer
                require(offerId != 0);                          //Fails if there are not enough offers to complete
            }
        }
        fill_amt = add(fill_amt, rmul(buy_amt * 10 ** 9, rdiv(offers[offerId].buy_amt, offers[offerId].pay_amt)) / 10 ** 9); //Add proportional amount of last offer to pay accumulator
    }

    // ---- Internal Functions ---- //

    function _buys(uint id, uint amount)
        internal
        returns (bool)
    {
        require(buyEnabled);

        if (amount == offers[id].pay_amt && isOfferSorted(id)) {
            //offers[id] must be removed from sorted list because all of it is bought
            _unsort(id);
        }
        require(super.buy(id, amount));
        return true;
    }

    //find the id of the next higher offer after offers[id]
    function _find(uint id)
        internal
        view
        returns (uint)
    {
        require( id > 0 );

        address buy_gem = address(offers[id].buy_gem);
        address pay_gem = address(offers[id].pay_gem);
        uint top = _best[pay_gem][buy_gem];
        uint old_top = 0;

        // Find the larger-than-id order whose successor is less-than-id.
        while (top != 0 && _isPricedLtOrEq(id, top)) {
            old_top = top;
            top = _rank[top].prev;
        }
        return old_top;
    }

    //find the id of the next higher offer after offers[id]
    function _findpos(uint id, uint pos)
        internal
        view
    returns (uint)
    {
        require(id > 0);

        // Look for an active order.
        while (pos != 0 && !isActive(pos)) {
            pos = _rank[pos].prev;
        }

        if (pos == 0) {
            //if we got to the end of list without a single active offer
            return _find(id);

        } else {
            // if we did find a nearby active offer
            // Walk the order book down from there...
            if(_isPricedLtOrEq(id, pos)) {
                uint old_pos;

                // Guaranteed to run at least once because of
                // the prior if statements.
                while (pos != 0 && _isPricedLtOrEq(id, pos)) {
                    old_pos = pos;
                    pos = _rank[pos].prev;
                }
                return old_pos;

            // ...or walk it up.
            } else {
                while (pos != 0 && !_isPricedLtOrEq(id, pos)) {
                    pos = _rank[pos].next;
                }
                return pos;
            }
        }
    }

    //return true if offers[low] priced less than or equal to offers[high]
    function _isPricedLtOrEq(
        uint low,   //lower priced offer's id
        uint high   //higher priced offer's id
    )
        internal
        view
        returns (bool)
    {
        return mul(offers[low].buy_amt, offers[high].pay_amt)
          >= mul(offers[high].buy_amt, offers[low].pay_amt);
    }

    //these variables are global only because of solidity local variable limit

    //match offers with taker offer, and execute token transactions
    function _matcho(
        uint t_pay_amt,    //taker sell how much
        ERC20 t_pay_gem,   //taker sell which token
        uint t_buy_amt,    //taker buy how much
        ERC20 t_buy_gem,   //taker buy which token
        uint pos,          //position id
        bool rounding      //match "close enough" orders?
    )
        internal
        returns (uint id)
    {
        uint best_maker_id;    //highest maker id
        uint t_buy_amt_old;    //taker buy how much saved
        uint m_buy_amt;        //maker offer wants to buy this much token
        uint m_pay_amt;        //maker offer wants to sell this much token

        // there is at least one offer stored for token pair
        while (_best[t_buy_gem][t_pay_gem] > 0) {
            best_maker_id = _best[t_buy_gem][t_pay_gem];
            m_buy_amt = offers[best_maker_id].buy_amt;
            m_pay_amt = offers[best_maker_id].pay_amt;

            // Ugly hack to work around rounding errors. Based on the idea that
            // the furthest the amounts can stray from their "true" values is 1.
            // Ergo the worst case has t_pay_amt and m_pay_amt at +1 away from
            // their "correct" values and m_buy_amt and t_buy_amt at -1.
            // Since (c - 1) * (d - 1) > (a + 1) * (b + 1) is equivalent to
            // c * d > a * b + a + b + c + d, we write...
            if (mul(m_buy_amt, t_buy_amt) > mul(t_pay_amt, m_pay_amt) +
                (rounding ? m_buy_amt + t_buy_amt + t_pay_amt + m_pay_amt : 0))
            {
                break;
            }
            // ^ The `rounding` parameter is a compromise borne of a couple days
            // of discussion.

            buy(best_maker_id, min(m_pay_amt, t_buy_amt));
            t_buy_amt_old = t_buy_amt;
            t_buy_amt = sub(t_buy_amt, min(m_pay_amt, t_buy_amt));
            t_pay_amt = mul(t_buy_amt, t_pay_amt) / t_buy_amt_old;

            if (t_pay_amt == 0 || t_buy_amt == 0) {
                break;
            }
        }

        if (t_buy_amt > 0 && t_pay_amt > 0) {
            //new offer should be created
            id = super.offer(t_pay_amt, t_pay_gem, t_buy_amt, t_buy_gem);
            //insert offer into the sorted list
            _sort(id, pos);
        }
    }

    // Make a new offer without putting it in the sorted list.
    // Takes funds from the caller into market escrow.
    // ****Available to authorized contracts only!**********
    // Keepers should call insert(id,pos) to put offer in the sorted list.
    function _offeru(
        uint pay_amt,      //maker (ask) sell how much
        ERC20 pay_gem,     //maker (ask) sell which token
        uint buy_amt,      //maker (ask) buy how much
        ERC20 buy_gem      //maker (ask) buy which token
    )
        internal
        /*NOT synchronized!!! */
        returns (uint id)
    {
        require(_dust[pay_gem] <= pay_amt);
        id = super.offer(pay_amt, pay_gem, buy_amt, buy_gem);
        _near[id] = _head;
        _head = id;
        LogUnsortedOffer(id);
    }

    //put offer into the sorted list
    function _sort(
        uint id,    //maker (ask) id
        uint pos    //position to insert into
    )
        internal
    {
        require(isActive(id));

        address buy_gem = address(offers[id].buy_gem);
        address pay_gem = address(offers[id].pay_gem);
        uint prev_id;                                      //maker (ask) id

        if (pos == 0 || !isOfferSorted(pos)) {
            pos = _find(id);
        } else {
            pos = _findpos(id, pos);

            //if user has entered a `pos` that belongs to another currency pair
            //we start from scratch
            if(pos != 0 && (offers[pos].pay_gem != offers[id].pay_gem
                      || offers[pos].buy_gem != offers[id].buy_gem))
            {
                pos = 0;
                pos=_find(id);
            }
        }


        //requirement below is satisfied by statements above
        //require(pos == 0 || isOfferSorted(pos));


        if (pos != 0) {                                    //offers[id] is not the highest offer
            //requirement below is satisfied by statements above
            //require(_isPricedLtOrEq(id, pos));
            prev_id = _rank[pos].prev;
            _rank[pos].prev = id;
            _rank[id].next = pos;
        } else {                                           //offers[id] is the highest offer
            prev_id = _best[pay_gem][buy_gem];
            _best[pay_gem][buy_gem] = id;
        }

        if (prev_id != 0) {                               //if lower offer does exist
            //requirement below is satisfied by statements above
            //require(!_isPricedLtOrEq(id, prev_id));
            _rank[prev_id].next = id;
            _rank[id].prev = prev_id;
        }

        _span[pay_gem][buy_gem]++;
        LogSortedOffer(id);
    }

    // Remove offer from the sorted list (does not cancel offer)
    function _unsort(
        uint id    //id of maker (ask) offer to remove from sorted list
    )
        internal
        returns (bool)
    {
        address buy_gem = address(offers[id].buy_gem);
        address pay_gem = address(offers[id].pay_gem);
        require(_span[pay_gem][buy_gem] > 0);

        require(_rank[id].delb == 0 &&                    //assert id is in the sorted list
                 isOfferSorted(id));

        if (id != _best[pay_gem][buy_gem]) {              // offers[id] is not the highest offer
            require(_rank[_rank[id].next].prev == id);
            _rank[_rank[id].next].prev = _rank[id].prev;
        } else {                                          //offers[id] is the highest offer
            _best[pay_gem][buy_gem] = _rank[id].prev;
        }

        if (_rank[id].prev != 0) {                        //offers[id] is not the lowest offer
            require(_rank[_rank[id].prev].next == id);
            _rank[_rank[id].prev].next = _rank[id].next;
        }

        _span[pay_gem][buy_gem]--;
        _rank[id].delb = block.number;                    //mark _rank[id] for deletion
        return true;
    }

    //Hide offer from the unsorted order book (does not cancel offer)
    function _hide(
        uint id     //id of maker offer to remove from unsorted list
    )
        internal
        returns (bool)
    {
        uint uid = _head;               //id of an offer in unsorted offers list
        uint pre = uid;                 //id of previous offer in unsorted offers list

        require(!isOfferSorted(id));    //make sure offer id is not in sorted offers list

        if (_head == id) {              //check if offer is first offer in unsorted offers list
            _head = _near[id];          //set head to new first unsorted offer
            _near[id] = 0;              //delete order from unsorted order list
            return true;
        }
        while (uid > 0 && uid != id) {  //find offer in unsorted order list
            pre = uid;
            uid = _near[uid];
        }
        if (uid != id) {                //did not find offer id in unsorted offers list
            return false;
        }
        _near[pre] = _near[id];         //set previous unsorted offer to point to offer after offer id
        _near[id] = 0;                  //delete order from unsorted order list
        return true;
    }
}

Contract ABI
[{"constant":true,"inputs":[],"name":"matchingEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"sell_gem","type":"address"},{"name":"buy_gem","type":"address"}],"name":"getBestOffer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"pay_gem","type":"address"},{"name":"pay_amt","type":"uint256"},{"name":"buy_gem","type":"address"},{"name":"min_fill_amount","type":"uint256"}],"name":"sellAllAmount","outputs":[{"name":"fill_amt","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pay_gem","type":"address"},{"name":"buy_gem","type":"address"},{"name":"pay_amt","type":"uint128"},{"name":"buy_amt","type":"uint128"}],"name":"make","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"buy_gem","type":"address"},{"name":"pay_gem","type":"address"},{"name":"pay_amt","type":"uint256"}],"name":"getBuyAmount","outputs":[{"name":"fill_amt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"baseToken","type":"address"},{"name":"quoteToken","type":"address"}],"name":"addTokenPairWhitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"baseToken","type":"address"},{"name":"quoteToken","type":"address"}],"name":"remTokenPairWhitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pay_amt","type":"uint256"},{"name":"pay_gem","type":"address"},{"name":"buy_amt","type":"uint256"},{"name":"buy_gem","type":"address"},{"name":"pos","type":"uint256"}],"name":"offer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"pos","type":"uint256"}],"name":"insert","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"last_offer_id","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"matchingEnabled_","type":"bool"}],"name":"setMatchingEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"cancel","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getOffer","outputs":[{"name":"","type":"uint256"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"del_rank","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"bytes32"},{"name":"maxTakeAmount","type":"uint128"}],"name":"take","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"pay_gem","type":"address"}],"name":"getMinSell","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTime","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getNextUnsortedOffer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"close_time","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"_span","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"_best","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id_","type":"bytes32"}],"name":"bump","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"sell_gem","type":"address"},{"name":"buy_gem","type":"address"}],"name":"getOfferCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"buy_gem","type":"address"},{"name":"buy_amt","type":"uint256"},{"name":"pay_gem","type":"address"},{"name":"max_fill_amount","type":"uint256"}],"name":"buyAllAmount","outputs":[{"name":"fill_amt","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"isActive","outputs":[{"name":"active","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"offers","outputs":[{"name":"pay_amt","type":"uint256"},{"name":"pay_gem","type":"address"},{"name":"buy_amt","type":"uint256"},{"name":"buy_gem","type":"address"},{"name":"owner","type":"address"},{"name":"timestamp","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getFirstUnsortedOffer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"baseToken","type":"address"},{"name":"quoteToken","type":"address"}],"name":"isTokenPairWhitelisted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getBetterOffer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"_dust","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getWorseOffer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"_menu","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"_near","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"bytes32"}],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pay_gem","type":"address"},{"name":"dust","type":"uint256"}],"name":"setMinSell","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isClosed","outputs":[{"name":"closed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"_rank","outputs":[{"name":"next","type":"uint256"},{"name":"prev","type":"uint256"},{"name":"delb","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getOwner","outputs":[{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"isOfferSorted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"buyEnabled_","type":"bool"}],"name":"setBuyEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"amount","type":"uint256"}],"name":"buy","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pay_amt","type":"uint256"},{"name":"pay_gem","type":"address"},{"name":"buy_amt","type":"uint256"},{"name":"buy_gem","type":"address"},{"name":"pos","type":"uint256"},{"name":"rounding","type":"bool"}],"name":"offer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pay_amt","type":"uint256"},{"name":"pay_gem","type":"address"},{"name":"buy_amt","type":"uint256"},{"name":"buy_gem","type":"address"}],"name":"offer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"buyEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"pay_gem","type":"address"},{"name":"buy_gem","type":"address"},{"name":"buy_amt","type":"uint256"}],"name":"getPayAmount","outputs":[{"name":"fill_amt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"close_time","type":"uint64"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"}],"name":"LogItemUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pay_amt","type":"uint256"},{"indexed":true,"name":"pay_gem","type":"address"},{"indexed":false,"name":"buy_amt","type":"uint256"},{"indexed":true,"name":"buy_gem","type":"address"}],"name":"LogTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"pair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"pay_gem","type":"address"},{"indexed":false,"name":"buy_gem","type":"address"},{"indexed":false,"name":"pay_amt","type":"uint128"},{"indexed":false,"name":"buy_amt","type":"uint128"},{"indexed":false,"name":"timestamp","type":"uint64"}],"name":"LogMake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"pair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"pay_gem","type":"address"},{"indexed":false,"name":"buy_gem","type":"address"},{"indexed":false,"name":"pay_amt","type":"uint128"},{"indexed":false,"name":"buy_amt","type":"uint128"},{"indexed":false,"name":"timestamp","type":"uint64"}],"name":"LogBump","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"bytes32"},{"indexed":true,"name":"pair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"pay_gem","type":"address"},{"indexed":false,"name":"buy_gem","type":"address"},{"indexed":true,"name":"taker","type":"address"},{"indexed":false,"name":"take_amt","type":"uint128"},{"indexed":false,"name":"give_amt","type":"uint128"},{"indexed":false,"name":"timestamp","type":"uint64"}],"name":"LogTake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"pair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"pay_gem","type":"address"},{"indexed":false,"name":"buy_gem","type":"address"},{"indexed":false,"name":"pay_amt","type":"uint128"},{"indexed":false,"name":"buy_amt","type":"uint128"},{"indexed":false,"name":"timestamp","type":"uint64"}],"name":"LogKill","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"isEnabled","type":"bool"}],"name":"LogBuyEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pay_gem","type":"address"},{"indexed":false,"name":"min_amount","type":"uint256"}],"name":"LogMinSell","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"isEnabled","type":"bool"}],"name":"LogMatchingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"}],"name":"LogUnsortedOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"}],"name":"LogSortedOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"baseToken","type":"address"},{"indexed":false,"name":"quoteToken","type":"address"}],"name":"LogAddTokenPairWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"baseToken","type":"address"},{"indexed":false,"name":"quoteToken","type":"address"}],"name":"LogRemTokenPairWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keeper","type":"address"},{"indexed":false,"name":"id","type":"uint256"}],"name":"LogInsert","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keeper","type":"address"},{"indexed":false,"name":"id","type":"uint256"}],"name":"LogDelete","type":"event"}]

Contract Creation Code
606060405260048054605860020a60ff0219605060020a60ff02199091166a010000000000000000000017166b010000000000000000000000179055341561004657600080fd5b6040516020806133cd8339810160405280805160018054600160a060020a03191633600160a060020a03169081179091559092508291507fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9460405160405180910390a26004805467ffffffffffffffff9092166101000268ffffffffffffffff0019909216919091179055506132ec806100e16000396000f30060606040526004361061024d5763ffffffff60e060020a60003504166301492a0b81146102525780630374fc6f146102795780630621b4f6146102b057806307da68f5146102dc578063093f5198146102f157806313af403514610328578063144a27521461034757806315e287001461036f5780631aa859d0146103945780631b33d412146103b95780631d834a1b146103e8578063232cae0b146104015780632aed19051461041457806340e58ee51461042c5780634579268a14610442578063467f0b7b1461048c57806349606455146104a2578063511fa487146104c4578063557ed1ba146104e357806361f54a79146105135780636377ebca14610529578063677170e11461053c57806374c1d7d31461056157806375f12b2114610586578063779997c3146105995780637a9e5e4b146105af5780637ca9429a146105ce5780638185402b146105f357806382afd23b1461061f5780638a72ea6a146106355780638af82a2e146106985780638d7daf95146106ab5780638da5cb5b146106d0578063911550f4146106ff57806391be90c814610715578063943911bc1461073457806396d7a9ed1461074a578063a78d431614610760578063b4f9b6c814610776578063bf7c734e1461078c578063bf7e214f146107ae578063c2b6b58c146107c1578063c2d526aa146107d4578063c41a360a1461080e578063d2b420ce14610824578063d6f154691461083a578063d6febde814610852578063e1a6f0141461086b578063f09ea2a61461089f578063f582d293146108cb578063ff1fd974146108de575b600080fd5b341561025d57600080fd5b610265610906565b604051901515815260200160405180910390f35b341561028457600080fd5b61029e600160a060020a036004358116906024351661091e565b60405190815260200160405180910390f35b34156102bb57600080fd5b61029e600160a060020a03600435811690602435906044351660643561094b565b34156102e757600080fd5b6102ef610a90565b005b34156102fc57600080fd5b61029e600160a060020a03600435811690602435166001608060020a0360443581169060643516610ad2565b341561033357600080fd5b6102ef600160a060020a0360043516610afb565b341561035257600080fd5b61029e600160a060020a0360043581169060243516604435610b6d565b341561037a57600080fd5b610265600160a060020a0360043581169060243516610c39565b341561039f57600080fd5b610265600160a060020a0360043581169060243516610d9a565b34156103c457600080fd5b61029e600435600160a060020a036024358116906044359060643516608435610f15565b34156103f357600080fd5b610265600435602435610fe6565b341561040c57600080fd5b61029e611070565b341561041f57600080fd5b6102656004351515611076565b341561043757600080fd5b610265600435611109565b341561044d57600080fd5b6104586004356111bc565b604051938452600160a060020a03928316602085015260408085019290925290911660608301526080909101905180910390f35b341561049757600080fd5b6102656004356111f2565b34156104ad57600080fd5b6102ef6004356001608060020a03602435166112b3565b34156104cf57600080fd5b61029e600160a060020a03600435166112d5565b34156104ee57600080fd5b6104f66112f0565b60405167ffffffffffffffff909116815260200160405180910390f35b341561051e57600080fd5b61029e6004356112f4565b341561053457600080fd5b6104f6611306565b341561054757600080fd5b61029e600160a060020a036004358116906024351661131b565b341561056c57600080fd5b61029e600160a060020a0360043581169060243516611338565b341561059157600080fd5b610265611355565b34156105a457600080fd5b6102ef60043561136b565b34156105ba57600080fd5b6102ef600160a060020a03600435166114b5565b34156105d957600080fd5b61029e600160a060020a0360043581169060243516611527565b34156105fe57600080fd5b61029e600160a060020a036004358116906024359060443516606435611552565b341561062a57600080fd5b61026560043561167c565b341561064057600080fd5b61064b6004356116a3565b604051958652600160a060020a0394851660208701526040808701949094529184166060860152909216608084015267ffffffffffffffff90911660a083015260c0909101905180910390f35b34156106a357600080fd5b61029e6116f5565b34156106b657600080fd5b610265600160a060020a03600435811690602435166116fb565b34156106db57600080fd5b6106e3611798565b604051600160a060020a03909116815260200160405180910390f35b341561070a57600080fd5b61029e6004356117a7565b341561072057600080fd5b61029e600160a060020a03600435166117b9565b341561073f57600080fd5b61029e6004356117cb565b341561075557600080fd5b6102656004356117e0565b341561076b57600080fd5b61029e6004356117f5565b341561078157600080fd5b6102ef600435611807565b341561079757600080fd5b610265600160a060020a036004351660243561181e565b34156107b957600080fd5b6106e3611904565b34156107cc57600080fd5b610265611913565b34156107df57600080fd5b6107ea60043561195a565b60405180848152602001838152602001828152602001935050505060405180910390f35b341561081957600080fd5b6106e360043561197b565b341561082f57600080fd5b610265600435611999565b341561084557600080fd5b6102656004351515611a0a565b341561085d57600080fd5b610265600435602435611a9b565b341561087657600080fd5b61029e600435600160a060020a03602435811690604435906064351660843560a4351515611afc565b34156108aa57600080fd5b61029e600435600160a060020a036024358116906044359060643516611c22565b34156108d657600080fd5b610265611d00565b34156108e957600080fd5b61029e600160a060020a0360043581169060243516604435611d17565b6004546b010000000000000000000000900460ff1681565b600160a060020a038083166000908152600660209081526040808320938516835292905220545b92915050565b60008060005b6000861115610a7957610964858861091e565b915081151561097257600080fd5b6000828152600360205260409020600281015490546109919190611dd0565b86670de0b6b3a76400000210156109a757610a79565b6000828152600360205260409020600201548610610a1b576000828152600360205260409020546109d9908490611e01565b6000838152600360205260409020600201549093506109f9908790611e11565b600083815260036020526040902054909650610a169083906112b3565b610a74565b60008281526003602052604090208054600290910154633b9aca0091610a4d9189840291610a4891611e21565b611e3d565b811515610a5657fe5b049050610a638382611e01565b9250610a6f82826112b3565b600095505b610951565b83831015610a8657600080fd5b5050949350505050565b610aa633600035600160e060020a031916611e6d565b1515610ab157600080fd5b6004805469ff00000000000000000019166901000000000000000000179055565b6000610af2836001608060020a031686846001608060020a031687611c22565b95945050505050565b610b1133600035600160e060020a031916611e6d565b1515610b1c57600080fd5b60018054600160a060020a031916600160a060020a038381169190911791829055167fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9460405160405180910390a250565b600080610b7a858561091e565b90505b600081815260036020526040902060020154831115610bf757600081815260036020526040902054610bb0908390611e01565b600082815260036020526040902060020154909250610bd0908490611e11565b92506000831115610bf257610be4816117cb565b9050801515610bf257600080fd5b610b7d565b60008181526003602052604090208054600290910154610af2918491633b9aca0091610c2a9188840291610a4891611e21565b811515610c3357fe5b04611e01565b6000610c5133600035600160e060020a031916611e6d565b1515610c5c57600080fd5b600435602435808233600160a060020a031660008035600160e060020a0319169034903660405183815260406020820181815290820183905260608201848480828437820191505094505050505060405180910390a4610cbc85856116fb565b15610cc657600080fd5b600160a060020a03851615801590610ce65750600160a060020a03841615155b1515610cf157600080fd5b6001600a60008787604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040908101600020805460ff1916921515929092179091557f4b84ee81b11f5c5a33aaf2f3bdc5a35f23156c1b3cbefdbd00ba84846c19044b908690869051600160a060020a039283168152911660208201526040908101905180910390a1506001949350505050565b6000610db233600035600160e060020a031916611e6d565b1515610dbd57600080fd5b600435602435808233600160a060020a031660008035600160e060020a0319169034903660405183815260406020820181815290820183905260608201848480828437820191505094505050505060405180910390a4610e1d85856116fb565b1515610e2857600080fd5b600a60008686604051606060020a600160a060020a0393841681028252919092160260148201526028016040519081900390208152602081019190915260409081016000908120805460ff19169055600a918690889051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040908101600020805460ff191690557f80eb6b7f03b2ffa03a2dda3ce0c7db2b44d4bda32c071d3508a817321cd327d6908690869051600160a060020a039283168152911660208201526040908101905180910390a1506001949350505050565b60008483600a60008383604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff1680610fae5750600a60008284604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff165b1515610fb957600080fd5b610fc1611913565b15610fcb57600080fd5b610fda88888888886000611afc565b98975050505050505050565b6000610ff183611999565b15610ffb57600080fd5b6110048361167c565b151561100f57600080fd5b61101883611f64565b50611023838361200c565b7f6d5c16212bdea16850dce4d9fa2314c446bd30ce84700d9c36c7677c6d2839403384604051600160a060020a03909216825260208201526040908101905180910390a150600192915050565b60025481565b600061108e33600035600160e060020a031916611e6d565b151561109957600080fd5b600480546bff000000000000000000000019166b010000000000000000000000841515810291909117918290557fea11e00ec1642be9b494019b756440e2c57dbe9e59242c4f9c64ce33fb4f41d99160ff91900416604051901515815260200160405180910390a1506001919050565b6000816111158161167c565b151561112057600080fd5b611128611913565b8061114c57506111378161197b565b600160a060020a031633600160a060020a0316145b151561115757600080fd5b6004546b010000000000000000000000900460ff16156111ac5761117a83611999565b1561119857611188836121e8565b151561119357600080fd5b6111ac565b6111a183611f64565b15156111ac57600080fd5b6111b5836123a9565b9392505050565b600090815260036020819052604090912080546001820154600283015492909301549093600160a060020a039384169390911690565b60006111fd8261167c565b15801561121a575060008281526005602052604090206002015415155b801561123b5750600082815260056020526040902060020154600919430190105b151561124657600080fd5b60008281526005602052604080822082815560018101839055600201919091557fcb9d6176c6aac6478ebb9a2754cdce22a944de29ed1f2642f8613884eba4b40c903390849051600160a060020a03909216825260208201526040908101905180910390a1506001919050565b6112c6826001608060020a038316611a9b565b15156112d157600080fd5b5050565b600160a060020a031660009081526008602052604090205490565b4290565b60009081526009602052604090205490565b600454610100900467ffffffffffffffff1681565b600760209081526000928352604080842090915290825290205481565b600660209081526000928352604080842090915290825290205481565b6004546901000000000000000000900460ff1681565b6000816113778161167c565b151561138257600080fd5b61138a611913565b1561139457600080fd5b600083815260036020819052604091829020600481015460018201549190920154869550600160a060020a039283169391831692169051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020600084815260036020819052604091829020600181015491810154815460028301546004909301548a957f70a14c213064359ede031fd2a1645a11ce2ec825ffe6ab5cfb5b160c3ef4d0a295600160a060020a03908116959416939160a060020a900467ffffffffffffffff169051600160a060020a0395861681529390941660208401526001608060020a039182166040808501919091529116606083015267ffffffffffffffff909216608082015260a001905180910390a4505050565b6114cb33600035600160e060020a031916611e6d565b15156114d657600080fd5b60008054600160a060020a031916600160a060020a038381169190911791829055167f1abebea81bfa2637f28358c371278fb15ede7ea8dd28d2e03b112ff6d936ada460405160405180910390a250565b600160a060020a03918216600090815260076020908152604080832093909416825291909152205490565b6000805b600085111561166657611569868561091e565b905080151561157757600080fd5b600081815260036020526040902080546002909101546115979190611dd0565b85670de0b6b3a76400000210156115ad57611666565b600081815260036020526040902054851061161e576000818152600360205260409020600201546115df908390611e01565b6000828152600360205260409020549092506115fc908690611e11565b6000828152600360205260409020549095506116199082906112b3565b611661565b600081815260036020526040902060028101549054611650918491633b9aca0091610c2a918a840291610a4891611e21565b915061165c81866112b3565b600094505b611556565b8282111561167357600080fd5b50949350505050565b60009081526003602052604081206004015460a060020a900467ffffffffffffffff161190565b6003602081905260009182526040909120805460018201546002830154938301546004909301549193600160a060020a039182169390929082169181169060a060020a900467ffffffffffffffff1686565b600b5490565b6000600a60008484604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff16806111b55750600a60008385604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff169392505050565b600154600160a060020a031681565b60009081526005602052604090205490565b60086020526000908152604090205481565b60009081526005602052604090206001015490565b600a6020526000908152604090205460ff1681565b60096020526000908152604090205481565b61181081611109565b151561181b57600080fd5b50565b600061183633600035600160e060020a031916611e6d565b151561184157600080fd5b600435602435808233600160a060020a031660008035600160e060020a0319169034903660405183815260406020820181815290820183905260608201848480828437820191505094505050505060405180910390a4600160a060020a038516600090815260086020526040908190208590557fc28d56449b0bb31e64ee7487e061f57a2e72aea8019d810832f26dda099823d0908690869051600160a060020a03909216825260208201526040908101905180910390a1506001949350505050565b600054600160a060020a031681565b6004546000906901000000000000000000900460ff16806119555750600454610100900467ffffffffffffffff166119496112f0565b67ffffffffffffffff16115b905090565b60056020526000908152604090208054600182015460029092015490919083565b600090815260036020526040902060040154600160a060020a031690565b6000818152600560205260408120541515806119c5575060008281526005602052604090206001015415155b8061094557505060008181526003602081815260408084206001810154600160a060020a03908116865260068452828620919094015490931684529190529020541490565b6000611a2233600035600160e060020a031916611e6d565b1515611a2d57600080fd5b600480546aff0000000000000000000019166a0100000000000000000000841515810291909117918290557f7089e4f0bcc948f9f723a361590c32d9c2284da7ab1981b1249ad2edb9f953c19160ff91900416604051901515815260200160405180910390a1506001919050565b600061328983611aaa8161167c565b1515611ab557600080fd5b611abd611913565b15611ac757600080fd5b6004546b010000000000000000000000900460ff16611ae85761266e611aec565b612ade5b9150610af285858463ffffffff16565b60008584600a60008383604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff1680611b955750600a60008284604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff165b1515611ba057600080fd5b611ba8611913565b15611bb257600080fd5b600160a060020a03881660009081526008602052604090205489901115611bd857600080fd5b6004546b010000000000000000000000900460ff1615611c0757611c00898989898989612b4f565b9250611c16565b611c1389898989612c92565b92505b50509695505050505050565b60006132898483600a60008383604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff1680611cbe5750600a60008284604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020815260208101919091526040016000205460ff165b1515611cc957600080fd5b6004546b010000000000000000000000900460ff16611cea57612c92611cee565b612ff85b9250610fda888888888763ffffffff16565b6004546a0100000000000000000000900460ff1681565b600080611d24848661091e565b90505b600081815260036020526040902054831115611d9e57600081815260036020526040902060020154611d5a908390611e01565b600082815260036020526040902054909250611d77908490611e11565b92506000831115611d9957611d8b816117cb565b9050801515611d9957600080fd5b611d27565b600081815260036020526040902060028101549054610af2918491633b9aca0091610c2a9188840291610a4891611e21565b600081611df0611de885670de0b6b3a7640000613084565b600285610c33565b811515611df957fe5b049392505050565b8082018281101561094557600080fd5b8082038281111561094557600080fd5b600081611df0611de8856b033b2e3c9fd0803ce8000000613084565b60006b033b2e3c9fd0803ce8000000611df0611e598585613084565b60026b033b2e3c9fd0803ce8000000610c33565b600030600160a060020a031683600160a060020a03161415611e9157506001610945565b600154600160a060020a0384811691161415611eaf57506001610945565b600054600160a060020a03161515611ec957506000610945565b60008054600160a060020a03169063b7009613908590309086906040516020015260405160e060020a63ffffffff8616028152600160a060020a039384166004820152919092166024820152600160e060020a03199091166044820152606401602060405180830381600087803b1515611f4257600080fd5b6102c65a03f11515611f5357600080fd5b505050604051805190509050610945565b600b5460009080611f7484611999565b15611f7e57600080fd5b83600b541415611fa55760008481526009602052604081208054600b555560019250612005565b5b600082118015611fb65750838214155b15611fd1575060008181526009602052604090205490611fa6565b818414611fe15760009250612005565b60008481526009602052604080822080548484529183209190915585825255600192505b5050919050565b600080600061201a8561167c565b151561202557600080fd5b600085815260036020819052604090912090810154600190910154600160a060020a039182169450169150831580612063575061206184611999565b155b1561207857612071856130ac565b9350612103565b6120828585613135565b935083158015906120ee57506000858152600360205260408082206001908101548784529190922090910154600160a060020a0390811691161415806120ee5750600085815260036020819052604080832082015487845292200154600160a060020a03908116911614155b156121035760009350612100856130ac565b93505b831561212f5750600083815260056020526040808220600101805490879055868352912084905561215c565b50600160a060020a0381811660009081526006602090815260408083209386168352929052208054908590555b80156121805760008181526005602052604080822087905586825290206001018190555b600160a060020a0380831660009081526007602090815260408083209387168352929052819020805460010190557f20fb9bad86c18f7e22e8065258790d9416a7d2df8ff05f80f82c46d38b925acd9086905190815260200160405180910390a15050505050565b600081815260036020818152604080842092830154600190930154600160a060020a039081168086526007845282862091909416808652925283205490919083901161223357600080fd5b600084815260056020526040902060020154158015612256575061225684611999565b151561226157600080fd5b600160a060020a0380821660009081526006602090815260408083209386168352929052205484146122d45760008481526005602052604080822054825290206001015484146122b057600080fd5b6000848152600560205260408082206001808201549154845291909220015561230a565b600084815260056020908152604080832060010154600160a060020a038086168552600684528285209087168552909252909120555b6000848152600560205260409020600101541561236157600084815260056020526040808220600101548252902054841461234457600080fd5b600084815260056020526040808220805460019091015483529120555b600160a060020a039081166000908152600760209081526040808320949093168252928352818120805460001901905593845260059091529091204360029091015550600190565b60006123b361328b565b826123bd8161167c565b15156123c857600080fd5b6123d0611913565b806123f457506123df8161197b565b600160a060020a031633600160a060020a0316145b15156123ff57600080fd5b60045460ff161561240f57600080fd5b6004805460ff19166001179055600084815260036020526040908190209060c09051908101604090815282548252600180840154600160a060020a0390811660208086019182526002808801548688015260038089015485166060890152600498890154948516608089015260a060020a90940467ffffffffffffffff1660a088015260008c8152918490529481208181559384018054600160a060020a03199081169091559484015590820180549093169092559092018054600160e060020a0319169055925051600160a060020a031663a9059cbb8360800151845160006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561253957600080fd5b6102c65a03f1151561254a57600080fd5b50505060405180519050151561255f57600080fd5b7fa2c251311b1a7a475913900a2a73dc9789a21b04bc737e050bbc506dd4eb34888460405190815260200160405180910390a18160800151600160a060020a031682602001518360600151604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020857f9577941d28fff863bfbee4694a6a4a56fb09e169619189d2eaa750b5b4819995602086015186606001518751886040015142604051600160a060020a0395861681529390941660208401526001608060020a039182166040808501919091529116606083015267ffffffffffffffff909216608082015260a001905180910390a450506004805460ff19169055506001919050565b600061267861328b565b6000846126848161167c565b151561268f57600080fd5b612697611913565b156126a157600080fd5b60045460ff16156126b157600080fd5b6004805460ff19166001179055600086815260036020526040908190209060c090519081016040908152825482526001830154600160a060020a039081166020840152600284015491830191909152600383015481166060830152600490920154918216608082015260a060020a90910467ffffffffffffffff1660a082015292508251612743868560400151613084565b81151561274c57fe5b0491506001608060020a038216821461276457600080fd5b6001608060020a038516851461277957600080fd5b841580612784575081155b8061278f5750825185115b8061279d5750826040015182115b156127ab5760009350612acb565b6127b6835186611e11565b60008781526003602052604090819020919091556127d79084015183611e11565b6000878152600360205260409020600201556060830151600160a060020a03166323b872dd3385608001518560006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561285b57600080fd5b6102c65a03f1151561286c57600080fd5b50505060405180519050151561288157600080fd5b8260200151600160a060020a031663a9059cbb338760006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156128e257600080fd5b6102c65a03f115156128f357600080fd5b50505060405180519050151561290857600080fd5b7fa2c251311b1a7a475913900a2a73dc9789a21b04bc737e050bbc506dd4eb34888660405190815260200160405180910390a133600160a060020a03168360800151600160a060020a031684602001518560600151604051606060020a600160a060020a0393841681028252919092160260148201526028016040519081900390207f3383e3357c77fd2e3a4b30deea81179bc70a795d053d14d5b7f2f01d0fd4596f89602088015188606001518b8942604051958652600160a060020a039485166020870152929093166040808601919091526001608060020a0391821660608601529216608084015267ffffffffffffffff1660a083015260c0909101905180910390a48260600151600160a060020a03168360200151600160a060020a03167f819e390338feffe95e2de57172d6faf337853dfd15c7a09a32d76f7fd2443875878560405191825260208201526040908101905180910390a36000868152600360205260409020541515612ac65760008681526003602081905260408220828155600181018054600160a060020a0319908116909155600282019390935590810180549092169091556004018054600160e060020a03191690555b600193505b50506004805460ff191690555092915050565b6004546000906a0100000000000000000000900460ff161515612b0057600080fd5b60008381526003602052604090205482148015612b215750612b2183611999565b15612b3157612b2f836121e8565b505b612b3b838361266e565b1515612b4657600080fd5b50600192915050565b60008060008060005b600160a060020a038089166000908152600660209081526040808320938e168352929052908120541115612c57575050600160a060020a038087166000908152600660209081526040808320938c168352928152828220548083526003909152919020600281015490549193509085612bd2576000612bda565b808b8a840101015b612be48c83613084565b01612bef838b613084565b1115612bfa57612c57565b612c0d84612c08838c613214565b611a9b565b50889250612c2489612c1f838c613214565b611e11565b985082612c318a8d613084565b811515612c3a57fe5b049a508a1580612c48575088155b15612c5257612c57565b612b58565b600089118015612c67575060008b115b15612c8457612c788b8b8b8b612c92565b9450612c84858861200c565b505050509695505050505050565b6000612c9c61328b565b612ca4611913565b15612cae57600080fd5b60045460ff1615612cbe57600080fd5b6004805460ff191660011790556001608060020a0386168614612ce057600080fd5b6001608060020a0384168414612cf557600080fd5b60008611612d0257600080fd5b600160a060020a0385161515612d1757600080fd5b60008411612d2457600080fd5b600160a060020a0383161515612d3957600080fd5b600160a060020a038581169084161415612d5257600080fd5b858152600160a060020a0380861660208301526040820185905283811660608301523316608082015267ffffffffffffffff421660a0820152612d9361322b565b60008181526003602052604090209092508190815181556020820151600182018054600160a060020a031916600160a060020a0392909216919091179055604082015181600201556060820151600382018054600160a060020a031916600160a060020a03929092169190911790556080820151600482018054600160a060020a031916600160a060020a039290921691909117905560a08201516004909101805467ffffffffffffffff9290921660a060020a027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff90921691909117905550600160a060020a0385166323b872dd33308960006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515612edd57600080fd5b6102c65a03f11515612eee57600080fd5b505050604051805190501515612f0357600080fd5b7fa2c251311b1a7a475913900a2a73dc9789a21b04bc737e050bbc506dd4eb34888260405190815260200160405180910390a133600160a060020a03168584604051606060020a600160a060020a039384168102825291909216026014820152602801604051908190039020837f773ff502687307abfa024ac9f62f9752a0d210dac2ffd9a29e38e12e2ea82c8288878b8a42604051600160a060020a0395861681529390941660208401526001608060020a039182166040808501919091529116606083015267ffffffffffffffff909216608082015260a001905180910390a4506004805460ff19169055949350505050565b600160a060020a0383166000908152600860205260408120548590111561301e57600080fd5b61302a85858585612c92565b600b80546000838152600960205260409081902091909155908290559091507f8173832a493e0a3989e521458e55bfe9feac9f9b675a94e100b9d5a85f8148629082905190815260200160405180910390a1949350505050565b60008115806130a157505080820282828281151561309e57fe5b04145b151561094557600080fd5b6000808080808086116130be57600080fd5b505050600083815260036020818152604080842092830154600190930154600160a060020a039081168086526006845282862091909416808652925283205490935090915b811580159061311757506131178683613239565b15610af2575060008181526005602052604090206001015490613103565b60008080841161314457600080fd5b821580159061315957506131578361167c565b155b15613177576000928352600560205260409092206001015491613144565b82151561318e57613187846130ac565b915061320d565b6131988484613239565b156131d8575b82158015906131b257506131b28484613239565b156131d057506000828152600560205260409020600101549161319e565b80915061320d565b82158015906131ee57506131ec8484613239565b155b156132095760009283526005602052604090922054916131d8565b8291505b5092915050565b60008183111561322457816111b5565b5090919050565b600280546001019081905590565b600081815260036020526040808220600201548483529082205461325d9190613084565b600084815260036020526040808220600201548583529120546132809190613084565b10159392505050565bfe5b60c06040519081016040908152600080835260208301819052908201819052606082018190526080820181905260a0820152905600a165627a7a7230582095afc05b2e23665dee009f71c5171aa6e967666958dd65c039ad9fbf5c4294120029000000000000000000000000000000000000000000000000000000005c2d09fd


   Swarm Source:
bzzr://95afc05b2e23665dee009f71c5171aa6e967666958dd65c039ad9fbf5c429412
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward